2017-05-16 30 views
-2

以前に作成したコードを使用して、pdf形式のテキストを置き換えようとしています。しかし、この行は赤色の下線です。 'myLocationTextExtractionStrategy strategy = new myLocationTextExtractionStrategy();' 。カスタム戦略を作成する必要がありますか、ライブラリを使用できますか?あなたのソースで使用Itextsharpを使用してpdfファイルのテキストを置き換えます。

class Program 
{ 
    static iTextSharp.text.pdf.PdfStamper stamper = null; 
    static void Main(string[] args) 
    { 
     var oldFile = @"C:\oldFile.pdf"; 
     var newFile = @"C:\newFile.pdf"; 

     string replacingVariable = "Test"; 
     PdfReader pReader = new PdfReader(oldFile); 
     stamper = new iTextSharp.text.pdf.PdfStamper(pReader, new System.IO.FileStream(newFile, System.IO.FileMode.Create)); 
     PDFTextGetter("ExistingVariableinPDF", replacingVariable, StringComparison.CurrentCultureIgnoreCase, oldFile, newFile); 
     stamper.Close(); 
     pReader.Close(); 
    } 

    public static void PDFTextGetter(string pSearch, string replacingText, StringComparison SC, string SourceFile, string DestinationFile) 
    { 
     try 
     { 
      iTextSharp.text.pdf.PdfContentByte cb = null; 
      iTextSharp.text.pdf.PdfContentByte cb2 = null; 
      iTextSharp.text.pdf.PdfWriter writer = null; 
      iTextSharp.text.pdf.BaseFont bf = null; 

      if (System.IO.File.Exists(SourceFile)) 
      { 
       PdfReader pReader = new PdfReader(SourceFile); 
       for (int page = 1; page <= pReader.NumberOfPages; page++) 
       { 
        myLocationTextExtractionStrategy strategy = new myLocationTextExtractionStrategy(); 
        cb = stamper.GetOverContent(page); 
        cb2 = stamper.GetOverContent(page); 
        strategy.UndercontentCharacterSpacing = (int)cb.CharacterSpacing; 
        strategy.UndercontentHorizontalScaling = (int)cb.HorizontalScaling; 
        string currentText = PdfTextExtractor.GetTextFromPage(pReader, page, strategy); 

        List<iTextSharp.text.Rectangle> MatchesFound = strategy.GetTextLocations(pSearch, SC); 
        cb.SetColorFill(BaseColor.WHITE); 
        foreach (iTextSharp.text.Rectangle rect in MatchesFound) 
        { 
         cb.Rectangle(rect.Left, rect.Bottom, 60, rect.Height); 
         cb.Fill(); 
         cb2.SetColorFill(BaseColor.BLACK); 
         bf = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED); 
         cb2.SetFontAndSize(bf, 9); 
         cb2.BeginText(); 
         cb2.ShowTextAligned(0, replacingText, rect.Left, rect.Bottom, 0); 
         cb2.EndText(); 
         cb2.Fill(); 
        } 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
     } 
    } 
} 
+0

はい、それが見えます。 – criticalfix

+0

戦略が – user6934713

答えて

1

myLocationTextExtractionStrategyクラスはexample Projectから質問"how to highlight a text or word in a pdf file using iTextsharp?"his answerに共有スタックオーバーフローユーザーJcisを取っているように見えます。

彼はVB.Netでそれを書いています:

Public Class myLocationTextExtractionStrategy 
    Implements ITextExtractionStrategy 

    '* set to true for debugging 

    Private _UndercontentCharacterSpacing = 0 
    Private _UndercontentHorizontalScaling = 0 
    Private ThisPdfDocFonts As SortedList(Of String, DocumentFont) 

    Public Shared DUMP_STATE As Boolean = False 

    '* a summary of all found text 

    Private locationalResult As New List(Of TextChunk)() 

    '* 
    '   * Creates a new text extraction renderer. 
    '   

    Public Sub New() 
     ThisPdfDocFonts = New SortedList(Of String, DocumentFont) 
    End Sub 

    '* 
    '   * @see com.itextpdf.text.pdf.parser.RenderListener#beginTextBlock() 
    '   

    Public Overridable Sub BeginTextBlock() Implements ITextExtractionStrategy.BeginTextBlock 
    End Sub 

    '* 
    '   * @see com.itextpdf.text.pdf.parser.RenderListener#endTextBlock() 
    '   

    Public Overridable Sub EndTextBlock() Implements ITextExtractionStrategy.EndTextBlock 
    End Sub 

