diff --git a/changelog.md b/changelog.md
index 3b3bad3df..2cdda8f1f 100644
--- a/changelog.md
+++ b/changelog.md
@@ -23,3 +23,4 @@
 * Use Django REST framework status code constants instead of integers.
 * Added long text field.
 * Fixed not refreshing token bug and improved authentication a little bit.
+* Introduced copy, paste and delete functionality of selected fields.
diff --git a/web-frontend/modules/database/components/view/grid/GridViewField.vue b/web-frontend/modules/database/components/view/grid/GridViewField.vue
index 5db34855d..2b6c91148 100644
--- a/web-frontend/modules/database/components/view/grid/GridViewField.vue
+++ b/web-frontend/modules/database/components/view/grid/GridViewField.vue
@@ -13,6 +13,7 @@
 
 <script>
 import { isElement } from '@baserow/modules/core/utils/dom'
+import { copyToClipboard } from '@baserow/modules/database/utils/clipboard'
 
 export default {
   name: 'GridViewField',
@@ -105,37 +106,75 @@ export default {
         }
         document.body.addEventListener('click', this.$el.clickOutsideEvent)
 
-        // If the tab or arrow keys are pressed we want to select the next field. This
-        // is however out of the scope of this component so we emit the selectNext
-        // event that the GridView can handle.
-        this.$el.keyPressedNextFieldEvent = (event) => {
-          // We will first ask if we can select the next field. If that is not allowed
-          // we don't do anything.
-          if (!this.$refs.field.canSelectNext(event)) {
-            return
-          }
-
-          const { keyCode } = event
+        // Event that is called when a key is pressed while the field is selected.
+        this.$el.keyDownEvent = (event) => {
+          // If the tab or arrow keys are pressed we want to select the next field. This
+          // is however out of the scope of this component so we emit the selectNext
+          // event that the GridView can handle.
+          const { keyCode, ctrlKey, metaKey } = event
           const arrowKeysMapping = {
             37: 'selectPrevious',
             38: 'selectAbove',
             39: 'selectNext',
             40: 'selectBelow',
           }
-          if (Object.keys(arrowKeysMapping).includes(keyCode.toString())) {
+          if (
+            Object.keys(arrowKeysMapping).includes(keyCode.toString()) &&
+            this.$refs.field.canSelectNext(event)
+          ) {
             event.preventDefault()
             this.$emit(arrowKeysMapping[keyCode])
           }
-
-          if (keyCode === 9) {
+          if (keyCode === 9 && this.$refs.field.canSelectNext(event)) {
             event.preventDefault()
             this.$emit(event.shiftKey ? 'selectPrevious' : 'selectNext')
           }
+
+          // Copies the value to the clipboard if ctrl/cmd + c is pressed.
+          if (
+            (ctrlKey || metaKey) &&
+            keyCode === 67 &&
+            this.$refs.field.canCopy(event)
+          ) {
+            const rawValue = this.row['field_' + this.field.id]
+            const value = this.$registry
+              .get('field', this.field.type)
+              .prepareValueForCopy(this.field, rawValue)
+            copyToClipboard(value)
+          }
+
+          // Removes the value if the backspace/delete key is pressed.
+          if (
+            (keyCode === 46 || keyCode === 8) &&
+            this.$refs.field.canEmpty(event)
+          ) {
+            event.preventDefault()
+            const value = this.$registry
+              .get('field', this.field.type)
+              .getEmptyValue(this.field)
+            const oldValue = this.row['field_' + this.field.id]
+            if (value !== oldValue) {
+              this.update(value, oldValue)
+            }
+          }
         }
-        document.body.addEventListener(
-          'keydown',
-          this.$el.keyPressedNextFieldEvent
-        )
+        document.body.addEventListener('keydown', this.$el.keyDownEvent)
+
+        // Updates the value of the field when a user pastes something in the field.
+        this.$el.pasteEvent = (event) => {
+          if (!this.$refs.field.canPaste(event)) {
+            return
+          }
+
+          const value = this.$registry
+            .get('field', this.field.type)
+            .prepareValueForPaste(this.field, event.clipboardData)
+          const oldValue = this.row['field_' + this.field.id]
+          if (value !== oldValue) {
+            this.update(value, oldValue)
+          }
+        }
+        document.addEventListener('paste', this.$el.pasteEvent)
 
         // Emit the selected event so that the parent component can take an action like
         // making sure that the element fits in the viewport.
@@ -152,11 +191,10 @@ export default {
         this.selected = false
       })
       document.body.removeEventListener('click', this.$el.clickOutsideEvent)
-      document.body.removeEventListener(
-        'keydown',
-        this.$el.keyPressedNextFieldEvent
-      )
+      document.body.removeEventListener('keydown', this.$el.keyDownEvent)
+      document.removeEventListener('paste', this.$el.pasteEvent)
     },
   },
 }
 </script>
