You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确转换含嵌套表格的HTML为Docx?解决多余行问题

HTML嵌套表格转Docx时多余行问题修复

问题现象

将包含单元格内嵌套表格的HTML转换为Docx格式时,嵌套表格所在行的后续会生成多余行,多余行数等于该行内所有嵌套表格的行数总和,无法实现仅将嵌套表格插入对应单元格的需求。

错误原因

在处理嵌套表格的逻辑中,错误地将父表格对象(parent_docx_table)传递给了递归调用的handle_table方法,而非当前单元格内新建的子表格。这导致嵌套表格的行被错误追加到父表格中,而非单元格内部的子表格,最终引发多余行问题。

修复后的完整代码

from docx import Document
from bs4 import BeautifulSoup

class HtmlToDocx:
    def __init__(self):
        self.document = Document()

    def handle_table(self, table_soup, parent_docx_table=None, row_idx=0, col_idx=0):
        rows, cols = self.get_table_dimensions(table_soup)
        
        if parent_docx_table:
            cell = parent_docx_table.cell(row_idx, col_idx)
            docx_table = cell.add_table(rows=rows, cols=cols)
        else:
            docx_table = self.document.add_table(rows=rows, cols=cols)
    
        rows = self.get_table_rows(table_soup)
        cell_row = 0
        for row in rows:
            cols = self.get_table_columns(row)
            cell_col = 0
            for col in cols:
                nested_table = col.find('table') 
                docx_cell = docx_table.cell(cell_row, cell_col)
    
                if nested_table:
                    # 修复:传递当前单元格内的子表格作为父表格,而非原父表格
                    self.handle_table(nested_table, docx_table, cell_row, cell_col)
                    cell_col += 1  
                    continue  

                cell_html = self.get_cell_html(col)
                docx_cell.text = cell_html
    
                cell_col += 1
            cell_row += 1

    def get_table_rows(self, table_soup):
        return table_soup.find_all('tr')

    def get_table_columns(self, row):
        return row.find_all(['th', 'td'], recursive=False)

    def get_cell_html(self, soup):
        return ''.join([str(i) for i in soup.contents if not (i.name == 'table' or isinstance(i, BeautifulSoup))])

    def get_table_dimensions(self, table_soup):
        rows = self.get_table_rows(table_soup)
        cols = self.get_table_columns(rows[0]) if rows else []
        return len(rows), len(cols)

    def add_html_to_docx(self, html_content, output_file):
        self.soup = BeautifulSoup(html_content, "html.parser")
        top_tables = self.soup.find_all('table', recursive=False)
        for table_soup in top_tables:
            self.handle_table(table_soup)
        self.document.save(output_file)

html_content = """
   
    <table style="border-collapse: collapse; width: 100%; height: 232px;" border="1">
        <tbody>
        <tr style="height: 22px;">
        <td style="width: 23.7413%; height: 22px;">&nbsp;</td>
        <td style="width: 23.7413%; height: 22px;">&nbsp;</td>
        <td style="width: 23.7413%; height: 22px;">&nbsp;</td>
        <td style="width: 23.7413%; height: 22px;">&nbsp;</td>
        </tr>
        <tr style="height: 188px;">
        <td style="width: 23.7413%; height: 188px;">&nbsp;</td>
        <td style="width: 23.7413%; height: 188px;">
        </td>
        <td style="width: 23.7413%; height: 188px;">
        <table style="border-collapse: collapse; width: 95.0877%;" border="1">
        <tbody>
        <tr>
        <td style="width: 14.6073%;">&nbsp;</td>
        <td style="width: 14.6073%;">&nbsp;</td>
        <td style="width: 14.6073%;">&nbsp;</td>
        <td style="width: 14.6073%;">&nbsp;</td>
        <td style="width: 14.6246%;">&nbsp;</td>
        </tr>
        <tr>
        <td style="width: 14.6073%;">&nbsp;</td>
        <td style="width: 14.6073%;">&nbsp;</td>
        <td style="width: 14.6073%;">ааа</td>
        <td style="width: 14.6073%;">&nbsp;</td>
        <td style="width: 14.6246%;">&nbsp;</td>
        </tr>
        <tr>
        <td style="width: 14.6073%;">&nbsp;</td>
        <td style="width: 14.6073%;">&nbsp;</td>
        <td style="width: 14.6073%;">&nbsp;</td>
        <td style="width: 14.6073%;">&nbsp;</td>
        <td style="width: 14.6246%;">&nbsp;</td>
        </tr>
        </tbody>
        </table>
        </td>
        <td style="width: 23.7413%; height: 188px;">
        <table style="border-collapse: collapse; width: 95.0877%;" border="1">
        <tbody>
        <tr>
        <td style="width: 27.8655%;">е</td>
        <td style="width: 27.8655%;">&nbsp;</td>
        <td style="width: 27.8742%;">&nbsp;</td>
        </tr>
        <tr>
        <td style="width: 27.8655%;">&nbsp;</td>
        <td style="width: 27.8655%;">еее</td>
        <td style="width: 27.8742%;">&nbsp;</td>
        </tr>
        </tbody>
        </table>
        </td>
        </tr>
        <tr style="height: 22px;">
        <td style="width: 23.7413%; height: 22px;">&nbsp;</td>
        <td style="width: 23.7413%; height: 22px;">&nbsp;</td>
        <td style="width: 23.7413%; height: 22px;">
        <table style="border-collapse: collapse; width: 95.0877%;" border="1">
        <tbody>
        <tr>
        <td style="width: 19.5803%;">11</td>
        <td style="width: 19.5803%;">&nbsp;</td>
        <td style="width: 19.5803%;">&nbsp;</td>
        <td style="width: 19.5889%;">&nbsp;</td>
        </tr>
        <tr>
        <td style="width: 19.5803%;">&nbsp;</td>
        <td style="width: 19.5803%;">&nbsp;</td>
        <td style="width: 19.5803%;">222</td>
        <td style="width: 19.5889%;">333</td>
        </tr>
        </tbody>
        </table>
        </td>
        <td style="width: 23.7413%; height: 22px;">&nbsp;</td>
        </tr>
        </tbody>
        </table>
"""
converter = HtmlToDocx()
converter.add_html_to_docx(html_content, "output.docx")

关键修复点

在处理嵌套表格的递归调用中,将传递的父表格从parent_docx_table改为当前单元格内新建的docx_table,确保嵌套表格的行被正确添加到单元格内部的子表格中,而非父表格。


内容的提问来源于stack exchange,提问作者Василий Чернов

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 01:22:33