    '* 
    '   * @param str 
    '   * @return true if the string starts with a space character, false if the string is empty or starts with a non-space character 
    '   

    Private Function StartsWithSpace(ByVal str As [String]) As Boolean 
     If str.Length = 0 Then 
      Return False 
     End If 
     Return str(0) = " "c 
    End Function 

    '* 
    '   * @param str 
    '   * @return true if the string ends with a space character, false if the string is empty or ends with a non-space character 
    '   

    Private Function EndsWithSpace(ByVal str As [String]) As Boolean 
     If str.Length = 0 Then 
      Return False 
     End If 
     Return str(str.Length - 1) = " "c 
    End Function 

    Public Property UndercontentCharacterSpacing 
     Get 
      Return _UndercontentCharacterSpacing 
     End Get 
     Set(ByVal value) 
      _UndercontentCharacterSpacing = value 
     End Set 
    End Property 

    Public Property UndercontentHorizontalScaling 
     Get 
      Return _UndercontentHorizontalScaling 
     End Get 
     Set(ByVal value) 
      _UndercontentHorizontalScaling = value 
     End Set 
    End Property 

    Public Overridable Function GetResultantText() As [String] Implements ITextExtractionStrategy.GetResultantText 

     If DUMP_STATE Then 
      DumpState() 
     End If 

     locationalResult.Sort() 

     Dim sb As New StringBuilder() 
     Dim lastChunk As TextChunk = Nothing 

     For Each chunk As TextChunk In locationalResult 

      If lastChunk Is Nothing Then 
       sb.Append(chunk.text) 
      Else 
       If chunk.SameLine(lastChunk) Then 
        Dim dist As Single = chunk.DistanceFromEndOf(lastChunk) 
        If dist < -chunk.charSpaceWidth Then 
         sb.Append(" "c) 
         ' we only insert a blank space if the trailing character of the previous string wasn't a space, and the leading character of the current string isn't a space 
        ElseIf dist > chunk.charSpaceWidth/2.0F AndAlso Not StartsWithSpace(chunk.text) AndAlso Not EndsWithSpace(lastChunk.text) Then 
         sb.Append(" "c) 
        End If 

        sb.Append(chunk.text) 
       Else 
        sb.Append(ControlChars.Lf) 
        sb.Append(chunk.text) 
       End If 
      End If 
      lastChunk = chunk 
     Next 

     Return sb.ToString() 

    End Function 

    Public Function GetTextLocations(ByVal pSearchString As String, ByVal pStrComp As System.StringComparison) As List(Of iTextSharp.text.Rectangle) 
     Dim FoundMatches As New List(Of iTextSharp.text.Rectangle) 
     Dim sb As New StringBuilder() 
     Dim ThisLineChunks As List(Of TextChunk) = New List(Of TextChunk) 
     Dim bStart As Boolean, bEnd As Boolean 
     Dim FirstChunk As TextChunk = Nothing, LastChunk As TextChunk = Nothing 
     Dim sTextInUsedChunks As String = vbNullString 

     For Each chunk As TextChunk In locationalResult 

      If ThisLineChunks.Count > 0 AndAlso Not chunk.SameLine(ThisLineChunks.Last) Then 
       If sb.ToString.IndexOf(pSearchString, pStrComp) > -1 Then 
        Dim sLine As String = sb.ToString 

        'Check how many times the Search String is present in this line: 
        Dim iCount As Integer = 0 
        Dim lPos As Integer 
        lPos = sLine.IndexOf(pSearchString, 0, pStrComp) 
        Do While lPos > -1 
         iCount += 1 
         If lPos + pSearchString.Length > sLine.Length Then Exit Do Else lPos = lPos + pSearchString.Length 
         lPos = sLine.IndexOf(pSearchString, lPos, pStrComp) 
        Loop 

        'Process each match found in this Text line: 
        Dim curPos As Integer = 0 
        For i As Integer = 1 To iCount 
         Dim sCurrentText As String, iFromChar As Integer, iToChar As Integer 

         iFromChar = sLine.IndexOf(pSearchString, curPos, pStrComp) 
         curPos = iFromChar 
         iToChar = iFromChar + pSearchString.Length - 1 
         sCurrentText = vbNullString 
         sTextInUsedChunks = vbNullString 
         FirstChunk = Nothing 
         LastChunk = Nothing 

         'Get first and last Chunks corresponding to this match found, from all Chunks in this line 
         For Each chk As TextChunk In ThisLineChunks 
          sCurrentText = sCurrentText & chk.text 