+gl
diff --git a/web-frontend/modules/database/fieldTypes.js b/web-frontend/modules/database/fieldTypes.js
index efcf75d78..dc1156c1e 100644
--- a/web-frontend/modules/database/fieldTypes.js
+++ b/web-frontend/modules/database/fieldTypes.js
@@ -116,6 +116,24 @@ export class FieldType extends Registerable {
   toHumanReadableString(field, value) {
     return value
   }
+
+  /**
+   * This hook is called before the field's value is copied to the clipboard.
+   * Optionally formatting can be done here. By default the value is always
+   * converted to a string.
+   */
+  prepareValueForCopy(field, value) {
+    return value.toString()
+  }
+
+  /**
+   * This hook is called before the field's value is overwritten by the clipboard
+   * data. That data might needs to be prepared so that the field accepts it.
+   * By default the text value if the clipboard data is used.
+   */
+  prepareValueForPaste(field, clipboardData) {
+    return clipboardData.getData('text')
+  }
 }
 
 export class TextFieldType extends FieldType {
@@ -194,6 +212,36 @@ export class NumberFieldType extends FieldType {
   getRowEditFieldComponent() {
     return RowEditFieldNumber
   }
+
+  /**
+   * First checks if the value is numeric, if that is the case, the number is going
+   * to be formatted.
+   */
+  prepareValueForPaste(field, clipboardData) {
+    const value = clipboardData.getData('text')
+    if (isNaN(parseFloat(value)) || !isFinite(value)) {
+      return null
+    }
+    return this.constructor.formatNumber(field, value)
+  }
+
+  /**
+   * Formats the value based on the field's settings. The number will be rounded
+   * if to much decimal places are provided and if negative numbers aren't allowed
+   * they will be set to 0.
+   */
+  static formatNumber(field, value) {
+    if (value === '' || isNaN(value) || value === undefined || value === null) {
+      return null
+    }
+    const decimalPlaces =
+      field.number_type === 'DECIMAL' ? field.number_decimal_places : 0
+    let number = parseFloat(value)
+    if (!field.number_negative && number < 0) {
+      number = 0
+    }
+    return number.toFixed(decimalPlaces)
+  }
 }
 
 export class BooleanFieldType extends FieldType {
@@ -220,4 +268,14 @@ export class BooleanFieldType extends FieldType {
   getEmptyValue(field) {
     return false
   }
+
+  /**
+   * Check if the clipboard data text contains a string that might indicate if the
+   * value is true.
+   */
+  prepareValueForPaste(field, clipboardData) {
+    const value = clipboardData.getData('text').toLowerCase()
+    const allowed = ['1', 'y', 't', 'y', 'yes', 'true', 'on']
+    return allowed.includes(value)
+  }
 }
diff --git a/web-frontend/modules/database/mixins/gridField.js b/web-frontend/modules/database/mixins/gridField.js
index 1b38ad9b0..70cf8a7ee 100644
--- a/web-frontend/modules/database/mixins/gridField.js
+++ b/web-frontend/modules/database/mixins/gridField.js
@@ -56,5 +56,31 @@ export default {
     canSelectNext() {
       return true
     },
+    /**
+     * If the user presses ctrl/cmd + c while a field is selected, the value is
+     * going to be copied to the clipboard. In some cases, for example when the user
+     * is editing the value, we do not want to copy the value. If false is returned
+     * the value won't be copied.
+     */
+    canCopy() {
+      return true
+    },
+    /**
+     * If the user presses ctrl/cmd + v while a field is selected, the value is
+     * overwritten with the data of the clipboard. In some cases, for example when the
+     * user is editing the value, we do not want to change the value. If false is
+     * returned the value won't be changed.
+     */
+    canPaste() {
+      return true
+    },
+    /**
+     * If the user presses delete or backspace while a field is selected, the value is
+     * deleted. In some cases, for example when the user is editing the value, we do
+     * not want to delete the value. If false is returned the value won't be changed.
+     */
+    canEmpty() {
+      return true
+    },
   },
 }
diff --git a/web-frontend/modules/database/mixins/gridFieldInput.js b/web-frontend/modules/database/mixins/gridFieldInput.js
index b0c00972b..f00414e35 100644
--- a/web-frontend/modules/database/mixins/gridFieldInput.js
+++ b/web-frontend/modules/database/mixins/gridFieldInput.js
@@ -163,5 +163,14 @@ export default {
     canSaveByPressingEnter(event) {
       return true
     },
+    canCopy() {
+      return !this.editing
+    },
+    canPaste() {
+      return !this.editing
+    },
+    canEmpty() {
+      return !this.editing
+    },
   },
 }
