【问题标题】:Locate string using RegexBasedLocationExtractionStrategy and stamp an image using iTextSharp's PDFstamper. Problem stamping all locations使用 RegexBasedLocationExtractionStrategy 定位字符串并使用 iTextSharp 的 PDFstamper 标记图像。标记所有位置的问题
【发布时间】:2019-08-30 12:24:00
【问题描述】:

我正在尝试使用 Itext7 的 RegexBasedLocationExtractionStrategy 循环遍历所述 PDF 中的所有页面来定位 PDF 中的字符串模式。例如,我正在搜索的字符串是“Conrad Noll IV,#6272795”。我想要做的是,每次我找到这个字符串的 x 和 7 坐标时,我都会使用这些坐标,从 x 坐标中减去几个点,这样我就可以在它旁边标记一个“X”(png 图像) .

这是我尝试过的代码/模块。

    Imports iTextSharp.text
    Imports System.IO
    Imports System.IO.Path
    Imports System.Text.RegularExpressions
    Imports iTextSharp.text.pdf.parser
    Imports System.Linq
    Imports iText
    Imports iText.Kernel.Pdf.Canvas.Parser.Listener
    Imports iText.Kernel.Pdf.Canvas.Parser
    Imports iText.Kernel.Pdf

    Module Module1
    Dim signedFolder = "C:\Users\xborja\Desktop\Original PDF's\Signed PDFs\"
    Sub Main()

    If Not Directory.Exists(signedFolder) Then
        Directory.CreateDirectory(signedFolder)
    End If
    Dim src = "C:\Users\xborja\Desktop\Original PDF's Before Merge\TP067389.CRUZ.pdf"
    Dim pattern = "Conrad Noll IV, #6272795"
    Dim inputfile As Stream = New FileStream(src, FileMode.Open, FileAccess.Read, FileShare.Read)
    Dim inputImage As Stream = New FileStream("C:\Users\user\source\repos\addImagePdf\addImagePdf\CN signature.png", FileMode.Open, FileAccess.Read, FileShare.Read)
    Dim xmarkImage As Stream = New FileStream("C:\Users\user\Desktop\xmark.png", FileMode.Open, FileAccess.Read, FileShare.Read)
    Dim finalPDF As String = signedFolder & GetFileNameWithoutExtension(src) & " signed.pdf"
    Dim outputPdf As Stream = New FileStream(finalPDF, FileMode.Create, FileAccess.Write, FileShare.None)
    Dim pdfReader = New iText.Kernel.Pdf.PdfReader(src)
    Dim pdfReader2 = New pdf.PdfReader(inputfile)
    Dim pdfDoc As iText.Kernel.Pdf.PdfDocument = New iText.Kernel.Pdf.PdfDocument(pdfReader)
    Dim pageCount = pdfDoc.GetNumberOfPages
    Dim pagecount2 = pdfReader2.NumberOfPages
    Dim extractionStrategy As RegexBasedLocationExtractionStrategy = New RegexBasedLocationExtractionStrategy(pattern)
    Dim locationList As IList(Of IPdfTextLocation) = New List(Of IPdfTextLocation)
    Dim parser As PdfCanvasProcessor = New PdfCanvasProcessor(extractionStrategy)

    Dim stamper = New pdf.PdfStamper(pdfReader2, outputPdf)

    Dim pdfContentByte = Nothing
    Dim image As Image = Image.GetInstance(inputImage)
    Dim xmark As Image = Image.GetInstance(xmarkImage)

    Dim xy = Nothing
    Dim counter = 0

    Console.WriteLine(pagecount2)

    For page1 = 1 To pagecount2

        parser.ProcessPageContent(pdfDoc.GetPage(page1)) ' THIS has to be outside the for each
        For Each location As IPdfTextLocation In extractionStrategy.GetResultantLocations
            parser.ProcessPageContent(pdfDoc.GetPage(page1))
            pdfContentByte = stamper.GetOverContent(page1)
            If location IsNot Nothing Then
                counter += 1
                Dim xP = Math.Round(location.GetRectangle.GetX)
                Dim yP = Math.Round(location.GetRectangle.GetY)


                xmark.SetAbsolutePosition(xP - 18, yP)
                pdfContentByte.addimage(xmark)
                stamper.Close()

                Console.WriteLine(pattern & " " & xP & " " & yP & " located on page " & page1 & " and counter is " & counter)

            End If

        Next location

    Next page1

End Sub

End Module

如您所见,我正在同时使用 2 个不同的阅读器,因为每个阅读器都有不同的参数,因此我尝试将两者结合使用来做一些棘手的事情。