          'Check if we entered the part where we had found a matching String then get this Chunk (First Chunk) 
          If Not bStart AndAlso sCurrentText.Length - 1 >= iFromChar Then 
           FirstChunk = chk 
           bStart = True 
          End If 

          'Keep getting Text from Chunks while we are in the part where the matching String had been found 
          If bStart And Not bEnd Then 
           sTextInUsedChunks = sTextInUsedChunks & chk.text 
          End If 

          'If we get out the matching String part then get this Chunk (last Chunk) 
          If Not bEnd AndAlso sCurrentText.Length - 1 >= iToChar Then 
           LastChunk = chk 
           bEnd = True 
          End If 

          'If we already have first and last Chunks enclosing the Text where our String pSearchString has been found 
          'then it's time to get the rectangle, GetRectangleFromText Function below this Function, there we extract the pSearchString locations 
          If bStart And bEnd Then 
           FoundMatches.Add(GetRectangleFromText(FirstChunk, LastChunk, pSearchString, sTextInUsedChunks, iFromChar, iToChar, pStrComp)) 
           curPos = curPos + pSearchString.Length 
           bStart = False : bEnd = False 
           Exit For 
          End If 
         Next 
        Next 
       End If 
       sb.Clear() 
       ThisLineChunks.Clear() 
      End If 
      ThisLineChunks.Add(chunk) 
      sb.Append(chunk.text) 
     Next 

     Return FoundMatches 
    End Function 

    Private Function GetRectangleFromText(ByVal FirstChunk As TextChunk, ByVal LastChunk As TextChunk, ByVal pSearchString As String, _ 
           ByVal sTextinChunks As String, ByVal iFromChar As Integer, ByVal iToChar As Integer, ByVal pStrComp As System.StringComparison) As iTextSharp.text.Rectangle 

     'There are cases where Chunk contains extra text at begining and end, we don't want this text locations, we need to extract the pSearchString location inside 
     'for these cases we need to crop this String (left and Right), and measure this excedent at left and right, at this point we don't have any direct way to make a 
     'Transformation from text space points to User Space units, the matrix for making this transformation is not accesible from here, so for these special cases when 
     'the String needs to be cropped (Left/Right) We'll interpolate between the width from Text in Chunk (we have this value in User Space units), then i'll measure Text corresponding 
     'to the same String but in Text Space units, finally from the relation betweeenthese 2 values I get the TransformationValue I need to use for all cases 

     'Text Width in User Space Units 
     Dim LineRealWidth As Single = LastChunk.PosRight - FirstChunk.PosLeft 

     'Text Width in Text Units 
     Dim LineTextWidth As Single = GetStringWidth(sTextinChunks, LastChunk.curFontSize, _ 
                LastChunk.charSpaceWidth, _ 
                ThisPdfDocFonts.Values.ElementAt(LastChunk.FontIndex)) 
     'TransformationValue value for Interpolation 
     Dim TransformationValue As Single = LineRealWidth/LineTextWidth 

     'In the worst case, we'll need to crop left and right: 
     Dim iStart As Integer = sTextinChunks.IndexOf(pSearchString, pStrComp) 

     Dim iEnd As Integer = iStart + pSearchString.Length - 1 

     Dim sLeft As String 
     If iStart = 0 Then sLeft = vbNullString Else sLeft = sTextinChunks.Substring(0, iStart) 

     Dim sRight As String 
     If iEnd = sTextinChunks.Length - 1 Then sRight = vbNullString Else sRight = sTextinChunks.Substring(iEnd + 1, sTextinChunks.Length - iEnd - 1) 

     'Measure cropped Text at left: 
     Dim LeftWidth As Single = 0 
     If iStart > 0 Then 
      LeftWidth = GetStringWidth(sLeft, LastChunk.curFontSize, _ 
               LastChunk.charSpaceWidth, _ 
               ThisPdfDocFonts.Values.ElementAt(LastChunk.FontIndex)) 
      LeftWidth = LeftWidth * TransformationValue 
     End If 

     'Measure cropped Text at right: 
     Dim RightWidth As Single = 0 
     If iEnd < sTextinChunks.Length - 1 Then 
      RightWidth = GetStringWidth(sRight, LastChunk.curFontSize, _ 
               LastChunk.charSpaceWidth, _ 
               ThisPdfDocFonts.Values.ElementAt(LastChunk.FontIndex)) 
      RightWidth = RightWidth * TransformationValue 
     End If 