diff --git a/web-frontend/modules/database/mixins/numberField.js b/web-frontend/modules/database/mixins/numberField.js
index 3fc719e8c..eeeb2eb3e 100644
--- a/web-frontend/modules/database/mixins/numberField.js
+++ b/web-frontend/modules/database/mixins/numberField.js
@@ -1,3 +1,5 @@
+import { NumberFieldType } from '@baserow/modules/database/fieldTypes'
+
 /**
  * This mixin contains some method overrides for validating and formatting the
  * number field. This mixin is used in both the GridViewFieldNumber and
@@ -21,28 +23,11 @@ export default {
       return this.getError() === null
     },
     /**
-     * Formats the value based on the field's settings. The number will be rounded
-     * if to much decimal places are provided and if negative numbers aren't allowed
-     * they will be set to 0.
+     * Before the numeric value is saved we might need to do some formatting such that
+     * the value is conform the fields requirements.
      */
     beforeSave(value) {
-      if (
-        value === '' ||
-        isNaN(value) ||
-        value === undefined ||
-        value === null
-      ) {
-        return null
-      }
-      const decimalPlaces =
-        this.field.number_type === 'DECIMAL'
-          ? this.field.number_decimal_places
-          : 0
-      let number = parseFloat(value)
-      if (!this.field.number_negative && number < 0) {
-        number = 0
-      }
-      return number.toFixed(decimalPlaces)
+      return NumberFieldType.formatNumber(this.field, value)
     },
   },
 }
diff --git a/web-frontend/modules/database/utils/clipboard.js b/web-frontend/modules/database/utils/clipboard.js
new file mode 100644
index 000000000..f661b8e90
--- /dev/null
+++ b/web-frontend/modules/database/utils/clipboard.js
@@ -0,0 +1,17 @@
+/**
+ * Copies the given text to the clipboard by temporarily creating a textarea and
+ * using the documents `copy` command.
+ */
+export const copyToClipboard = (text) => {
+  const textarea = document.createElement('textarea')
+  document.body.appendChild(textarea)
+
+  textarea.style.position = 'absolute'
+  textarea.style.left = '-99999px'
+  textarea.style.top = '-99999px'
+  textarea.value = text
+  textarea.select()
+
+  document.execCommand('copy')
+  document.body.removeChild(textarea)
+}