英文:
Add nested table into word by phpword library and DOM object
问题
我有一个完整的HTML文本,需要相应地转换为phpword,并最终添加到Word中。
HTML代码是:
$html = '<table style="height:500px;width:600px;"><thead><tr><th>Lor<strong>em</strong></th><th colspan="2"><p>ipsum</p><p>dolr</p></th></tr></thead><tbody><tr><td colspan="2"><table><tbody><tr><td>1</td><td>2</td><td>3</td></tr><tr><td>4</td><td>5</td><td>6</td></tr></tbody></table></td><td style="height:50px;padding:5px;text-align:center;vertical-align:top;">cell value</td></tr><tr><td>datetime</td><td>touch</td><td>inputtypes</td></tr><tr><td colspan="3">Merged third row</td></tr><tr><td>fourth row 1</td><td>fourth row 2</td><td>fourth row 3</td></tr><tr><td>fifth row 1</td><td>fifth row 2</td><td>fifth row 3</td></tr></tbody></table>';
这是我的PHP代码
```php
$section = $phpWord->addSection();
processTableToWord($section, $html);
function processTableToWord($section, $table_data) {
//... (此处省略了代码的一部分)
}
这是输出的结果:
我实际上对外部表格做得不错,但当涉及到内部表格时,它与外部表格一起渲染并破坏了一切。需要有人帮忙修复代码。
我看到了$cells = $row->getElementsByTagName('td');
这里也将第二个表格的td添加到了主表格中。所以应该在这里进行一些处理。谢谢
英文:
I have a Full HTML text which needs to be converted accordingly to phpword and added finally in word.
HTML code is :
$html = '<table style="height:500px;width:600px;"><thead><tr><th>Lor<strong>em</strong></th><th colspan="2"><p>ipsum</p><p>dolr</p></th></tr></thead><tbody><tr><td colspan="2"><table><tbody><tr><td>1</td><td>2</td><td>3</td></tr><tr><td>4</td><td>5</td><td>6</td></tr></tbody></table></td><td style="height:50px;padding:5px;text-align:center;vertical-align:top;">cell value</td></tr><tr><td>datetime</td><td>touch</td><td>inputtypes</td></tr><tr><td colspan="3">Merged third row</td></tr><tr><td>fourth row 1</td><td>fourth row 2</td><td>fourth row 3</td></tr><tr><td>fifth row 1</td><td>fifth row 2</td><td>fifth row 3</td></tr></tbody></table>';
here is my PHP code
$section = $phpWord->addSection();
processTableToWord($section, $html);
function processTableToWord($section, $table_data) {
$table_style = new \PhpOffice\PhpWord\Style\Table;
$table_style->setBorderColor('aaaaaa');
$table_style->setBorderSize(1);
$table_style->setUnit('auto');
$table_style->setWidth('100px');
$clm_width = countColumns($table_data);
$table = $section->addTable($table_style);
$dom = new \DOMDocument;
$dom->loadHTML($table_data);
$tbody = $dom->getElementsByTagName('tbody')->item(0);
$thead = $dom->getElementsByTagName('thead')->item(0);
$thead_rows = $thead->getElementsByTagName('tr');
foreach ($thead_rows as $thead_row) {
$thead_cells = $thead_row->getElementsByTagName('th');
$table->addRow();
foreach ($thead_cells as $thead_cell) {
$thead_text = $thead_cell->nodeValue;
// dump(htmlspecialchars($thead_text));
$table->addCell($clm_width)->addText($thead_text, ['bold' => true], 'a_table');
}
}
$rows = $tbody->getElementsByTagName('tr');
foreach ($rows as $row) {
$cells = $row->getElementsByTagName('td');
$table->addRow();
foreach ($cells as $cell) {
// dump($dom->saveHTML($cell));
$width = $cell->getAttribute('width');
$height = $cell->getAttribute('height');
$text = $cell->nodeValue;
$style_arrs = [];
if (!empty($cell->getAttribute('style'))) {
$style_arrs = processStyleAttributes($cell->getAttribute('style'));
}
$colspan = $cell->getAttribute('colspan');
if ($colspan > 1) {
if (isset($style_arrs['vertical-align']) && !empty($style_arrs['vertical-align'])) {
$table->addCell($colspan * $clm_width, ['gridSpan' => $colspan, 'valign' => $style_arrs['vertical-align']])->addText($text, [], 'a_table');
}else {
$table->addCell($colspan * $clm_width, ['gridSpan' => $colspan])->addText($text, [], 'a_table');
}
}else {
if (isset($style_arrs['vertical-align']) && !empty($style_arrs['vertical-align'])) {
$table->addCell($clm_width, ['valign' => $style_arrs['vertical-align']])->addText($text, [], 'a_table');
}else {
$table->addCell($clm_width)->addText($text, [], 'a_table');
}
}
}
}
}
I am actually doing the right thing for outer table but when comes to inner Table, Its rendering with outer table and breaking everything. Need someone help in fixing the code.
I got about $cells = $row->getElementsByTagName('td');
Here it is adding second table td's also into main one. So there should be something doing it here. Thank you
答案1
得分: 0
我通过循环多次尝试来实现自身函数
function processTableToWord($section, $table_data, $nested = FALSE) {
$table_style = new \PhpOffice\PhpWord\Style\Table;
$table_style->setBorderColor('aaaaaa');
$table_style->setBorderSize(1);
$table_style->setUnit('auto');
$clm_width = countColumns($table_data);
$table = $section->addTable($table_style);
$dom = new \DOMDocument;
$dom->loadHTML($table_data);
$tbody = $dom->getElementsByTagName('tbody')->item(0);
$thead = $dom->getElementsByTagName('thead')->item(0);
$thead_rows = !empty($thead) ? $thead->getElementsByTagName('tr') : [];
foreach ($thead_rows as $thead_row) {
$thead_cells = $thead_row->getElementsByTagName('th');
$table->addRow();
foreach ($thead_cells as $thead_cell) {
$thead_text = $thead_cell->nodeValue;
$table->addCell($clm_width)->addText($thead_text, ['bold' => true], 'a_table');
}
}
$rows = $tbody->getElementsByTagName('tr');
foreach ($rows as $row) {
$cells = $row->getElementsByTagName('td');
$table->addRow(1500);
foreach ($cells as $cell) {
$haveNestedTbl = FALSE;
$nested_tbl = '';
$nestedTable = $cell->getElementsByTagName('table')->item(0);
if ($nestedTable) {
$haveNestedTbl = TRUE;
$nested_tbl = $dom->saveHTML($nestedTable);
$cell->removeChild($nestedTable);
}
$width = $cell->hasAttribute('width') ? $cell->getAttribute('width') : '';
$height = $cell->hasAttribute('height') ? $cell->getAttribute('height') : '';
$text = $cell->nodeValue;
$style_arrs = [];
if ($cell->hasAttribute('style')) {
$style_arrs = processStyleAttributes($cell->getAttribute('style'));
}
$colspan = $cell->getAttribute('colspan');
if ($colspan > 1) {
if (isset($style_arrs['vertical-align']) && !empty($style_arrs['vertical-align'])) {
$innerCell = $table->addCell($colspan * $clm_width, ['gridSpan' => $colspan, 'valign' => $style_arrs['vertical-align']]);
$innerCell->addText($text, [], 'a_table');
} else {
$innerCell = $table->addCell($colspan * $clm_width, ['gridSpan' => $colspan]);
$innerCell->addText($text, [], 'a_table');
}
} else {
if (isset($style_arrs['vertical-align']) && !empty($style_arrs['vertical-align'])) {
$innerCell = $table->addCell($clm_width, ['valign' => $style_arrs['vertical-align']]);
$innerCell->addText($text, [], 'a_table');
} else {
$innerCell = $table->addCell($clm_width);
$innerCell->addText($text, [], 'a_table');
}
}
if ($haveNestedTbl) {
processTableToWord($innerCell, $nested_tbl);
}
}
}
}
这里将嵌套表分配给一个变量后,必须从 DOM 中删除它,以便在其他行中不再处理它。这是输出的截图。
英文:
I am to achieve by multiple attempts by looping through self function
function processTableToWord($section, $table_data, $nested = FALSE) {
$table_style = new \PhpOffice\PhpWord\Style\Table;
$table_style->setBorderColor('aaaaaa');
$table_style->setBorderSize(1);
$table_style->setUnit('auto');
$clm_width = countColumns($table_data);
$table = $section->addTable($table_style);
$dom = new \DOMDocument;
$dom->loadHTML($table_data);
$tbody = $dom->getElementsByTagName('tbody')->item(0);
$thead = $dom->getElementsByTagName('thead')->item(0);
$thead_rows = !empty($thead) ? $thead->getElementsByTagName('tr') : [];
foreach ($thead_rows as $thead_row) {
$thead_cells = $thead_row->getElementsByTagName('th');
$table->addRow();
foreach ($thead_cells as $thead_cell) {
$thead_text = $thead_cell->nodeValue;
$table->addCell($clm_width)->addText($thead_text, ['bold' => true], 'a_table');
}
}
$rows = $tbody->getElementsByTagName('tr');
foreach ($rows as $row) {
$cells = $row->getElementsByTagName('td');
$table->addRow(1500);
foreach ($cells as $cell) {
$haveNestedTbl = FALSE;
$nested_tbl = '';
$nestedTable = $cell->getElementsByTagName('table')->item(0);
if ($nestedTable) {
$haveNestedTbl = TRUE;
$nested_tbl = $dom->saveHTML($nestedTable);
$cell->removeChild($nestedTable);
}
$width = $cell->hasAttribute('width') ? $cell->getAttribute('width') : '';
$height = $cell->hasAttribute('height') ? $cell->getAttribute('height') : '';
$text = $cell->nodeValue;
$style_arrs = [];
if ($cell->hasAttribute('style')) {
$style_arrs = processStyleAttributes($cell->getAttribute('style'));
}
$colspan = $cell->getAttribute('colspan');
if ($colspan > 1) {
if (isset($style_arrs['vertical-align']) && !empty($style_arrs['vertical-align'])) {
$innerCell = $table->addCell($colspan * $clm_width, ['gridSpan' => $colspan, 'valign' => $style_arrs['vertical-align']]);
$innerCell->addText($text, [], 'a_table');
}else {
$innerCell = $table->addCell($colspan * $clm_width, ['gridSpan' => $colspan]);
$innerCell->addText($text, [], 'a_table');
}
}else {
if (isset($style_arrs['vertical-align']) && !empty($style_arrs['vertical-align'])) {
$innerCell = $table->addCell($clm_width, ['valign' => $style_arrs['vertical-align']]);
$innerCell->addText($text, [], 'a_table');
}else {
$innerCell = $table->addCell($clm_width);
$innerCell->addText($text, [], 'a_table');
}
}
if ($haveNestedTbl) {
processTableToWord($innerCell, $nested_tbl);
}
}
}
}
Here after assigining nested table to a variable, have to delete it from DOM to not further process it in another rows.
Here is the screenshot of the output
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论