diff --git a/includes/webform.report.inc b/includes/webform.report.inc
index 75188a9..d72d087 100644
--- a/includes/webform.report.inc
+++ b/includes/webform.report.inc
@@ -180,8 +180,9 @@ function webform_results_table($node, $pager_count = 0) {
   $header = theme('webform_results_table_header', array('node' => $node));
   $submissions = webform_get_submissions($node->nid, $header, $pager_count);
   $total_count = webform_get_submission_count($node->nid);
+  $extra_data = webform_results_get_extra_data($submissions);
 
-  $output = theme('webform_results_table', array('node' => $node, 'components' => $node->webform['components'], 'submissions' => $submissions, 'total_count' => $total_count, 'pager_count' => $pager_count));
+  $output = theme('webform_results_table', array('node' => $node, 'components' => $node->webform['components'], 'submissions' => $submissions, 'extra_data' => $extra_data, 'total_count' => $total_count, 'pager_count' => $pager_count));
   if ($pager_count) {
     $output .= theme('pager');
   }
@@ -217,6 +218,7 @@ function theme_webform_results_table($variables) {
   $node = $variables['node'];
   $components = $variables['components'];
   $submissions = $variables['submissions'];
+  $extra_data = $variables['extra_data'];
   $total_count = $variables['total_count'];
   $pager_count = $variables['pager_count'];
 
@@ -246,6 +248,14 @@ function theme_webform_results_table($variables) {
       }
     }
 
+    // Generate cells for extra data.
+    if (isset($extra_data[$sid]) && is_array($extra_data[$sid])) {
+      foreach ($extra_data[$sid] as $key => $value) {
+        $component_headers[] = check_plain($key);
+        $cell[] = check_plain($value);
+      }
+    }
+
     $rows[] = $cell;
     unset($cell);
   }
@@ -790,6 +800,8 @@ function webform_results_export_batch($node, $format = 'delimited', $options = a
 function webform_results_download_headers($node, $options) {
   module_load_include('inc', 'webform', 'includes/webform.components');
   $submission_information = webform_results_download_submission_information($node, $options);
+  $submissions = webform_results_download_get_submissions($node, $options);
+  $extra_data = webform_results_get_extra_data($submissions);
 
   // Fill in the header for the submission information (if any).
   $header[2] = $header[1] = $header[0] = count($submission_information) ? array_fill(0, count($submission_information), '') : array();
@@ -827,6 +839,17 @@ function webform_results_download_headers($node, $options) {
     }
   }
 
+  // Add extra data row headers.
+  foreach ($submissions as $sid => $submission) {
+    if (isset($extra_data[$sid]) && is_array($extra_data[$sid])) {
+      foreach ($extra_data[$sid] as $label => $data) {
+        $header[0][] = '';
+        $header[1][] = '';
+        $header[2][] = $label;
+      }
+    }
+  }
+
   return $header;
 }
 
@@ -849,17 +872,9 @@ function webform_results_download_headers($node, $options) {
 function webform_results_download_rows($node, $options, $serial_start = 0) {
   module_load_include('inc', 'webform', 'includes/webform.components');
 
-  // Get all the required submissions for the download.
-  $filters['nid'] = $node->nid;
-  if (!empty($options['sids'])){
-    $filters['sid'] = $options['sids'];
-  }
-  elseif (!empty($options['completion_type']) && $options['completion_type'] !== 'all') {
-    $filters['is_draft'] = (int) ($options['completion_type'] === 'draft');
-  }
-
-  $submissions = webform_get_submissions($filters, NULL);
+  $submissions = webform_results_download_get_submissions($node, $options);
   $submission_information = webform_results_download_submission_information($node, $options);
+  $extra_data = webform_results_get_extra_data($submissions);
 
   // Generate a row for each submission.
   $row_count = 0;
@@ -917,6 +932,13 @@ function webform_results_download_rows($node, $options, $serial_start = 0) {
       }
     }
 
+    // Add extra data rows.
+    if (isset($extra_data[$sid]) && is_array($extra_data[$sid])) {
+      foreach ($extra_data[$sid] as $data) {
+        $row[] = $data;
+      }
+    }
+
     $rows[$serial_start + $row_count] = $row;
   }
 
