diff --git a/includes/form.inc b/includes/form.inc
index 72362a0..9aa91fe 100644
--- a/includes/form.inc
+++ b/includes/form.inc
@@ -3275,7 +3275,21 @@ function theme_tableselect($variables) {
       // As theme_table only maps header and row columns by order, create the
       // correct order by iterating over the header fields.
       foreach ($element['#header'] as $fieldname => $title) {
-        $row['data'][] = $element['#options'][$key][$fieldname];
+        // A row cell can span over multiple headers, which means less row cells
+        // than headers could be present.
+        if (isset($element['#options'][$key][$fieldname])) {
+          // A header can span over multiple cells and in this case the cells
+          // are passed in an array. The order of this array determines the
+          // order in which they are added.
+          if (!isset($element['#options'][$key][$fieldname]['data']) && is_array($element['#options'][$key][$fieldname])) {
+            foreach ($element['#options'][$key][$fieldname] as $cell) {
+              $row['data'][] = $cell;
+            }
+          }
+          else {
+            $row['data'][] = $element['#options'][$key][$fieldname];
+          }
+        }
       }
       $rows[] = $row;
     }
diff --git a/modules/simpletest/tests/form.test b/modules/simpletest/tests/form.test
index ec7df2c..191f206 100644
--- a/modules/simpletest/tests/form.test
+++ b/modules/simpletest/tests/form.test
@@ -723,7 +723,6 @@ class FormsElementsTableSelectFunctionalTest extends DrupalWebTestCase {
     parent::setUp('form_test');
   }
 
-
   /**
    * Test the display of checkboxes when #multiple is TRUE.
    */
@@ -759,6 +758,31 @@ class FormsElementsTableSelectFunctionalTest extends DrupalWebTestCase {
     }
   }
 
+   /**
+   * Tests the display when #colspan is set.
+   */
+  function testTableselectColSpan() {
+    $this->drupalGet('form_test/tableselect/colspan');
+
+    $this->assertText(t('Three'), 'Presence of the third column');
+    $this->assertNoText(t('Four'), 'Absence of a fourth column');
+
+    // There should be three labeled column headers and 1 for the input.
+    $table_head = $this->xpath('//thead');
+    $this->assertEqual(count($table_head[0]->tr->th), 4, 'There are four column headers');
+
+    $table_body = $this->xpath('//tbody');
+    // The first two body rows should each have 5 table cells: One for the
+    // radio, one cell in the first column, one cell in the the second column,
+    // and two cells in the third column which has colspan 2.
+    for ( $i = 0; $i <= 1; $i) {
+      $this->assertEqual(count($table_body[0]->tr[$i]->td), 5, format_string('There are five cells in row @row.', array('@row' => $i)));
+    }
+    // The third row should have 3 cells, one for the radio, one spanning the
+    // first and second column, and a third in column 3 (which has colspan 3).
+    $this->assertEqual(count($table_body[0]->tr[2]->td), 3, 'There are three cells in row 3.');
+  }
+
   /**
    * Test the display of the #empty text when #options is an empty array.
    */
diff --git a/modules/simpletest/tests/form_test.module b/modules/simpletest/tests/form_test.module
index 1c16c39..90969da 100644
--- a/modules/simpletest/tests/form_test.module
+++ b/modules/simpletest/tests/form_test.module
@@ -52,6 +52,13 @@ function form_test_menu() {
     'access arguments' => array('access content'),
     'type' => MENU_CALLBACK,
   );
+  $items['form_test/tableselect/colspan'] = array(
+    'title' => 'Tableselect colspan test',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('_form_test_tableselect_colspan_form'),
+    'access callback' => TRUE,
+    'type' => MENU_CALLBACK,
+  );
   $items['form_test/tableselect/empty-text'] = array(
     'title' => 'Tableselect empty text test',
     'page callback' => 'drupal_get_form',
@@ -558,6 +565,29 @@ function _form_test_tableselect_multiple_false_form($form, $form_state) {
   return _form_test_tableselect_form_builder($form, $form_state, array('#multiple' => FALSE));
 }
 
+ /**
+ * Test the tableselect #colspan functionality.
+ */
+function _form_test_tableselect_colspan_form($form, $form_state) {
+  list($header, $options) = _form_test_tableselect_get_data();
+
+  // Change the data so that the third column has colspan=2.
+  $header['three'] = array('data' => 'Three', 'colspan' => 2);
+  unset($header['four']);
+  // Set the each row so that column 3 is an array.
+  foreach ($options as $name => $row) {
+    $options[$name]['three'] = array($row['three'], $row['four']);
+    unset($options[$name]['four']);
+  }
+  // Combine cells in row 3.
+  $options['row3']['one'] = array('data' => $options['row3']['one'], 'colspan' => 2);
+  unset($options['row3']['two']);
+  $options['row3']['three'] = array('data' => $options['row3']['three'][0], 'colspan' => 2);
+  unset($options['row3']['four']);
+
+  return _form_test_tableselect_form_builder($form, $form_state, array('#header' => $header, '#options' => $options));
+}
+
 /**
  * Process the tableselect #multiple = FALSE submitted values.
  */
