diff --git a/tablefield.module b/tablefield.module
index 0b8751c..063afe0 100644
--- a/tablefield.module
+++ b/tablefield.module
@@ -481,6 +481,7 @@ function tablefield_field_widget_form(&$form, &$form_state, $field, $instance, $
   $ajax_wrapper_id = "$id-wrapper";
   $rebuild_id = "$id-rebuild";
   $import_id = "$id-import";
+  $pasted_id = "$id-pasted";
 
   // Default table size.
   $default_size['count_cols'] = isset($instance['default_value'][0]['tablefield']['rebuild']['count_cols']) ? $instance['default_value'][0]['tablefield']['rebuild']['count_cols'] : 5;
@@ -503,6 +504,15 @@ function tablefield_field_widget_form(&$form, &$form_state, $field, $instance, $
       tablefield_import_csv($form, $form_state, $langcode, $import_id, $tablefield_parents);
       $default_value = drupal_array_get_nested_value($form_state['input'], $tablefield_parents);
     }
+    elseif ($form_state['triggering_element']['#name'] == $pasted_id) {
+      // Importing pasted data
+      tablefield_import_pasted($form, $form_state, $langcode, $pasted_id, $tablefield_parents);
+      $default_value = drupal_array_get_nested_value($form_state['input'], $tablefield_parents);
+      if (empty($default_value['rebuild'])) {
+        $default_value['rebuild'] = $default_size;
+      }
+      $default_value = tablefield_rationalize_table($default_value);
+    }
     else {
       // The triggering element is neither a rebuild nor an import
       // e.g. a file upload.
@@ -689,7 +699,7 @@ function tablefield_field_widget_form(&$form, &$form_state, $field, $instance, $
   $element['tablefield']['import'] = array(
     '#type' => 'fieldset',
     '#tree' => TRUE,
-    '#title' => t('Import from CSV'),
+    '#title' => t('Upload CSV file'),
     '#collapsible' => TRUE,
     '#collapsed' => TRUE,
   );
@@ -698,7 +708,6 @@ function tablefield_field_widget_form(&$form, &$form_state, $field, $instance, $
     '#title' => t('File upload'),
     '#type' => 'file',
   );
-
   $element['tablefield']['import']['import'] = array(
     '#type' => 'button',
     '#validate' => array(),
@@ -717,6 +726,70 @@ function tablefield_field_widget_form(&$form, &$form_state, $field, $instance, $
     ),
   );
 
+  // Allow user to paste data (e.g. from Excel)
+  $element['tablefield']['paste'] = array(
+    '#type' => 'fieldset',
+    '#tree' => TRUE,
+    '#title' => t('Copy & Paste (e.g. from Excel)'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+  );
+  $delimiters = array(
+    'TAB' => 'TAB',
+    ',' => 'Comma ,',
+    ';' => 'Semicolon ;',
+    '|' => 'Pipe |',
+    '+' => 'Plus +',
+    ':' => 'Colon :',
+  );
+  $element['tablefield']['paste']['paste_delimiter'] = array(
+    '#type' => 'select',
+    '#tree' => TRUE,
+    '#title' => t('Column separator'),
+    '#name' => 'delimiter[' . $pasted_id . ']',
+    '#options' => $delimiters,
+    '#description' => t('Data copied from Excel will use TAB.', array('!delimiter' => $delimiters)),
+  );
+  $element['tablefield']['paste']['data'] = array(
+    '#type' => 'textarea',
+    '#tree' => TRUE,
+    '#name' => 'data[' . $pasted_id . ']',
+    '#title' => t('Table data'),
+  );
+
+  $element['tablefield']['paste']['paste_import'] = array(
+    '#type' => 'button',
+    '#validate' => array(),
+    '#limit_validation_errors' => array(),
+    '#executes_submit_callback' => TRUE,
+    '#submit' => array('tablefield_rebuild_form'),
+    '#value' => t('Import Data'),
+    '#name' => $pasted_id,
+    '#attributes' => array(
+      'class' => array('tablefield-rebuild'),
+    ),
+    '#ajax' => array(
+      'callback' => 'tablefield_rebuild_form_ajax',
+      'wrapper' => $ajax_wrapper_id,
+      'effect' => 'fade',
+    ),
+  );
+
+  // Provide caption field to describe the data contained in the table.
+  $caption = '';
+  if (isset($items[$delta]['value'])) {
+    $raw = unserialize($items[$delta]['value']);
+    if (isset($raw['caption'])) {
+      $caption = $raw['caption'];
+    }
+  }
+  $element['tablefield']['caption'] = array(
+    '#title' => t('Table description'),
+    '#description' => t('This brief caption will be associated with the table and will help Assitive Technology, like screen readers, better describe the content within.'),
+    '#type' => 'textfield',
+    '#default_value' => isset($caption) ? $caption : ''
+  );
+
   // Allow the user to select input filters.
   if (!empty($field['settings']['cell_processing'])) {
     $element['#base_type'] = $element['#type'];
@@ -779,6 +852,56 @@ function tablefield_import_csv($form, &$form_state, $langcode, $file_form_field_
 }
 
 /**
+ * Helper function to import pasted data
+ * @param array $form
+ * @param array $form_state
+ * @param string $langcode
+ * @param string $file_form_field_name
+ * @param array $tablefield_parents
+ */
+function tablefield_import_pasted($form, &$form_state, $langcode, $pasted_form_field_name, $tablefield_parents) {
+
+  $data = $form_state['input']['data'][$pasted_form_field_name];
+  if (!empty($data)) {
+    tablefield_delete_table_values(drupal_array_get_nested_value($form_state['values'], $tablefield_parents));
+    tablefield_delete_table_values(drupal_array_get_nested_value($form_state['input'], $tablefield_parents));
+
+    // Get the rows:
+    $rows = explode(PHP_EOL, $data);
+    $col_delimiter = $form_state['input']['delimiter'][$pasted_form_field_name];
+    if ($col_delimiter == 'TAB') {
+      $col_delimiter = "\t";
+    }
+
+    // Populate table values:
+    $max_col_count = 0;
+    $row_count = 0;
+    $imported_tablefield = array();
+    foreach ($rows as $row_id => $row) {
+      // Explode the current row into columns:
+      $cols = explode($col_delimiter, $row);
+      $col_count = count($cols);
+      if ($col_count > 0) {
+        foreach ($cols as $col_id => $col) {
+          $imported_tablefield['cell_' . $row_count . '_' . $col_id] = $col;
+        }
+        $max_col_count = $col_count > $max_col_count ? $col_count : $max_col_count;
+        $row_count++;
+      }
+    }
+
+    $imported_tablefield['rebuild'] = array('count_cols' => $max_col_count, 'count_rows' => $row_count);
+    drupal_array_set_nested_value($form_state['values'], $tablefield_parents, $imported_tablefield);
+    drupal_array_set_nested_value($form_state['input'], $tablefield_parents, $imported_tablefield);
+
+    drupal_set_message(t('Successfully imported pasted data.'));
+  }
+  else {
+    drupal_set_message(t('There was a problem importing pasted.'));
+  }
+}
+
+/**
  * Helper function to remove all values in a particular table.
  *
  * @param array $tablefield
@@ -853,11 +976,12 @@ function tablefield_rationalize_table($tablefield) {
     $count_rows = $tablefield['rebuild']['count_rows'];
     unset($tablefield['rebuild']);
     unset($tablefield['import']);
+    unset($tablefield['paste']);
 
     foreach ($tablefield as $key => $value) {
       preg_match('/cell_(.*)_(.*)/', $key, $cell);
       // $cell[1] is row count $cell[2] is col count.
-      if ((int) $cell[1] < $count_rows && (int) $cell[2] < $count_cols) {
+      if (!empty($cell) && (int) $cell[1] < $count_rows && (int) $cell[2] < $count_cols) {
         $tabledata[$cell[1]][$cell[2]] = $value;
       }
     }
