Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I'm looking to modify a table on a page to include merged rows.

Here is the php code that deals with the output from a mysql db:

######## PRINT OUT TABLE WITH YEARS AND OFFICES PLUS NAMES IN CELLS ########    
for ($y = $year_max; $y >=$year_min; $y--){
    echo '<tr><th>'.$y.'</th>';

    for ($i = 0; $i<count($offices_used); $i++){

        if (isset($data[$y][$offices_used[$i]])){
            echo '<td>'.$data[$y][$offices_used[$i]].'</td>';
        } // END IF

        else {
            echo '<td></td>';
        } // END ELSE

        }   echo '</tr>';
    } // END FOR 

The table further below is generated from a multidimensional array such as immediately below;

array (  

[2013] => Array
    (
        [President] => John Mills
        [Internal VP] => Virgil Bagdonas
        [External VP] => Reid Gilmore
        [Treasurer] => Todd Heino
        [Secretary] => Eric Holmquist
        [Newsletter] => Art Bodwell
        [Webmaster] => Dave Eaton
        [Photographer] => Rick Angus
        [Video Librarian] => Mike Peters
        [Store Manager] => Kevin Nee
    )

[2012] => Array
    (
        [President] => Dave Eaton
        [Internal VP] => Jim Metcalf
        [External VP] => Reid Gilmore
        [Treasurer] => Mike Peters
        [Secretary] => Eric Holmquist
        [Newsletter] => Art Bodwell
        [Webmaster] => Dave Eaton
        [Photographer] => Peter Wilcox
        [Video Librarian] => Ray Asselin
        [Store Manager] => Joe Giroux
    )

[2011] => Array
    (
        [President] => Charlie Croteau
        [Internal VP] => Reid Gilmore
        [External VP] => Rick Angus
        [Treasurer] => Mike Peters
        [Secretary] => Eric Holmquist
        [Newsletter] => Ron Rocheleau
        [Webmaster] => Dave Eaton
        [Photographer] => Peter Wilcox
        [Video Librarian] => Ray Asselin
        [Book Librarian] => Roger Boisvert
        [Store Manager] => Mike Smith
    )

...etc

My php code NOW generates this table from mysql db:

<tr>
    <th>Year</th>
    <th>President</th>
    <th>Internal VP</th>
    <th>External VP</th>
    <th>Treasurer</th>
    <th>Secretary</th>
    <th>Webmaster</th>
    <th>Newsletter</th>
    <th>Photographer</th>
    <th>Video Librarian</th>
    <th>Book Librarian</th>
    <th>Store Manager</th>
</tr>

<tr>
    <th>2013</th>
    <td>John Mills</td>
    <td>Virgil Bagdonas</td>
    <td>Reid Gilmore</td>
    <td>Todd Heino</td>
    <td>Eric Holmquist</td>
    <td>Dave Eaton</td>
    <td>Art Bodwell</td>
    <td>Rick Angus</td>
    <td>Mike Peters</td>
    <td></td>
    <td>Kevin Nee</td>
</tr>
<tr>
    <th>2012</th>
    <td>Dave Eaton</td>
    <td>Jim Metcalf</td>
    <td>Reid Gilmore</td>
    <td>Mike Peters</td>
    <td>Eric Holmquist</td>
    <td>Dave Eaton</td>
    <td>Art Bodwell</td>
    <td>Peter Wilcox</td>
    <td>Ray Asselin</td>
    <td></td>
    <td>Joe Giroux</td>
</tr>
<tr>
    <th>2011</th>
    <td>Charlie Croteau</td>
    <td>Reid Gilmore</td>
    <td>Rick Angus</td>
    <td>Mike Peters</td>
    <td>Eric Holmquist</td>
    <td>Dave Eaton</td>
    <td>Ron Rocheleau</td>
    <td>Peter Wilcox</td>
    <td>Ray Asselin</td>
    <td>Roger Boisvert</td>
    <td>Mike Smith</td>
</tr>

But I WOULD LIKE to modify the array handling output to get the following:

<tr>
    <th>Year</th>
    <th>President</th>
    <th>Internal VP</th>
    <th>External VP</th>
    <th>Treasurer</th>
    <th>Secretary</th>
    <th>Webmaster</th>
    <th>Newsletter</th>
    <th>Photographer</th>
    <th>Video Librarian</th>
    <th>Book Librarian</th>
    <th>Store Manager</th>
</tr>
<tr>
    <th>2013</th>
    <td>John Mills</td>
    <td>Virgil Bagdonas</td>
    <td rowspan= "3">Reid Gilmore</td>
    <td>Todd Heino</td>
    <td rowspan="3">Eric Holmquist</td>
    <td rowspan="9">Dave Eaton</td>
    <td rowspan="2">Art Bodwell</td>
    <td>Rick Angus</td>
    <td>Mike Peters</td>
    <td></td>
    <td>Kevin Nee</td>
</tr>
<tr>
    <th>2012</th>
    <td>Dave Eaton</td>
    <td>Jim Metcalf</td>
    <td rowspan="2">Mike Peters</td>
    <td>Peter Wilcox</td>
    <td rowspan="3">Ray Asselin</td>
    <td></td>
    <td>Joe Giroux</td>
</tr>
<tr>
    <th>2011</th>
    <td>Charlie Croteau</td>
    <td>Rick Angus</td>
    <td>Ron Rocheleau</td>
    <td>Peter Wilcox</td>
    <td>Roger Boisvert</td>
    <td>Mike Smith</td>
</tr>

Any leads on how to add a flag or counter to accomplish this is welcome. Thanks!

share|improve this question
    
ok Please check my answer. –  imsiso May 25 '13 at 15:34
    
I think you mean colspan.check this. –  imsiso May 25 '13 at 15:36

3 Answers 3

up vote 0 down vote accepted

try this hope to work.(because I have not run it but think should work).

CODE for colspan:

for ($y = $year_max; $y >=$year_min; $y--){
    echo '<tr><th>'.$y.'</th>';

    $lastVal='';
    $buf=array();
    for ($i = 0; $i<count($offices_used); $i++){
        (!isset($data[$y][$offices_used[$i]])?($data[$y][$offices_used[$i]]=''):'');// Im not sure that is really needed

        if($lastVal==$data[$y][$offices_used[$i]]){
            $buf[count($buf)-1]['rep']++;
        }else{
            $lastVal=$data[$y][$offices_used[$i]];
            $buf[]=array('data'=>$lastVal,'rep'=>1);
        }

        foreach($buf as $arr){
            echo '<td'.($arr['rep']>1?' colspan="'.$arr['rep'].'"':'') . '>'.$arr['data'].'</td>';
        }


        }   echo '</tr>';
    } // END FOR 

NOTICE: error of code corrected


CODE for rowspan:(I think it can be down easier than this. bur I have tried to be good).

$buf=array();
for ($i = 0; $i<count($offices_used); $i++){// this loop makes fill $buf
    $lastVal='';
    for ($y = $year_max; $y >=$year_min; $y--){
        (!isset($data[$y][$offices_used[$i]])?($data[$y][$offices_used[$i]]=''):'');// Im not sure that is really needed
        if($lastVal==$data[$y][$offices_used[$i]]){
            $buf[$i][count($buf[$i])-1]['rep']++;
        }else{
            $lastVal=$data[$y][$offices_used[$i]];
            $buf[$i][$year_max-$y]=array('data'=>$lastVal,'rep'=>1);
        }
    }
}
$mtemp=$year_max;
foreach($buf as $row){
    echo '<tr><th>'.$mtemp.'</th>';
    foreach($row as $rec){
        echo '<td'.($rec['rep']>1?' rowspan="'.$rec['rep'].'"':'') . '>'.$rec['data'].'</td>';
    }
    $mtemp--;
    echo '</tr>';
}

really hope to work.

NOTICE: corrected

share|improve this answer
    
Maybe almost but not yet. I think I grasp the concept. Thank you. Here's what I want at: cnew.org/cnew_officer-history-sample-merged-rows.html and what I get implementing your suggestion at: cnew.org/officer-history-mergerow.php –  eaton9999 May 25 '13 at 15:43
    
I cant open your page can you paste the HTML out put of them as jsfiddle? –  imsiso May 25 '13 at 15:46
    
new = jsfiddle.net/eaton9999/JLfZR/1 –  eaton9999 May 25 '13 at 15:50
    
this link is for which of them? new?? –  imsiso May 25 '13 at 15:52
    
It is implementing what you provided. –  eaton9999 May 25 '13 at 15:54

Solved by using:

############################################################################
######## PRINT OUT TABLE WITH YEARS AND OFFICES PLUS NAMES IN CELLS ########    
for ($y = $year_max; $y >=$year_min; $y--){ // Loop through years
    echo '<tr><th>'.$y.'</th>';

    for ($i = 0; $i<count($offices_used); $i++){

        if (isset($data[$y][$offices_used[$i]])){

            $rowz =1;


            if(!($data[$y][$offices_used[$i]] == $data[($y+1)][$offices_used[$i]])){

                while ($data[$y][$offices_used[$i]] == $data[($y-$rowz)][$offices_used[$i]]) $rowz ++; 
                echo '<td rowspan = "'.$rowz.'">'.$data[$y][$offices_used[$i]].'</td>';
            }

        } // END IF

        else {
            echo '<td align = "center"> - </td>';
        } // END ELSE

        }   echo '</tr>';  // End row of current year

} // END FOR Loop through years 
echo '</table>';

See http://jsfiddle.net/eaton9999/8gMVK/ for resultant output page.

Thanks again to imsiso and other who helped!

share|improve this answer

I wrote a library a few days ago that can handle this stuff..
Have a look at https://github.com/donquixote/cellbrush

The benefit of the library is that you don't need to think about the order of cells in html, and which cells need to be skipped due to rowspan or colspan. Instead, you can just "paint" a cell anywhere in the grid, with whichever rowspan or colspan you want. And instead of specifying a number for rowspan or colspan, you simply specify the first and last row and column names of the rospan/colspan region.

E.g.

$table->td(['2011', '2013'], 'Secretary', 'Eric Holmquist');

Below is some code that creates the table you were asking for, with the help of this library. You still need some logic to calculate the intervals, but at least you don't need to worry about the integrity of the table html.

(This question is quite old, but there might still be people running into it from Google. So I hope it might be useful.)

<?php

require_once __DIR__ . '/vendor/autoload.php';

$data = array(
  '2013' => array(
    'President' => 'John Mills',
    'Internal VP' => 'Virgil Bagdonas',
    'External VP' => 'Reid Gilmore',
    'Treasurer' => 'Todd Heino',
    'Secretary' => 'Eric Holmquist',
    'Newsletter' => 'Art Bodwell',
    'Webmaster' => 'Dave Eaton',
    'Photographer' => 'Rick Angus',
    'Video Librarian' => 'Mike Peters',
    'Store Manager' => 'Kevin Nee',
  ),
  '2012' => array(
    'President' => 'Dave Eaton',
    'Internal VP' => 'Jim Metcalf',
    'External VP' => 'Reid Gilmore',
    'Treasurer' => 'Mike Peters',
    'Secretary' => 'Eric Holmquist',
    'Newsletter' => 'Art Bodwell',
    'Webmaster' => 'Dave Eaton',
    'Photographer' => 'Peter Wilcox',
    'Video Librarian' => 'Ray Asselin',
    'Store Manager' => 'Joe Giroux',
  ),
  '2011' => array(
    'President' => 'Charlie Croteau',
    'Internal VP' => 'Reid Gilmore',
    'External VP' => 'Rick Angus',
    'Treasurer' => 'Mike Peters',
    'Secretary' => 'Eric Holmquist',
    'Newsletter' => 'Ron Rocheleau',
    'Webmaster' => 'Dave Eaton',
    'Photographer' => 'Peter Wilcox',
    'Video Librarian' => 'Ray Asselin',
    'Book Librarian' => 'Roger Boisvert',
    'Store Manager' => 'Mike Smith',
  ),
);

// Collect positions to build table columns.
$positions = [];
foreach ($data as $year => $yearData) {
  foreach ($yearData as $position => $person) {
    $positions[$position] = TRUE;
  }
}
$positions = array_keys($positions);

// Define table columns.
$table = (new \Donquixote\Cellbrush\Table())
  ->addColName('year')
  ->addColNames($positions)
;

// Create thead section.
$headRow = $table->thead()->addRow('head');
$headRow->th('year', 'Year');
foreach ($positions as $position) {
  $headRow->th($position, $position);
}

// Create table rows with labels based on year.
$years = array_keys($data);
$table->addRowNames($years);
foreach ($years as $year) {
  $table->th($year, 'year', $year);
}

// Fill table cells in each column.
foreach ($positions as $position) {
  $periodPerson = NULL;
  $periodFirstYear = NULL;
  $periodLastYear = NULL;
  $column = $table->colHandle($position);
  foreach ($years as $year) {
    $person = isset($data[$year][$position])
      ? $data[$year][$position]
      : '-';
    if (!isset($periodFirstYear)) {
      // First year.
      $periodFirstYear = $year;
    }
    elseif ($person !== $periodPerson) {
      // Add a table cell with rowspan.
      $column->td([$periodFirstYear, $periodLastYear], $periodPerson);
      $periodFirstYear = $year;
    }
    $periodPerson = $person;
    $periodLastYear = $year;
  }
  if (isset($periodFirstYear)) {
    // Add a table cell with rowspan.
    $column->td([$periodFirstYear, $periodLastYear], $periodPerson);
  }
}

print $table->render();
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.