当我运行它并向自己打印结果时,它显示了我正在搜索的字符串的正确 X 和 Y 位置数量以及正确的页数,但 itextsharp.pdfstamper 仅标记一个位置,这是第一个它找到的位置。

xmark.SetAbsolutePosition(xP - 18, yP) 是我设置的,这样当它找到 x y 坐标时,x 减去 8 从而将我的 X 图像直接移动到它的右侧,所以它看起来像名称已签出。

代码会读取所有页面,打印出搜索字符串的所有位置,但只标记其中一个,这是有原因的吗?

【问题讨论】:

    标签: regex vb.net pdf itext


    【解决方案1】:

    添加标记后关闭内循环内的PdfStamper

    For page1 = 1 To pagecount2
        ...
        For Each location As IPdfTextLocation In extractionStrategy.GetResultantLocations
            ...
            If location IsNot Nothing Then
                ...
                xmark.SetAbsolutePosition(xP - 18, yP)
                pdfContentByte.addimage(xmark)
                stamper.Close()
                ...
            End If
        Next location
    Next page1
    

    因此,在添加第一个标记后,压模完成其输出,然后不再接受任何更改。在循环之后移动 Close 调用:

    For page1 = 1 To pagecount2
        ...
        For Each location As IPdfTextLocation In extractionStrategy.GetResultantLocations
            ...
            If location IsNot Nothing Then
                ...
                xmark.SetAbsolutePosition(xP - 18, yP)
                pdfContentByte.addimage(xmark)
                ' stamper.Close()
                ...
            End If
        Next location
    Next page1
    stamper.Close()
    

    【讨论】:

      【解决方案2】:

      您可以将所有内容保留在 Itext 中,而不使用 itextsharp,而是使用此代码:

      Imports System.IO
      Imports System.IO.Path
      Imports System.Text.RegularExpressions
      Imports iTextSharp.text.pdf.parser
      Imports System.Linq
      Imports iText
      Imports iText.Kernel.Pdf.Canvas.Parser.Listener
      Imports iText.Kernel.Pdf.Canvas.Parser
      Imports iText.Kernel.Pdf
      Imports iText.Layout
      Imports iText.IO.Image
      Imports iText.Layout.Element
      Imports iText.Layout.Properties
      
      Module Module1
          Dim signedFolder = "C:\Users\Desktop\Original PDF's\Signed PDFs\"
          Sub Main()
      
              If Not Directory.Exists(signedFolder) Then
                  Directory.CreateDirectory(signedFolder)
              End If
              Dim src = "C:\Users\Desktop\Original PDF's Before Merge\TP067389.CRUZ.pdf"
              Dim pattern = "Conrad Noll IV, #6272795"
      
              Dim xmarkImage = "C:\Users\Desktop\xmark.png"
              Dim finalPDF As String = signedFolder & GetFileNameWithoutExtension(src) & " signed.pdf"
      
              Dim pdfDoc As PdfDocument = New iText.Kernel.Pdf.PdfDocument(New PdfReader(src), New PdfWriter(finalPDF))
              Dim document As Document = New Document(pdfDoc)
      
      
              Dim pageCount = pdfDoc.GetNumberOfPages
      
      
              Dim extractionStrategy As RegexBasedLocationExtractionStrategy = New RegexBasedLocationExtractionStrategy(pattern)
              Dim locationList As IList(Of IPdfTextLocation) = New List(Of IPdfTextLocation)
              Dim parser As PdfCanvasProcessor = New PdfCanvasProcessor(extractionStrategy)
      
              Dim xmark As ImageData = ImageDataFactory.Create(xmarkImage)
      
              Dim counter = 0
      
              Dim xp = Nothing
              Dim yp = Nothing
      
      
              For page1 = 1 To pageCount
      
                  parser.ProcessPageContent(pdfDoc.GetPage(page1))
      
                  For Each location As IPdfTextLocation In extractionStrategy.GetResultantLocations
                      parser.ProcessPageContent(pdfDoc.GetPage(page1))
                      If location IsNot Nothing Then
                          counter += 1
      
                          xp = CType(Math.Round(location.GetRectangle.GetX), Single)
                          yp = CType(Math.Round(location.GetRectangle.GetY), Single)
      
                          Dim xmimage As Image = New Image(xmark).SetFixedPosition(page1, xp - 16, yp)
                          document.Add(xmimage)
      
                          locationList.Add(location)
                          Console.WriteLine(pattern & " " & xp & " " & yp & " located on page " & page1)
      
      
      
                      End If
                  Next location
              Next page1
              document.Close()
      
      
      
      
      
      
          End Sub
      
      
      End Module
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-01-17
        • 2012-01-07
        • 2017-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-04-27
        相关资源
        最近更新 更多