C# 使用Itextsharp替换pdf文件中的文本
尝试使用以前创建的代码替换pdf格式的文本。但这一行的下划线为红色“myLocationTextExtractionStrategy strategy=new myLocationTextExtractionStrategy;”。我需要创建一些自定义策略还是使用一些库C# 使用Itextsharp替换pdf文件中的文本,c#,itext,C#,Itext,尝试使用以前创建的代码替换pdf格式的文本。但这一行的下划线为红色“myLocationTextExtractionStrategy strategy=new myLocationTextExtractionStrategy;”。我需要创建一些自定义策略还是使用一些库 class Program { static iTextSharp.text.pdf.PdfStamper stamper = null; static void Main(string[] args) {
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)
{
}
}
}
源代码中使用的myLocationTextExtractionStrategy类似乎来自问题中共享的堆栈溢出用户
他在VB.Net中编写了:
公共类myLocationTextExtractionStrategy
实现ITextraction策略
'*设置为true进行调试
私有_UndercontentCharacterSpacing=0
私有_内容不足权限缩放=0
Private ThisPdfDocFonts作为字符串的排序列表,DocumentFont
公共共享转储\状态为布尔值=False
“*找到的所有文本的摘要
Private locationalResult作为TextChunk的新列表
'*
'*创建新的文本提取渲染器。
'
公共亚新
ThisPdfDocFonts=新排序的字符串列表,DocumentFont
端接头
'*
'*@请参见com.itextpdf.text.pdf.parser.RenderListenerbeginTextBlock
'
公共可重写子BeginTextBlock实现ITextractionStrategy.BeginTextBlock
端接头
'*
'*@请参见com.itextpdf.text.pdf.parser.RenderListenerendTextBlock
'
公共可重写子EndTextBlock实现ITextractionStrategy.EndTextBlock
端接头
'*
'*@param str
'*@如果字符串以空格字符开头,则返回true;如果字符串为空或以非空格字符开头,则返回false
'
私有函数StartsWithSpaceByVal str作为[String]作为布尔值
如果str.Length=0,则
返回错误
如果结束
返回str0=c
端函数
'*
'*@param str
'*@如果字符串以空格字符结尾,则返回true;如果字符串为空或以非空格字符结尾,则返回false
'
私有函数EndsWithSpaceByVal str作为布尔值[String]
如果str.Length=0,则
返回错误
如果结束
返回字符串长度-1=c
端函数
公共财产内容不足字符间距
收到
返回_UndercontentCharacterSpacing
结束
退步值
_UndercontentCharacterSpacing=值
端集
端属性
公共财产未达到法定水平
收到
返回内容不足权限缩放
结束
退步值
_未经授权的水平缩放=值
端集
端属性
公共可重写函数GetResultantText作为[String]实现ITextractionStrategy.GetResultantText
如果是DUMP_状态,那么
转储状态
如果结束
locationalResult.Sort
使某人成为新的架线工
将lastChunk设置为TextChunk=Nothing
将每个区块作为locationalResult中的TextChunk
如果lastChunk什么都不是
给某人发短信
其他的
如果chunk.SameLinelastChunk那么
Dim dist As Single=chunk.DistanceFromEndOflastChunk
如果dist<-chunk.charSpaceWidth,则
某人,某人
'仅当前一个字符串的尾随字符不是空格,而当前字符串的前导字符不是空格时,才插入空格
ElseIf dist>chunk.charSpaceWidth/2.0F且不以spacechunk.text开始,也不以spacelastchunk.text结束
某人,某人
如果结束
给某人发短信
其他的
某人
给某人发短信
如果结束
如果结束
lastChunk=chunk
下一个
使某人恢复原状
端函数
公共函数GetTextLocationsByVal pSearchString作为字符串,ByVal pStrComp作为System.StringComparison作为iTextSharp.text.Rectangle的列表
Dim FoundMatches作为iTextSharp.text.Rectangle的新列表
使某人成为新的架线工
Dim ThisLineChunks As ListOf TextChunk=新建ListOf TextChunk
将开始变暗为布尔值,将弯曲变为布尔值
将FirstChunk设置为TextChunk=Nothing,将LastChunk设置为TextChunk=Nothing
Dim sTextInUsedChunks As String=vbNullString
将每个区块作为locationalResult中的TextChunk
如果ThisLineChunks.Count>0且也不是chunk.SameLineThisLineChunks.Last,则
如果sb.ToString.indexofSearchString,pStrComp>-1,则
作为字符串的Dim sLine=sb.ToString
'检查搜索字符串在此行中出现的次数:
Dim I计数为整数=0
作为整数的Dim LPO
lPos=s
Line.indexofSearchString,0,pStrComp
当LPO>-1时执行此操作
i计数+=1
如果lPos+pSearchString.Length>sLine.Length,则退出Do Else lPos=lPos+pSearchString.Length
lPos=sLine.INDEXOFSEARCHSTRING,lPos,pStrComp
环
'处理在此文本行中找到的每个匹配项:
Dim curPos作为整数=0
对于i作为整数=1的i计数
Dim sCurrentText作为字符串,iFromChar作为整数,iToChar作为整数
iFromChar=sLine.indexofsearchstring、curPos、pStrComp
curPos=iFromChar
iToChar=iFromChar+pSearchString.Length-1
sCurrentText=vbNullString
sTextInUsedChunks=vbNullString
FirstChunk=无
LastChunk=无
'从此行的所有块中获取与找到的匹配对应的第一个和最后一个块
对于每个chk作为ThisLineChunks中的TextChunk
sCurrentText=sCurrentText&chk.text
'检查是否输入了找到匹配字符串的部分,然后首先获取该块
如果不是bStart and也不是sCurrentText.Length-1>=iFromChar,那么
FirstChunk=chk
b开始=正确
如果结束
'在找到匹配字符串的部分时,继续从块中获取文本
如果开始而不是弯曲,那么
sTextInUsedChunks=sTextInUsedChunks&chk.text
如果结束
'如果我们得到匹配的字符串部分,那么就得到最后一个块
如果不弯曲,也可以使用currentText.Length-1>=iToChar,则
LastChunk=chk
弯曲=真
如果结束
'如果在找到字符串pSearchString的地方已经有了包含文本的第一个和最后一个块
'然后是时候获取矩形了,在这个函数下面的GetRectangleFromText函数中,我们提取pSearchString位置
如果开始弯曲,那么
FoundMatches.AddGetRectangleFromTextFirstChunk、LastChunk、pSearchString、sTextInUsedChunks、iFromChar、iToChar、pStrComp
curPos=curPos+pSearchString.长度
b开始=错误:弯曲=错误
退出
如果结束
下一个
下一个
如果结束
清除某人
这是块,明白了吗
如果结束
ThisLineChunks.Addchunk
给某人发短信
下一个
返回匹配项
端函数
私有函数GetRectangleFromTextByVal FirstChunk作为TextChunk,ByVal LastChunk作为TextChunk,ByVal pSearchString作为String_
ByVal sTextinChunks作为字符串,ByVal iFromChar作为整数,ByVal iToChar作为整数,ByVal pStrComp作为System.StringComparison作为iTextSharp.text.Rectangle
“在某些情况下,区块在开始和结束时都包含额外的文本,我们不需要这些文本位置,我们需要提取其中的pSearchString位置
对于这些情况,我们需要在左右两边裁剪这根弦,并在左右两边测量这根弦的长度,在这一点上,我们没有任何直接的方法来做出判断
'从文本空间点到用户空间单位的转换,无法从此处访问用于进行此转换的矩阵,因此对于这些特殊情况
'字符串需要左/右裁剪,我们将在区块中文本的宽度之间进行插值,这个值以用户空间单位表示,然后我将测量相应的文本
'到相同的字符串,但以文本空间为单位,最后从这两个值之间的关系中,我得到所有情况下需要使用的TransformationValue
'以用户空间单位表示的文本宽度
将LineRealWidth设置为Single=LastChunk.PosRight-FirstChunk.PosLeft
'以文本单位表示的文本宽度
将LineTextWidth设置为Single=GetStringWidthsTextinChunks,LastChunk.curFontSize_
LastChunk.charSpaceWidth_
ThisPdfDocFonts.Values.ElementAtLastChunk.FontIndex
'用于插值的TransformationValue
Dim TransformationValue为Single=LineRealWidth/LineTextWidth
“在最坏的情况下,我们需要左右裁剪:
Dim iStart As
整数=sTextinChunks.indexofsearchstring,pStrComp
Dim iEnd As Integer=iStart+PSEARCSTRING.Length-1
像绳子一样变暗
如果iStart=0,则sLeft=vbNullString,否则sLeft=sTextinChunks.Substring0,iStart
暗如弦
如果iEnd=sTextinChunks.Length-1,则sRight=vbNullString,否则sRight=sTextinChunks.SubstringiEnd+1,sTextinChunks.Length-iEnd-1
'测量左侧剪切的文本:
将LeftWidth设置为单个=0
如果iStart>0,则
LeftWidth=GetStringWidthsLeft,LastChunk.curFontSize_
LastChunk.charSpaceWidth_
ThisPdfDocFonts.Values.ElementAtLastChunk.FontIndex
LeftWidth=LeftWidth*TransformationValue
如果结束
'在右侧测量裁剪的文本:
将右侧宽度调整为单个=0
如果iEnd在另一个问题的背景下,我发现了另一个问题,confer;在该答案的上下文中,我还对C做了一个快速移植,您可以在该答案的附录中找到。嗨,替换文本的代码工作得很好,我已经在C中翻译了类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;
}
}
}