     'LeftWidth is the text width at left we need to exclude, FirstChunk.distParallelStart is the distance to left margin, both together will give us this LeftOffset 
     Dim LeftOffset As Single = FirstChunk.distParallelStart + LeftWidth 
     'RightWidth is the text width at right we need to exclude, FirstChunk.distParallelEnd is the distance to right margin, we substract RightWidth from distParallelEnd to get RightOffset 
     Dim RightOffset As Single = LastChunk.distParallelEnd - RightWidth 
     'Return this Rectangle 
     Return New iTextSharp.text.Rectangle(LeftOffset, FirstChunk.PosBottom, RightOffset, FirstChunk.PosTop) 

    End Function 

    Private Function GetStringWidth(ByVal str As String, ByVal curFontSize As Single, ByVal pSingleSpaceWidth As Single, ByVal pFont As DocumentFont) As Single 
     Dim chars() As Char = str.ToCharArray() 
     Dim totalWidth As Single = 0 
     Dim w As Single = 0 

     For Each c As Char In chars 
      w = pFont.GetWidth(c)/1000 
      totalWidth += (w * curFontSize + Me.UndercontentCharacterSpacing) * Me.UndercontentHorizontalScaling/100 
     Next 

     Return totalWidth 
    End Function 

    Private Sub DumpState() 
     For Each location As TextChunk In locationalResult 
      location.PrintDiagnostics() 
      Console.WriteLine() 
     Next 
    End Sub 

    Public Overridable Sub RenderText(ByVal renderInfo As TextRenderInfo) Implements ITextExtractionStrategy.RenderText 
     Dim segment As LineSegment = renderInfo.GetBaseline() 
     Dim location As New TextChunk(renderInfo.GetText(), segment.GetStartPoint(), segment.GetEndPoint(), renderInfo.GetSingleSpaceWidth()) 

     With location 

      'Chunk Location: 
      Debug.Print(renderInfo.GetText) 
      .PosLeft = renderInfo.GetDescentLine.GetStartPoint(Vector.I1) 
      .PosRight = renderInfo.GetAscentLine.GetEndPoint(Vector.I1) 
      .PosBottom = renderInfo.GetDescentLine.GetStartPoint(Vector.I2) 
      .PosTop = renderInfo.GetAscentLine.GetEndPoint(Vector.I2) 
      'Chunk Font Size: (Height) 
      .curFontSize = .PosTop - segment.GetStartPoint()(Vector.I2) 
      'Use Font name and Size as Key in the SortedList 
      Dim StrKey As String = renderInfo.GetFont.PostscriptFontName & .curFontSize.ToString 
      'Add this font to ThisPdfDocFonts SortedList if it's not already present 
      If Not ThisPdfDocFonts.ContainsKey(StrKey) Then ThisPdfDocFonts.Add(StrKey, renderInfo.GetFont) 
      'Store the SortedList index in this Chunk, so we can get it later 
      .FontIndex = ThisPdfDocFonts.IndexOfKey(StrKey) 
     End With 
     locationalResult.Add(location) 
    End Sub 

    '* 
    '   * Represents a chunk of text, it's orientation, and location relative to the orientation vector 
    '   

    Public Class TextChunk 
     Implements IComparable(Of TextChunk) 
     '* the text of the chunk 

     Friend text As [String] 
     '* the starting location of the chunk 

     Friend startLocation As Vector 
     '* the ending location of the chunk 

     Friend endLocation As Vector 
     '* unit vector in the orientation of the chunk 

     Friend orientationVector As Vector 
     '* the orientation as a scalar for quick sorting 

     Friend orientationMagnitude As Integer 
     '* perpendicular distance to the orientation unit vector (i.e. the Y position in an unrotated coordinate system) 
     '    * we round to the nearest integer to handle the fuzziness of comparing floats 

     Friend distPerpendicular As Integer 
     '* distance of the start of the chunk parallel to the orientation unit vector (i.e. the X position in an unrotated coordinate system) 

     Friend distParallelStart As Single 
     '* distance of the end of the chunk parallel to the orientation unit vector (i.e. the X position in an unrotated coordinate system) 

     Friend distParallelEnd As Single 
     '* the width of a single space character in the font of the chunk 

     Friend charSpaceWidth As Single 

     Private _PosLeft As Single 

     Private _PosRight As Single 

     Private _PosTop As Single 

     Private _PosBottom As Single 

     Private _curFontSize As Single 

     Private _FontIndex As Integer 

