Extração de Texto Fora de Ordem em Tabelas Justamente Compactadas
Texto extraído de layouts de tabela ou formulário compactados aparece embaralhado. Caracteres de linhas adjacentes são misturados, por exemplo, "Número Único 123456789" é extraído como "U123456789nique Number".
Esta é uma limitação conhecida da extração page.Lines para layouts densamente compactados. page.Lines agrupa caracteres usando uma tolerância vertical embutida que não é configurável. Quando duas linhas visíveis em uma célula de tabela estão separadas por apenas um ponto ou dois, o agrupador colapsa ambas as linhas em uma linha lógica e ordena os caracteres da esquerda para a direita, mesclando-os. O método ExtractTextFromPage(i) por padrão usa a ordem do fluxo de conteúdo, que pode não corresponder à ordem de leitura visual em PDFs de formulário.
Solução
Recomendado: Extrair usando TextChunks com tolerância ajustável
Cada TextChunk expõe seu BoundingBox, o que permite o agrupamento por posição vertical e a ordenação dentro de cada linha por posição horizontal:
using IronPdf.Pages;
using System.Text;
static string ExtractTextUsingTextChunks(IPdfPage page, double rowTolerance = 2.0)
{
var rows = page.TextChunks
.Where(c => !string.IsNullOrWhiteSpace(c.Contents))
.GroupBy(c => Math.Round(c.BoundingBox.Top / rowTolerance) * rowTolerance)
.OrderByDescending(g => g.Key);
var extractedText = new StringBuilder();
foreach (var row in rows)
{
var line = string.Join(" ",
row.OrderBy(c => c.BoundingBox.Left)
.Select(c => c.Contents.Trim())
.Where(text => !string.IsNullOrWhiteSpace(text)));
extractedText.AppendLine(line);
}
return extractedText.ToString();
}
using IronPdf.Pages;
using System.Text;
static string ExtractTextUsingTextChunks(IPdfPage page, double rowTolerance = 2.0)
{
var rows = page.TextChunks
.Where(c => !string.IsNullOrWhiteSpace(c.Contents))
.GroupBy(c => Math.Round(c.BoundingBox.Top / rowTolerance) * rowTolerance)
.OrderByDescending(g => g.Key);
var extractedText = new StringBuilder();
foreach (var row in rows)
{
var line = string.Join(" ",
row.OrderBy(c => c.BoundingBox.Left)
.Select(c => c.Contents.Trim())
.Where(text => !string.IsNullOrWhiteSpace(text)));
extractedText.AppendLine(line);
}
return extractedText.ToString();
}
Imports IronPdf.Pages
Imports System.Text
Private Shared Function ExtractTextUsingTextChunks(page As IPdfPage, Optional rowTolerance As Double = 2.0) As String
Dim rows = page.TextChunks _
.Where(Function(c) Not String.IsNullOrWhiteSpace(c.Contents)) _
.GroupBy(Function(c) Math.Round(c.BoundingBox.Top / rowTolerance) * rowTolerance) _
.OrderByDescending(Function(g) g.Key)
Dim extractedText As New StringBuilder()
For Each row In rows
Dim line = String.Join(" ", row.OrderBy(Function(c) c.BoundingBox.Left) _
.Select(Function(c) c.Contents.Trim()) _
.Where(Function(text) Not String.IsNullOrWhiteSpace(text)))
extractedText.AppendLine(line)
Next
Return extractedText.ToString()
End Function
Comece com rowTolerance = 2.0. Se as linhas ainda se fundirem, reduza para 1.0 ou 0.5. Para controle mais fino, substitua page.Characters por page.TextChunks.
Alternativa: Extração por ordem visual
Para PDFs onde apenas a ordem do fluxo de conteúdo está errada:
pdf.ExtractTextFromPage(i, TextExtractionOrder.VisualOrder);
pdf.ExtractTextFromPage(i, TextExtractionOrder.VisualOrder);
pdf.ExtractTextFromPage(i, TextExtractionOrder.VisualOrder)
Para PDFs com linhas que estão visualmente muito próximas, a abordagem TextChunks lida melhor com tolerâncias apertadas.

