I would like to know if there is any way to edit the pdf using c# .net core, just to replace some words
I would like to know if there is any way to edit the pdf using c# .net core, just to replace some words
Docotic.Pdf library provides two options for replacement of static text on a page:
Copy page objects and change specific text chunks. Basic sample: https://github.com/BitMiracle/Docotic.Pdf.Samples/tree/master/Samples/Pages%20and%20Navigation/CopyPageObjects
In the drawText method you can check PdfTextData.Text value and draw another text instead (replace target.DrawString(td.GetCharacterCodes()); call)
For example, this code replaces all occurrences of "have" on the first page with "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"));
}
}
}
Hide existing text chunk and draw new text above. You can try to draw new text in a readonly textbox without border over rectangle:
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(..);
}
I've just found this nuget package sautinsoft.document
To replace the word, they have an example in 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 });
}
}
}
It's really simple :)
There is aspose.pdf, a commercial product that offers you this feature for .NET Framework, .NET Core, Java and C++