     Public Property FontIndex As Integer 
      Get 
       Return _FontIndex 
      End Get 
      Set(ByVal value As Integer) 
       _FontIndex = value 
      End Set 
     End Property 

     Public Property PosLeft As Single 
      Get 
       Return _PosLeft 
      End Get 
      Set(ByVal value As Single) 
       _PosLeft = value 
      End Set 
     End Property 

     Public Property PosRight As Single 
      Get 
       Return _PosRight 
      End Get 
      Set(ByVal value As Single) 
       _PosRight = value 
      End Set 
     End Property 

     Public Property PosTop As Single 
      Get 
       Return _PosTop 
      End Get 
      Set(ByVal value As Single) 
       _PosTop = value 
      End Set 
     End Property 

     Public Property PosBottom As Single 
      Get 
       Return _PosBottom 
      End Get 
      Set(ByVal value As Single) 
       _PosBottom = value 
      End Set 
     End Property 

     Public Property curFontSize As Single 
      Get 
       Return _curFontSize 
      End Get 
      Set(ByVal value As Single) 
       _curFontSize = value 
      End Set 
     End Property 

     Public Sub New(ByVal str As [String], ByVal startLocation As Vector, ByVal endLocation As Vector, ByVal charSpaceWidth As Single) 
      Me.text = str 
      Me.startLocation = startLocation 
      Me.endLocation = endLocation 
      Me.charSpaceWidth = charSpaceWidth 

      Dim oVector As Vector = endLocation.Subtract(startLocation) 
      If oVector.Length = 0 Then 
       oVector = New Vector(1, 0, 0) 
      End If 
      orientationVector = oVector.Normalize() 
      orientationMagnitude = CInt(Math.Truncate(Math.Atan2(orientationVector(Vector.I2), orientationVector(Vector.I1)) * 1000)) 

      Dim origin As New Vector(0, 0, 1) 
      distPerpendicular = CInt((startLocation.Subtract(origin)).Cross(orientationVector)(Vector.I3)) 

      distParallelStart = orientationVector.Dot(startLocation) 
      distParallelEnd = orientationVector.Dot(endLocation) 
     End Sub 

     Public Sub PrintDiagnostics() 
      Console.WriteLine("Text (@" & Convert.ToString(startLocation) & " -> " & Convert.ToString(endLocation) & "): " & text) 
      Console.WriteLine("orientationMagnitude: " & orientationMagnitude) 
      Console.WriteLine("distPerpendicular: " & distPerpendicular) 
      Console.WriteLine("distParallel: " & distParallelStart) 
     End Sub 

     '* 
     '    * @param as the location to compare to 
     '    * @return true is this location is on the the same line as the other 
     '    

     Public Function SameLine(ByVal a As TextChunk) As Boolean 
      If orientationMagnitude <> a.orientationMagnitude Then 
       Return False 
      End If 
      If distPerpendicular <> a.distPerpendicular Then 
       Return False 
      End If 
      Return True 
     End Function 

     '* 
     '    * Computes the distance between the end of 'other' and the beginning of this chunk 
     '    * in the direction of this chunk's orientation vector. Note that it's a bad idea 
     '    * to call this for chunks that aren't on the same line and orientation, but we don't 
     '    * explicitly check for that condition for performance reasons. 
     '    * @param other 
     '    * @return the number of spaces between the end of 'other' and the beginning of this chunk 
     '    

     Public Function DistanceFromEndOf(ByVal other As TextChunk) As Single 
      Dim distance As Single = distParallelStart - other.distParallelEnd 
      Return distance 
     End Function 

     '* 
     '    * Compares based on orientation, perpendicular distance, then parallel distance 
     '    * @see java.lang.Comparable#compareTo(java.lang.Object) 
     '    

     Public Function CompareTo(ByVal rhs As TextChunk) As Integer Implements System.IComparable(Of TextChunk).CompareTo 
      If Me Is rhs Then 
       Return 0 
      End If 
      ' not really needed, but just in case 
      Dim rslt As Integer 
      rslt = CompareInts(orientationMagnitude, rhs.orientationMagnitude) 
      If rslt <> 0 Then 
       Return rslt 
      End If 

      rslt = CompareInts(distPerpendicular, rhs.distPerpendicular) 
      If rslt <> 0 Then 
       Return rslt 
      End If 

      ' note: it's never safe to check floating point numbers for equality, and if two chunks 
      ' are truly right on top of each other, which one comes first or second just doesn't matter 
      ' so we arbitrarily choose this way. 
      rslt = If(distParallelStart < rhs.distParallelStart, -1, 1) 

