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

使用iText获取Word与CorelDraw生成PDF中指定字符串位置的问题

解决iText提取不同来源PDF指定字符串位置的问题

问题背景

使用iText提取Word、CorelDraw等工具生成的PDF中指定字符串位置时,CorelDraw生成的PDF能正常获取完整字符串的位置,但Word生成的PDF里字符串会被拆分成如“T”“est”这类片段,导致原代码无法匹配到完整目标字符串。

问题原因

PDF的文本渲染单元并非严格按自然语言的字符串划分:

  • CorelDraw生成PDF时,通常会将连续字符串作为单个文本块输出
  • Word生成PDF时,可能因字体子集嵌入、排版优化(如字距调整、连字)或压缩策略,将完整字符串拆分为多个小文本块,以满足渲染或文件大小优化需求。

通过Word导出设置尝试解决

可以尝试调整Word导出PDF的参数,部分场景下能减少文本块拆分:

  • 导出时选择**「最佳打印质量」**而非「最小文件大小」:后者为压缩文件会拆分文本块
  • 关闭**「PDF/A兼容性」**:PDF/A的规范可能强制调整文本结构
  • 选择**「嵌入所有字体」**而非「仅嵌入所用字符」:完整字体嵌入可能保留更完整的文本块

注意:这些设置不保证100%生效,Word的PDF导出逻辑因版本不同可能有差异。

代码层面的通用解决方案

如果无法通过设置解决,需要通过代码收集并拼接文本块,再匹配目标字符串并合并其位置信息。以下是修改后的实现:

1. 定义文本块存储类

用于记录每个文本块的内容和对应的渲染信息:

public class TextChunk
{
    public string Text { get; set; }
    public TextRenderInfo RenderInfo { get; set; }
}

2. 修改事件监听器收集文本块

将所有渲染的文本块收集起来,而非单次匹配:

class MyEventListener : IEventListener
{
    private readonly List<TextChunk> _textChunks = new List<TextChunk>();

    public List<TextChunk> TextChunks => _textChunks;

    public void EventOccurred(IEventData data, EventType type)
    {
        if (type == EventType.RENDER_TEXT)
        {
            var renderInfo = (TextRenderInfo)data;
            _textChunks.Add(new TextChunk { Text = renderInfo.GetText(), RenderInfo = renderInfo });
        }
    }

    public ICollection<EventType> GetSupportedEvents()
    {
        return new List<EventType> { EventType.RENDER_TEXT };
    }
}

3. 主逻辑:拼接文本、匹配目标、合并位置

private static readonly string specificText = "Test";
private void BtnNewPDF_Click(object sender, RoutedEventArgs e)
{
    using var pdfDoc = new PdfDocument(new PdfReader(@"D:\Word-test.pdf"));
    var pdfPage = pdfDoc.GetPage(1);

    var listener = new MyEventListener();
    using var canvasProcessor = new PdfCanvasProcessor(listener);
    canvasProcessor.ProcessPageContent(pdfPage);

    // 拼接所有文本块得到完整页面文本
    var fullText = string.Join("", listener.TextChunks.Select(c => c.Text));
    var startIndex = fullText.IndexOf(specificText, StringComparison.OrdinalIgnoreCase);

    if (startIndex >= 0)
    {
        var endIndex = startIndex + specificText.Length;
        var currentPos = 0;
        var targetRenderInfos = new List<TextRenderInfo>();

        // 定位包含目标字符串的所有文本块
        foreach (var chunk in listener.TextChunks)
        {
            var chunkEnd = currentPos + chunk.Text.Length;
            // 检查当前块与目标字符串的重叠范围
            if (!(chunkEnd <= startIndex || currentPos >= endIndex))
            {
                targetRenderInfos.Add(chunk.RenderInfo);
            }
            currentPos = chunkEnd;
            if (currentPos >= endIndex) break;
        }

        // 合并所有目标块的边界框
        if (targetRenderInfos.Any())
        {
            var combinedRect = targetRenderInfos[0].GetDescentLine().GetBoundingRectangle();
            foreach (var info in targetRenderInfos.Skip(1))
            {
                var rect = info.GetDescentLine().GetBoundingRectangle();
                combinedRect = combinedRect.Merge(rect);
            }

            MessageBox.Show($"X坐标:{combinedRect.GetX()}");
            MessageBox.Show($"Y坐标:{combinedRect.GetY()}");
            // 可选:显示完整边界框信息
            // MessageBox.Show($"边界框:{combinedRect.ToString()}");
        }
    }
    else
    {
        MessageBox.Show("未找到目标字符串");
    }
}

方案优势

  • 通用性强:不管PDF由什么工具生成,只要文本按视觉顺序渲染,就能正确拼接并匹配目标字符串
  • 准确性高:通过合并对应文本块的边界框,得到完整目标字符串的位置

内容的提问来源于stack exchange,提问作者CodeCatia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 22:12:31