@@ -1591,3 +1613,64 @@ function webform_download_latest_start_sid($nid, $latest_count, $completion_type
   $latest_sids = $query->execute()->fetchCol();
   return min($latest_sids);
 }
+
+/**
+ * Retrieve additional data for a set of submissions.
+ *
+ * @param array $submissions
+ *  An array of webform submission objects.
+ *
+ * @return array
+ *  An array of additional info keyed by submission id.
+ */
+function webform_results_get_extra_data(array $submissions) {
+  $extra_data = &drupal_static(__FUNCTION__, array());
+  $unknown = array();
+
+  foreach ($submissions as $submission) {
+    if (!isset($extra_data[$submission->sid])) {
+      $unknown[$submission->sid] = $submission;
+      // Initialize this value.
+      $extra_data[$submission->sid] = array();
+    }
+  }
+  if ($unknown) {
+    // array_merge_recursive makes impossible for hook implementations to return
+    // data keyed by submission id.
+    foreach (module_implements('webform_results_extra_data') as $module) {
+      $result = module_invoke($module, 'webform_results_extra_data', $unknown);
+      foreach ($result as $sid => $data) {
+        $extra_data[$sid] = array_merge($extra_data[$sid], $data);
+      }
+    }
+  }
+
+  return $extra_data;
+}
+
+/**
+ * Get all the required submissions for the download.
+ *
+ * @param stdClass $node
+ *   A node object.
+ * @param array $options
+ *   An array of download options.
+ *
+ * @return array
+ *  An array of submissions keyed by sid.
+ *
+ * @see webform_get_submissions()
+ */
+function webform_results_download_get_submissions(stdClass $node, array $options) {
+  module_load_include('inc', 'webform', 'includes/webform.submissions');
+
+  $filters['nid'] = $node->nid;
+  if (!empty($options['sids'])) {
+    $filters['sid'] = $options['sids'];
+  }
+  elseif (!empty($options['completion_type']) && $options['completion_type'] !== 'all') {
+    $filters['is_draft'] = (int) ($options['completion_type'] === 'draft');
+  }
+
+  return webform_get_submissions($filters, NULL);
+}
diff --git a/webform.api.php b/webform.api.php
index 9adddcf..3aee635 100644
--- a/webform.api.php
+++ b/webform.api.php
@@ -643,6 +643,27 @@ function hook_webform_results_access($node, $account) {
 }
 
 /**
+ * Provide additional data for a set of webform submissions.
+ *
+ * @see webform_results_get_extra_data().
+ *
+ * @param array $submissions
+ *   An array of submission objects.
+ *
+ * @return array
+ *   An array of additional info array keyed by submission id. Each info array
+ *   key will be used as label when displaying and the value as value.
+ */
+function hook_webform_results_extra_data(array $submissions) {
+  // Give a random value to each submission.
+  $data = array();
+  foreach ($submissions as $submission) {
+    $data[$submission->sid] = array(t('Random') => rand(0, 10));
+  }
+  return $data;
+}
+
+/**
  * Return an array of files associated with the component.
  *
  * The output of this function will be used to attach files to e-mail messages.
diff --git a/webform.module b/webform.module
index 9e30e9b..e7f39c0 100644
--- a/webform.module
+++ b/webform.module
@@ -781,7 +781,7 @@ function webform_theme() {
       'file' => 'includes/webform.report.inc',
     ),
     'webform_results_table' => array(
-      'variables' => array('node' => NULL, 'components' => NULL, 'submissions' => NULL, 'node' => NULL, 'total_count' => NULL, 'pager_count' => NULL),
+      'variables' => array('node' => NULL, 'components' => NULL, 'submissions' => NULL, 'extra_data' => NULL, 'node' => NULL, 'total_count' => NULL, 'pager_count' => NULL),
       'file' => 'includes/webform.report.inc',
     ),
     'webform_results_download_range' => array(