      Return rslt 
     End Function 

     '* 
     '    * 
     '    * @param int1 
     '    * @param int2 
     '    * @return comparison of the two integers 
     '    

     Private Shared Function CompareInts(ByVal int1 As Integer, ByVal int2 As Integer) As Integer 
      Return If(int1 = int2, 0, If(int1 < int2, -1, 1)) 
     End Function 


    End Class 

    '* 
    '   * no-op method - this renderer isn't interested in image events 
    '   * @see com.itextpdf.text.pdf.parser.RenderListener#renderImage(com.itextpdf.text.pdf.parser.ImageRenderInfo) 
    '   * @since 5.0.1 
    '   

    Public Sub RenderImage(ByVal renderInfo As ImageRenderInfo) Implements IRenderListener.RenderImage 
     ' do nothing 
    End Sub 
End Class 

をスタックオーバーフローユーザーBorisは同じ質問にhis answerで、その中に小さな問題を解決したと主張しました。

さらに別の問題の文脈では、もう1つの問題が見つかりました。this answer;その答えの文脈で私はC#への簡単な移植を行いました。あなたはその答えの付録として見つけることができます。

0

こんにちは、テキストを置き換えるコードがうまくいけば、クラスmyLocationTextExtractionStrategyのvb.netのコードを#翻訳しました。 は、それはそれです:あなたは `myLocationTextExtractionStrategy()`を書いたり、ライブラリを使用する必要がありますように

private class myLocationTextExtractionStrategy : LocationTextExtractionStrategy 
{ 

    public float UndercontentCharacterSpacing { get; set; } 
    public float UndercontentHorizontalScaling { get; set; } 
    private SortedList<string, DocumentFont> ThisPdfDocFonts = new SortedList<string, DocumentFont>(); 
    private List<TextChunk> locationalResult = new List<TextChunk>(); 

    private bool StartsWithSpace(String inText) 
    { 
    if (string.IsNullOrEmpty(inText)) 
    { 
     return false; 
    } 
    if (inText.StartsWith(" ")) 
    { 
     return true; 
    } 
    return false; 
    } 

    private bool EndsWithSpace(String inText) 
    { 
    if (string.IsNullOrEmpty(inText)) 
    { 
     return false; 
    } 
    if (inText.EndsWith(" ")) 
    { 
     return true; 
    } 
    return false; 
    } 

    public override string GetResultantText() 
    { 
    locationalResult.Sort(); 

    StringBuilder sb = new StringBuilder(); 
    TextChunk lastChunk = null; 

    foreach (var chunk in locationalResult) 
    { 
     if (lastChunk == null) 
     { 
     sb.Append(chunk.text); 
     } 
     else 
     { 
     if (chunk.SameLine(lastChunk)) 
     { 
      float dist = chunk.DistanceFromEndOf(lastChunk); 
      if (dist < -chunk.charSpaceWidth) 
      { 
      sb.Append(" "); 
      } 
      else if (dist > chunk.charSpaceWidth/2.0F && !StartsWithSpace(chunk.text) && !EndsWithSpace(lastChunk.text)) 
      { 
      sb.Append(" "); 
      } 
      sb.Append(chunk.text); 
     } 
     else 
     { 
      sb.Append("\n"); 
      sb.Append(chunk.text); 
     } 
     } 
     lastChunk = chunk; 
    } 
    return sb.ToString(); 
    } 

    public List<iTextSharp.text.Rectangle> GetTextLocations(string pSearchString, System.StringComparison pStrComp) 
    { 
    List<iTextSharp.text.Rectangle> FoundMatches = new List<iTextSharp.text.Rectangle>(); 
    StringBuilder sb = new StringBuilder(); 
    List<TextChunk> ThisLineChunks = new List<TextChunk>(); 
    bool bStart = false; 
    bool bEnd = false; 
    TextChunk FirstChunk = null; 
    TextChunk LastChunk = null; 
    string sTextInUsedChunks = null; 

    foreach (var chunk in locationalResult) 
    { 
     if (ThisLineChunks.Count > 0 && !chunk.SameLine(ThisLineChunks.Last())) 
     { 
     if (sb.ToString().IndexOf(pSearchString, pStrComp) > -1) 
     { 
      string sLine = sb.ToString(); 

      int iCount = 0; 
      int lPos = 0; 
      lPos = sLine.IndexOf(pSearchString, 0, pStrComp); 
      while (lPos > -1) 
      { 
      iCount++; 
      if (lPos + pSearchString.Length > sLine.Length) 
      { 
       break; 
      } 
      else 
      { 
       lPos = lPos + pSearchString.Length; 
      } 
      lPos = sLine.IndexOf(pSearchString, lPos, pStrComp); 
      } 

      int curPos = 0; 
      for (int i = 1; i <= iCount; i++) 
      { 
      string sCurrentText; 
      int iFromChar; 
      int iToChar; 

      iFromChar = sLine.IndexOf(pSearchString, curPos, pStrComp); 
      curPos = iFromChar; 
      iToChar = iFromChar + pSearchString.Length - 1; 
      sCurrentText = null; 
      sTextInUsedChunks = null; 
      FirstChunk = null; 
      LastChunk = null; 

      foreach (var chk in ThisLineChunks) 
      { 
       sCurrentText = sCurrentText + chk.text; 

       if (!bStart && sCurrentText.Length - 1 >= iFromChar) 
       { 
       FirstChunk = chk; 
       bStart = true; 
       } 

       if (bStart && !bEnd) 
       { 
       sTextInUsedChunks = sTextInUsedChunks + chk.text; 
       } 

       if (!bEnd && sCurrentText.Length - 1 >= iToChar) 
       { 
       LastChunk = chk; 
       bEnd = true; 
       } 
       if (bStart && bEnd) 
       { 
       FoundMatches.Add(GetRectangleFromText(FirstChunk, LastChunk, pSearchString, sTextInUsedChunks, iFromChar, iToChar, pStrComp)); 
       curPos = curPos + pSearchString.Length; 
       bStart = false; 
       bEnd = false; 
       break; 
       } 
      } 
      } 
     } 
     sb.Clear(); 
     ThisLineChunks.Clear(); 
     } 
     ThisLineChunks.Add(chunk); 
     sb.Append(chunk.text); 
    } 
    return FoundMatches; 
    } 

    private iTextSharp.text.Rectangle GetRectangleFromText(TextChunk FirstChunk, TextChunk LastChunk, string pSearchString, 
    string sTextinChunks, int iFromChar, int iToChar, System.StringComparison pStrComp) 
    { 
    float LineRealWidth = LastChunk.PosRight - FirstChunk.PosLeft; 

    float LineTextWidth = GetStringWidth(sTextinChunks, LastChunk.curFontSize, 
               LastChunk.charSpaceWidth, 
               ThisPdfDocFonts.ElementAt(LastChunk.FontIndex).Value); 

    float TransformationValue = LineRealWidth/LineTextWidth; 

    int iStart = sTextinChunks.IndexOf(pSearchString, pStrComp); 

    int iEnd = iStart + pSearchString.Length - 1; 

    string sLeft; 
    if (iStart == 0) 
    { 
     sLeft = null; 
    } 
    else 
    { 
     sLeft = sTextinChunks.Substring(0, iStart); 
    } 

    string sRight; 
    if (iEnd == sTextinChunks.Length - 1) 
    { 
     sRight = null; 
    } 
    else 
    { 
     sRight = sTextinChunks.Substring(iEnd + 1, sTextinChunks.Length - iEnd - 1); 
    } 

    float LeftWidth = 0; 
    if (iStart > 0) 
    { 
     LeftWidth = GetStringWidth(sLeft, LastChunk.curFontSize, 
             LastChunk.charSpaceWidth, 
             ThisPdfDocFonts.Values.ElementAt(LastChunk.FontIndex)); 
     LeftWidth = LeftWidth * TransformationValue; 
    } 

    float RightWidth = 0; 
    if (iEnd < sTextinChunks.Length - 1) 
    { 
     RightWidth = GetStringWidth(sRight, LastChunk.curFontSize, 
              LastChunk.charSpaceWidth, 
              ThisPdfDocFonts.Values.ElementAt(LastChunk.FontIndex)); 
     RightWidth = RightWidth * TransformationValue; 
    } 

    float LeftOffset = FirstChunk.distParallelStart + LeftWidth; 
    float RightOffset = LastChunk.distParallelEnd - RightWidth; 
    return new iTextSharp.text.Rectangle(LeftOffset, FirstChunk.PosBottom, RightOffset, FirstChunk.PosTop); 
    } 


    private float GetStringWidth(string str, float curFontSize, float pSingleSpaceWidth, DocumentFont pFont) 
    { 

    char[] chars = str.ToCharArray(); 
    float totalWidth = 0; 
    float w = 0; 

    foreach (Char c in chars) 
    { 
     w = pFont.GetWidth(c)/1000; 
     totalWidth += (w * curFontSize + this.UndercontentCharacterSpacing) * this.UndercontentHorizontalScaling/100; 
    } 

    return totalWidth; 
    } 

    public override void RenderText(TextRenderInfo renderInfo) 
    { 
    LineSegment segment = renderInfo.GetBaseline(); 
    TextChunk location = new TextChunk(renderInfo.GetText(), segment.GetStartPoint(), segment.GetEndPoint(), renderInfo.GetSingleSpaceWidth()); 

    location.PosLeft = renderInfo.GetDescentLine().GetStartPoint()[Vector.I1]; 
    location.PosRight = renderInfo.GetAscentLine().GetEndPoint()[Vector.I1]; 
    location.PosBottom = renderInfo.GetDescentLine().GetStartPoint()[Vector.I2]; 
    location.PosTop = renderInfo.GetAscentLine().GetEndPoint()[Vector.I2]; 
    location.curFontSize = location.PosTop - segment.GetStartPoint()[Vector.I2]; 

    string StrKey = renderInfo.GetFont().PostscriptFontName + location.curFontSize.ToString(); 
    if (!ThisPdfDocFonts.ContainsKey(StrKey)) 
    { 
     ThisPdfDocFonts.Add(StrKey, renderInfo.GetFont()); 
    } 
    location.FontIndex = ThisPdfDocFonts.IndexOfKey(StrKey); 
    locationalResult.Add(location); 
    } 


    private class TextChunk : IComparable<TextChunk> 
    { 
    public string text { get; set; } 
    public Vector startLocation { get; set; } 
    public Vector endLocation { get; set; } 
    public Vector orientationVector { get; set; } 
    public int orientationMagnitude { get; set; } 
    public int distPerpendicular { get; set; } 
    public float distParallelStart { get; set; } 
    public float distParallelEnd { get; set; } 
    public float charSpaceWidth { get; set; } 
    public float PosLeft { get; set; } 
    public float PosRight { get; set; } 
    public float PosTop { get; set; } 
    public float PosBottom { get; set; } 
    public float curFontSize { get; set; } 
    public int FontIndex { get; set; } 


    public TextChunk(string str, Vector startLocation, Vector endLocation, float charSpaceWidth) 
    { 
     this.text = str; 
     this.startLocation = startLocation; 
     this.endLocation = endLocation; 
     this.charSpaceWidth = charSpaceWidth; 

     Vector oVector = endLocation.Subtract(startLocation); 
     if (oVector.Length == 0) 
     { 
     oVector = new Vector(1, 0, 0); 
     } 
     orientationVector = oVector.Normalize(); 
     orientationMagnitude = (int)(Math.Truncate(Math.Atan2(orientationVector[Vector.I2], orientationVector[Vector.I1]) * 1000)); 

     Vector origin = new Vector(0, 0, 1); 
     distPerpendicular = (int)((startLocation.Subtract(origin)).Cross(orientationVector)[Vector.I3]); 

     distParallelStart = orientationVector.Dot(startLocation); 
     distParallelEnd = orientationVector.Dot(endLocation); 
    } 

    public bool SameLine(TextChunk a) 
    { 
     if (orientationMagnitude != a.orientationMagnitude) 
     { 
     return false; 
     } 
     if (distPerpendicular != a.distPerpendicular) 
     { 
     return false; 
     } 
     return true; 
    } 

    public float DistanceFromEndOf(TextChunk other) 
    { 
     float distance = distParallelStart - other.distParallelEnd; 
     return distance; 
    } 

    int IComparable<TextChunk>.CompareTo(TextChunk rhs) 
    { 
     if (this == rhs) 
     { 
     return 0; 
     } 

     int rslt; 
     rslt = orientationMagnitude.CompareTo(rhs.orientationMagnitude); 
     if (rslt != 0) 
     { 
     return rslt; 
     } 

     rslt = distPerpendicular.CompareTo(rhs.distPerpendicular); 
     if (rslt != 0) 
     { 
     return rslt; 
     } 
     rslt = (distParallelStart < rhs.distParallelStart ? -1 : 1); 

     return rslt; 
    } 
    } 

} 
+0

のように見えるようにするには、翻訳を行う必要はありません。上記の私の古い答えでは、私はあなたがファイルの翻訳版を見つけたかもしれないもう一つの答えを参照しました。 – mkl

関連する問題