PHP::表のセルを配列に入れ込む。

今まで集大成(かも)。
結論から言うとできたのかもしれない。

PHPの配列は結構いい加減なところ*1があるので、逆にそれを利用させてもらいました。

今回サンプルにした表は次の通り。

+-----+-----+-----+-----+-----+-----+-----+-----+-----+
| 0-0 |           |                 |     |     | 0-8 |
+-----+           +                 + 0-6 + 0-7 +-----+
| 1-0 |           | 0-3             |     |     | 1-8 |
+-----+           +                 +-----+-----+-----+
| 2-0 | 0-1       |                 |           | 2-8 |
+-----+           +-----+-----+-----+           +-----+
| 3-0 |           | 3-3 | 3-4       | 2-6       | 3-8 |
+-----+           +-----+-----+-----+           +-----+
| 4-0 |           | 4-3             |           | 4-8 |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+

たぶんこれで表を作るあらゆる場面を含んでいると思う。(何か足り気がするけど・・・)

この表のHTMLが次のようになるわな(一部省略)

...
        <tr>
            <td>テスト0-0</td>
            <td rowspan="5" colspan="2">テスト0-1</td>
            <td rowspan="3" colspan="3">テスト0-3</td>
            <td rowspan="2">テスト0-6</td>
            <td rowspan="2">テスト0-7</td>
            <td>テスト0-8</td>
        </tr>
        <tr>
            <td>テスト1-0</td>
            <td>テスト1-8</td>
        </tr>
        <tr>
            <td>テスト2-0</td>
            <td rowspan="3" colspan="2">テスト2-6</td>
            <td>テスト2-8</td>
        </tr>
        <tr>
            <td>テスト3-0</td>
            <td>テスト3-3</td>
            <td colspan="2">テスト3-4</td>
            <td>テスト3-8</td>
        </tr>
        <tr>
            <td>テスト4-0</td>
            <td colspan="3">テスト4-3</td>
            <td>テスト4-8</td>
        </tr>
...

見た目とHTMLとしてのデータとでは各行におけるセルの数が異なるんだよねぇ・・・。

まぁ、まずは各行、各列ごとに処理するため、次を前提としてその次の処理をする。

