【发布时间】:2020-10-29 18:40:15
【问题描述】:
我想知道是否有任何方法可以使用 c# .net core 编辑 pdf,只是为了替换一些单词
【问题讨论】:
-
PDF 不是为编辑而设计的。你能得到的最好的方法是在现有文本上绘画。现有文本不重排,由您来匹配字体并与现有文本对齐
标签: .net pdf .net-core .net-standard
我想知道是否有任何方法可以使用 c# .net core 编辑 pdf,只是为了替换一些单词
【问题讨论】:
标签: .net pdf .net-core .net-standard
aspose.pdf 是一款商业产品,可为您提供适用于 .NET Framework、.NET Core、Java 和 C++ 的此功能
【讨论】:
我刚刚找到了这个 nuget 包sautinsoft.document
为了替换这个词,他们在their documentation中有一个例子:
using System.IO;
using SautinSoft.Document;
using System.Linq;
using System.Text.RegularExpressions;
namespace Sample
{
class Sample
{
static void Main(string[] args)
{
FindAndReplace();
}
/// <summary>
/// Find and replace a text using ContentRange.
/// </summary>
/// <remarks>
/// Details: https://sautinsoft.com/products/document/examples/find-replace-content-net-csharp-vb.php
/// </remarks>
public static void FindAndReplace()
{
// Path to a loadable document.
string loadPath = @"..\..\critique.pdf";
// Load a document intoDocumentCore.
DocumentCore dc = DocumentCore.Load(loadPath);
Regex regex = new Regex(@"bean", RegexOptions.IgnoreCase);
//Find "Bean" and Replace everywhere on "Joker :-)"
// Please note, Reverse() makes sure that action replace not affects to Find().
foreach (ContentRange item in dc.Content.Find(regex).Reverse())
{
item.Replace("Joker");
}
// Save our document into PDF format.
string savePath = "Replaced.pdf";
dc.Save(savePath, new PdfSaveOptions());
// Open the result for demonstration purposes.
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(loadPath) { UseShellExecute = true });
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(savePath) { UseShellExecute = true });
}
}
}
真的很简单:)
【讨论】:
Docotic.Pdf library 提供了两种替换页面上静态文本的选项:
复制页面对象并更改特定的文本块。基本样本: https://github.com/BitMiracle/Docotic.Pdf.Samples/tree/master/Samples/Pages%20and%20Navigation/CopyPageObjects
在drawText 方法中,您可以检查 PdfTextData.Text 值并改为绘制另一个文本(替换 target.DrawString(td.GetCharacterCodes()); 调用)
例如,此代码将第一页上所有出现的“have”替换为“has”:
using System.Diagnostics;
namespace BitMiracle.Docotic.Pdf.Samples
{
public static class CopyPageObjects
{
public static void Main()
{
// NOTE:
// When used in trial mode, the library imposes some restrictions.
// Please visit http://bitmiracle.com/pdf-library/trial-restrictions.aspx
// for more information.
const string PathToFile = "CopyPageObjects.pdf";
using (var pdf = new PdfDocument(@"C:\Work\BitMiracle\Docotic\QPdf\Futura_font.pdf"))
{
using (PdfDocument copy = pdf.CopyPages(0, 1))
{
PdfPage sourcePage = copy.Pages[0];
PdfPage copyPage = copy.AddPage();
copyPage.Rotation = sourcePage.Rotation;
copyPage.MediaBox = sourcePage.MediaBox;
if (sourcePage.CropBox != sourcePage.MediaBox)
copyPage.CropBox = sourcePage.CropBox;
PdfCanvas target = copyPage.Canvas;
foreach (PdfPageObject obj in sourcePage.GetObjects())
{
target.SaveState();
setClipRegion(target, obj.ClipRegion);
if (obj.Type == PdfPageObjectType.Path)
{
PdfPath path = (PdfPath)obj;
target.Transform(path.TransformationMatrix);
if (path.PaintMode == PdfDrawMode.Fill || path.PaintMode == PdfDrawMode.FillAndStroke)
setBrush(target.Brush, path.Brush);
if (path.PaintMode == PdfDrawMode.Stroke || path.PaintMode == PdfDrawMode.FillAndStroke)
setPen(target.Pen, path.Pen);
appendPath(target, path);
drawPath(target, path);
}
else if (obj.Type == PdfPageObjectType.Image)
{
PdfPaintedImage image = (PdfPaintedImage)obj;
target.TranslateTransform(image.Position.X, image.Position.Y);
target.Transform(image.TransformationMatrix);
setBrush(target.Brush, image.Brush);
target.DrawImage(image.Image, 0, 0, 0);
}
else if (obj.Type == PdfPageObjectType.Text)
{
PdfTextData text = (PdfTextData)obj;
drawText(target, text);
}
target.RestoreState();
}
copy.RemovePage(0);
copy.Save(PathToFile);
}
}
Process.Start(PathToFile);
}
private static void setClipRegion(PdfCanvas canvas, PdfClipRegion clipRegion)
{
if (clipRegion.IntersectedPaths.Count == 0)
return;
PdfMatrix transformationBefore = canvas.TransformationMatrix;
try
{
foreach (PdfPath clipPath in clipRegion.IntersectedPaths)
{
canvas.ResetTransform();
canvas.Transform(clipPath.TransformationMatrix);
appendPath(canvas, clipPath);
canvas.SetClip(clipPath.ClipMode.Value);
}
}
finally
{
canvas.ResetTransform();
canvas.Transform(transformationBefore);
}
}
private static void setBrush(PdfBrush dst, PdfBrushInfo src)
{
PdfColor color = src.Color;
if (color != null)
dst.Color = color;
dst.Opacity = src.Opacity;
var pattern = src.Pattern;
if (pattern != null)
dst.Pattern = pattern;
}
private static void setPen(PdfPen dst, PdfPenInfo src)
{
PdfColor color = src.Color;
if (color != null)
dst.Color = color;
var pattern = src.Pattern;
if (pattern != null)
dst.Pattern = pattern;
dst.DashPattern = src.DashPattern;
dst.EndCap = src.EndCap;
dst.LineJoin = src.LineJoin;
dst.MiterLimit = src.MiterLimit;
dst.Opacity = src.Opacity;
dst.Width = src.Width;
}
private static void appendPath(PdfCanvas target, PdfPath path)
{
foreach (PdfSubpath subpath in path.Subpaths)
{
foreach (PdfPathSegment segment in subpath.Segments)
{
switch (segment.Type)
{
case PdfPathSegmentType.Point:
target.CurrentPosition = ((PdfPointSegment)segment).Value;
break;
case PdfPathSegmentType.Line:
PdfLineSegment line = (PdfLineSegment)segment;
target.CurrentPosition = line.Start;
target.AppendLineTo(line.End);
break;
case PdfPathSegmentType.Bezier:
PdfBezierSegment bezier = (PdfBezierSegment)segment;
target.CurrentPosition = bezier.Start;
target.AppendCurveTo(bezier.FirstControl, bezier.SecondControl, bezier.End);
break;
case PdfPathSegmentType.Rectangle:
target.AppendRectangle(((PdfRectangleSegment)segment).Bounds);
break;
case PdfPathSegmentType.CloseSubpath:
target.ClosePath();
break;
}
}
}
}
private static void drawPath(PdfCanvas target, PdfPath path)
{
switch (path.PaintMode)
{
case PdfDrawMode.Fill:
target.FillPath(path.FillMode.Value);
break;
case PdfDrawMode.FillAndStroke:
target.FillAndStrokePath(path.FillMode.Value);
break;
case PdfDrawMode.Stroke:
target.StrokePath();
break;
default:
target.ResetPath();
break;
}
}
private static void drawText(PdfCanvas target, PdfTextData td)
{
target.TextRenderingMode = td.RenderingMode;
setBrush(target.Brush, td.Brush);
setPen(target.Pen, td.Pen);
target.TextPosition = PdfPoint.Empty;
target.FontSize = td.FontSize;
target.Font = td.Font;
target.CharacterSpacing = td.CharacterSpacing;
target.WordSpacing = td.WordSpacing;
target.TextHorizontalScaling = td.HorizontalScaling;
target.TranslateTransform(td.Position.X, td.Position.Y);
target.Transform(td.TransformationMatrix);
if (!td.Text.Contains("have"))
target.DrawString(td.GetCharacterCodes());
else
target.DrawString(td.Text.Replace("have", "has"));
}
}
}
隐藏现有文本块并在上方绘制新文本。 您可以尝试在没有边框的只读文本框中绘制新文本:
using (PdfDocument pdf = ..)
{
// "replace" text - hide existing text and draw a new one.
PdfPage page = pdf.Pages[0];
PdfCanvas canvas = page.Canvas;
foreach (PdfTextData word in page.GetWords())
{
if (word.Text == "text_to_replace")
{
PdfRectangle rectangleToHide = word.Bounds;
canvas.Brush.Color = new PdfRgbColor(255, 255, 255);
canvas.DrawRectangle(rectangleToHide, PdfDrawMode.Fill);
// Draw new string in a readonly text box. This solution restricts selection of the old string.
PdfTextBox textBox = page.AddTextBox(rectangleToHide);
textBox.HasBorder = false;
textBox.ReadOnly = true;
textBox.Font = word.Font;
textBox.FontSize = word.FontSize * word.TransformationMatrix.M22;
textBox.Text = "new text";
}
}
pdf.Save(..);
}
【讨论】: