Descrição do problema
O PR #1373 (issue #1371) corrige o IndexError que travava a geração inteira do PDF quando uma tabela tem <thead>/<tbody> com números de colunas diferentes. Mas a correção usa max(colunas do header, colunas do body) apenas como largura defensiva da tabela DOCX — ela evita o crash, não garante que o conteúdo fique posicionado na coluna correta. Revisando os PDFs reais gerados a partir do corpus de 593 artigos, o conteúdo de várias tabelas sai desalinhado mesmo sem crash.
Achados (revisão de @pitangainnovare no PR #1373, mais 1 achado complementar encontrado durante revisão automatizada do mesmo PR):
- BJT – Tabela 5:
<thead> mistura <td/> e <th>. Como a extração considera somente <th>, a célula vazia inicial é descartada e os cabeçalhos "Idade" e "Experiência" ficam deslocados uma coluna para a esquerda.
- RBCS – Tabela 1: o cálculo da largura não considera as posições já ocupadas por
rowspan de linhas anteriores. Cabeçalhos como "MDL" e "Increase in cumulative NH3-N loss" não ficam posicionados corretamente.
- DELTA – Tabela 6: o XML tem uma inconsistência real entre os
colspan declarados e a quantidade de colunas do corpo. O PDF é gerado, mas os grupos do cabeçalho continuam desalinhados.
- RBPV (2 artigos): a geração deixa de falhar, mas colunas vazias adicionais podem comprimir as tabelas.
- Célula de cabeçalho sem estilo (achado complementar): quando o corpo é mais largo que o cabeçalho,
_populate_headers só estiliza células até len(header_row), não até num_cols — a(s) coluna(s) extra(s) do cabeçalho ficam sem texto e sem nenhuma formatação (sem negrito, sem tamanho 7pt, sem margens ajustadas), destoando visualmente das demais células do cabeçalho.
Passos para reproduzir o problema
bjt/v29/2764-1589-bjt-29-e1526.xml (anexo a36.xml no corpus layout_examples_rafael/corpus/): gerar o PDF e observar a Tabela 5 com cabeçalho deslocado uma coluna para a esquerda.
rbcs/v50/... (corpus layout_roberta, ainda não copiado para layout_examples_rafael): gerar o PDF e observar a Tabela 1 com cabeçalhos mal posicionados por causa de rowspan não contabilizado.
delta/v42n2/...: gerar o PDF e observar a Tabela 6 com grupos de cabeçalho desalinhados.
rbpv/v35n1/... e rbpv/v35n3/...: gerar o PDF e observar colunas vazias extras comprimindo as tabelas.
- Reproduzir o achado 5 isoladamente chamando
add_table() com headers=[['', 'H1']] e rows=[['row-label', 'A', 'B']] (header com 2 colunas, body com 3, sem colspan) — a 3ª célula do cabeçalho sai sem nenhum run no .docx gerado.
Comportamento esperado
Os cabeçalhos e colunas devem ficar alinhados fielmente com a estrutura declarada no XML, mesmo quando <thead>/<tbody> têm contagens de colunas diferentes ou misturam <td>/<th>. Nenhuma célula de cabeçalho deveria ficar sem formatação aplicada.
Direção de correção sugerida (@pitangainnovare, no review do PR #1373): reescrever a extração da grade da tabela como um único algoritmo que:
- considere
<th> e <td> na ordem em que aparecem;
- preserve células vazias;
- reserve as posições ocupadas por
rowspan;
- aplique
colspan;
- produza dados e spans na mesma passagem.
Para XMLs realmente inconsistentes (caso DELTA), o comportamento deveria ser conservador: respeitar os spans declarados, completar posições ausentes com células vazias e, se possível, emitir um aviso — sem inferir automaticamente uma nova estrutura semântica.
O max(...) introduzido no PR #1373 deveria permanecer apenas como proteção defensiva contra crash, não como a solução de posicionamento.
Screenshots ou vídeos
Não anexado nesta issue — os PDFs analisados (BJT, RBCS, DELTA, RBPV) estão descritos no review do PR #1373.
Anexos
Ambiente utilizado
packtools, gerador de PDF (packtools/sps/formats/pdf/), encontrado durante o review do PR #1373 (issue #1371) e complementado durante revisão automatizada do mesmo PR, contra o corpus real de 593 artigos fornecido pela Roberta.
Descrição do problema
O PR #1373 (issue #1371) corrige o
IndexErrorque travava a geração inteira do PDF quando uma tabela tem<thead>/<tbody>com números de colunas diferentes. Mas a correção usamax(colunas do header, colunas do body)apenas como largura defensiva da tabela DOCX — ela evita o crash, não garante que o conteúdo fique posicionado na coluna correta. Revisando os PDFs reais gerados a partir do corpus de 593 artigos, o conteúdo de várias tabelas sai desalinhado mesmo sem crash.Achados (revisão de @pitangainnovare no PR #1373, mais 1 achado complementar encontrado durante revisão automatizada do mesmo PR):
<thead>mistura<td/>e<th>. Como a extração considera somente<th>, a célula vazia inicial é descartada e os cabeçalhos "Idade" e "Experiência" ficam deslocados uma coluna para a esquerda.rowspande linhas anteriores. Cabeçalhos como "MDL" e "Increase in cumulative NH3-N loss" não ficam posicionados corretamente.colspandeclarados e a quantidade de colunas do corpo. O PDF é gerado, mas os grupos do cabeçalho continuam desalinhados._populate_headerssó estiliza células atélen(header_row), não aténum_cols— a(s) coluna(s) extra(s) do cabeçalho ficam sem texto e sem nenhuma formatação (sem negrito, sem tamanho 7pt, sem margens ajustadas), destoando visualmente das demais células do cabeçalho.Passos para reproduzir o problema
bjt/v29/2764-1589-bjt-29-e1526.xml(anexoa36.xmlno corpuslayout_examples_rafael/corpus/): gerar o PDF e observar a Tabela 5 com cabeçalho deslocado uma coluna para a esquerda.rbcs/v50/...(corpuslayout_roberta, ainda não copiado paralayout_examples_rafael): gerar o PDF e observar a Tabela 1 com cabeçalhos mal posicionados por causa derowspannão contabilizado.delta/v42n2/...: gerar o PDF e observar a Tabela 6 com grupos de cabeçalho desalinhados.rbpv/v35n1/...erbpv/v35n3/...: gerar o PDF e observar colunas vazias extras comprimindo as tabelas.add_table()comheaders=[['', 'H1']]erows=[['row-label', 'A', 'B']](header com 2 colunas, body com 3, sem colspan) — a 3ª célula do cabeçalho sai sem nenhumrunno.docxgerado.Comportamento esperado
Os cabeçalhos e colunas devem ficar alinhados fielmente com a estrutura declarada no XML, mesmo quando
<thead>/<tbody>têm contagens de colunas diferentes ou misturam<td>/<th>. Nenhuma célula de cabeçalho deveria ficar sem formatação aplicada.Direção de correção sugerida (@pitangainnovare, no review do PR #1373): reescrever a extração da grade da tabela como um único algoritmo que:
<th>e<td>na ordem em que aparecem;rowspan;colspan;Para XMLs realmente inconsistentes (caso DELTA), o comportamento deveria ser conservador: respeitar os spans declarados, completar posições ausentes com células vazias e, se possível, emitir um aviso — sem inferir automaticamente uma nova estrutura semântica.
O
max(...)introduzido no PR #1373 deveria permanecer apenas como proteção defensiva contra crash, não como a solução de posicionamento.Screenshots ou vídeos
Não anexado nesta issue — os PDFs analisados (BJT, RBCS, DELTA, RBPV) estão descritos no review do PR #1373.
Anexos
a36.xmljá está emlayout_examples_rafael/corpus/(referenciado pela issue [PDF Generator] Crash ao gerar PDF quando cabeçalho e corpo de uma tabela têm números de colunas diferentes #1371/PR fix: nao trava geracao quando cabecalho e corpo de tabela tem colunas diferentes (#1371) #1373) — reproduz o caso BJT.layout_roberta/pacote_xml_pdf_csv/fornecido pela Roberta, ainda não copiados para o corpus de amostraslayout_examples_rafael/corpus/.Ambiente utilizado
packtools, gerador de PDF (packtools/sps/formats/pdf/), encontrado durante o review do PR #1373 (issue #1371) e complementado durante revisão automatizada do mesmo PR, contra o corpus real de 593 artigos fornecido pela Roberta.