$table[2][$tbl]	-> 上のHTML(最初の<tr>〜最後の</tr>までの部分)
<?php
...
$rc		= array(array());
$cell		= array(array());
$count_tr	= preg_match_all("/$reg_tr/u", $table[2][$tbl], $tr_array);
for ($tr=0; $tr < $count_tr; $tr++) {
	$new_rowspan		= 0;	// 新規rowspanの個数
	$existent_rowspan	= 0;	// 既存rowspanの個数
	$now_cell		= 0;	// 今現在の(データとしての)セルの番号
	$true_row		= 0;	// 本来(見た目)の列番号
	$before_cell		= 0;
	
	$count_td = preg_match_all("/$reg_td/u", $tr_array[1][$tr], $td_array);
	
	/* 
	 * $tr行目を
	 * $count_td + $sum_rowspan(新規と既存の和) 回す
	 */
	for ($td=0; $td < $count_td + $sum_rowspan; $td++) {
		// 新規のrowspanを監視
		$count_row = preg_match("/$reg_row/u", $td_array[1][$now_cell], $row_array);
		
		/* 
		 * 新規のrowspanがあった場合
		 *     1. rowspanの値を-1したものを$rowに代入
		 *     2. $new_rowspanを+1する
		 *     3. 今のセル番号が前のセル番号と同じ場合
		 *            3-1. $new_rowspanを-1する
		 *     4. $before_cellに今のセル番号を代入する
		 * 
		 * なかった場合
		 *     1. $rowを0にする
		 */
		if ( $count_row ) {
			$row = $row_array[1] - 1;
			//バグがあったため修正
			//if ( $before_cell != 0 )
			//	if ( $before_cell == $now_cell)
			//		$new_rowspan -= 1;
			if ($td_num != 0 && $before_cell == $now_cell)
				$new_rowspan--;
			$new_rowspan++;
			$before_cell = $now_cell;
		} else
			$row = 0;
		// 新規のcolspanを監視
		$count_col = preg_match("/$reg_col/u", $td_array[1][$now_cell], $col_array);
		
		/* 
		 * 新規のcolspanがあった場合
		 *     1. colspanの値を$colに代入
		 * 
		 * なかった場合
		 *     1. $colを1にする
		 */
		if ( $count_col )
			$col = $col_array[1];
		else
			$col = 1;
		
		// 1行目でなければ以下の処理をする
		if ( $tr != 0 )
			preg_match("/$reg_irc/u", $rc[$tr - 1][$true_row], $rc_array);
		
		/*
		 * 1行目
		 * もしくは
		 * 前の行で同じ列のrowspanの値が0
		 * の場合
		 *     1. rcに[rowspanの値]:[colspanの値]で代入
		 *     2. cellに該当するセルのデータを代入
		 *     3. $now_cellを1増やす→データとしてのセルの番号を次に移行する
		 *     4. 本来の列番号に$colを足して次の本来の列番号にする
		 * 
		 * 違う場合→主にrowspanの値が0じゃない場合
		 *     1. 次の行でのrowspanの値を$next_rowに代入
		 *     2. rcに[$next_row]:[前の行でのcolspanの値]で代入
		 *     3. cellには" "(空白)を代入(もしかしたら""(空)でもいいのかな?)
		 *     4. 本来の列番号に前の行でのcolspanの値を足して次の本来の列番号にする
		 */
		if ( $tr == 0 || $rc_array[1] == 0 ) {
			$rc[$tr][$true_row]	= $row . ":" . $col;
			$cell[$tr][$true_row]	= $td_array[2][$now_cell];
			$now_cell++;
			$true_row += $col;
		} else {
			$next_row = $rc_array[1] - 1;
			$rc[$tr][$true_row]	= $next_row . ":" . $rc_array[2];
			$cell[$tr][$true_row]	= " ";
			$true_row += $rc_array[2];
		}
		
		/*
		 * $next_rowが0じゃない場合→つまり既存のrowspanがあった場合
		 *     1. $existent_rowspanを+1する
		 *     2. $next_rowを初期化(0)にする
		 */
		if ( $next_row != 0 ) {
			$existent_rowspan += 1;
			$next_row	   = 0;
		}
	}
}
...
?>

で、サンプルの表で試したところ、次のようになった。

Array                     Array
(                         (
    [0] => Array           [0] => Array
         (                     (
            [0] => 0:1                [0] => 0-0
            [1] => 4:2                [1] => 0-1
            [3] => 2:3                [3] => 0-3
            [6] => 1:1                [6] => 0-6
            [7] => 1:1                [7] => 0-7
            [8] => 0:1                [8] => 0-8
         )                     )
    [1] => Array           [1] => Array
         (                     (
            [0] => 0:1                [0] => 1-0
            [1] => 3:2                [1] =>  
            [3] => 1:3                [3] =>  
            [6] => 0:1                [6] =>  
            [7] => 0:1                [7] =>  
            [8] => 0:1                [8] => 1-8
         )                     )
    [2] => Array           [2] => Array
         (                     (
            [0] => 0:1                [0] => 2-0
            [1] => 2:2                [1] =>  
            [3] => 0:3                [3] =>  
            [6] => 2:2                [6] => 2-6
            [8] => 0:1                [8] => 2-8
         )                     )
    [3] => Array           [3] => Array
         (                     (
            [0] => 0:1                [0] => 3-0
            [1] => 1:2                [1] =>  
            [3] => 0:1                [3] => 3-3
            [4] => 0:2                [4] => 3-4
            [6] => 1:2                [6] =>  
            [8] => 0:1                [8] => 3-8
         )                     )
    [4] => Array           [4] => Array
         (                     (
            [0] => 0:1                [0] => 4-0
            [1] => 0:2                [1] =>  
            [3] => 0:3                [3] => 4-3
            [6] => 0:2                [6] =>  
            [8] => 0:1                [8] => 4-8
         )                     )
)                         )

何とか意図したとおりになってくれてありがたい。

後はこれを元にTeXへ書換えていこう。rowspanが0じゃなかったらcline使うとかね。

くそう、時間かかったなぁ・・・。


余談

時間かかったけどこっちの方がソース綺麗。

前のやつ驚くほど汚かった。

*1:全ての行で列の数が違っても良いとか色々