I tried 3 different ways of displaying Page numbers, OnCloseDocument content is not displaying in the page, none of them worked.
My Intention is displaying Page numbers like this
1 of 10
2 0f 10
..............
............
10 of 10
on each page
I know how to display
1
2
3
4
....
10
but don`t know how to display total page number
I`m using OnCloseDocument to display No.of pages count,but the content in it is
not displaying.
public class MyPdfPageEventHelpPageNo : iTextSharp.text.pdf.PdfPageEventHelper
{
protected PdfTemplate total;
protected BaseFont helv;
private bool settingFont = false;
public override void OnOpenDocument(PdfWriter writer, Document document)
{
template= writer.DirectContent.CreateTemplate(100, 100);
bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.NOT_EMBEDDED);
}
public override void OnCloseDocument(PdfWriter writer, Document document)
{
//See below
}
1ST WAY:
public override void OnCloseDocument(PdfWriter writer, Document document)
{
//I create a table with one column like below.
PdfPTable pageNumber2 = new PdfPTable(1);
pageNumber2.TotalWidth = 50;
pageNumber2.HorizontalAlignment = Element.ALIGN_RIGHT;
pageNumber2.AddCell(BuildTable2RightCells("Page " + writer.PageNumber));
pageNumber.AddCell(BuildTable2LeftCells(writer.PageCount));
pageNumber2.WriteSelectedRows(0, -1, 500,
(document.PageSize.GetBottom(140)), cb);
}
2ND WAY:
public override void OnCloseDocument(PdfWriter writer, Document document)
{
ColumnText.ShowTextAligned(template,Element.ALIGN_CENTER,new
Phrase(writer.PageNumber.ToString()), 500, 140, 0);
}
3RD WAY:
public override void OnCloseDocument(PdfWriter writer, Document document)
{
template.BeginText();
template.SetFontAndSize(bf, 8);
template.SetTextMatrix(500, 140);
template.ShowText(Convert.ToString((writer.PageNumber - 1)));
template.EndText();
}
Am I doing anything wrong?
Your second way is probably the simplest way. Below is a very, very slimmed down but working version:
public class MyPdfPageEventHelpPageNo : iTextSharp.text.pdf.PdfPageEventHelper {
public override void OnEndPage(PdfWriter writer, Document document) {
ColumnText.ShowTextAligned(writer.DirectContent, Element.ALIGN_CENTER, new Phrase(writer.PageNumber.ToString()), 500, 140, 0);
}
}
And to use it:
//Create a file on our desktop
string outputFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "OnCloseTest.pdf");
//Standard PDF creation, adjust as needed
using (FileStream fs = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (Document doc = new Document(PageSize.LETTER)) {
using (PdfWriter writer = PdfWriter.GetInstance(doc, fs)) {
//Find our custom event handler
writer.PageEvent = new MyPdfPageEventHelpPageNo();
doc.Open();
//Add text the first page
doc.Add(new Paragraph("Test"));
//Add a new page with more text
doc.NewPage();
doc.Add(new Paragraph("Another Test"));
doc.Close();
}
}
}
EDIT
Sorry, I thought that you were having problems with the basic setup of events, my mistake.
I've only seen two ways to do what you are trying to do, either do two passes or use the PdfTemplate syntax which renders an image as far as I know.
I'd recommend just running two passes, the first just to create your PDF and the second to add your page numbers. You can run your first pass to a MemoryStream so you don't have to hit the disk twice if you want.
PdfReader reader = new PdfReader(outputFile);
using (FileStream fs = new FileStream(secondFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (PdfStamper stamper = new PdfStamper(reader, fs)) {
int PageCount = reader.NumberOfPages;
for (int i = 1; i <= PageCount; i++) {
ColumnText.ShowTextAligned(stamper.GetOverContent(i), Element.ALIGN_CENTER, new Phrase(String.Format("Page {0} of {1}", i, PageCount)), 500, 140, 0);
}
}
}
Here is sample code for for the "Chris Haas" explanation (the two pass method with out writing file into harddisk)
The "copy and paste code" using memorystream for page x of y output
protected void Button2_Click(object sender, EventArgs e)
{
byte[] b = CreatePDF2();
string ss = HttpContext.Current.Request.PhysicalApplicationPath;
string filenamefirst = ss + DateTime.Now.ToString("ddMMyyHHmmss");
string filenamefirstpdf = filenamefirst + ".pdf";
using (PdfReader reader = new PdfReader(b))
{
using (FileStream fs = new FileStream(filenamefirstpdf, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (PdfStamper stamper = new PdfStamper(reader, fs))
{
int PageCount = reader.NumberOfPages;
BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED);
for (int i = 1; i <= PageCount; i++)
{
string sss = String.Format("Page {0} of {1}", i, PageCount);
PdfContentByte over= stamper.GetOverContent(i);
over.BeginText();
over.SetTextMatrix(500, 750);
over.SetFontAndSize(bf, 8);
over.ShowText(sss);
over.EndText();
}
}
}
}
}
private byte[] CreatePDF2()
{
Document doc = new Document(PageSize.LETTER, 50, 50, 50, 50);
using (MemoryStream output = new MemoryStream())
{
PdfWriter wri = PdfWriter.GetInstance(doc, output);
doc.Open();
Paragraph header = new Paragraph("My Document") { Alignment = Element.ALIGN_CENTER };
Paragraph paragraph = new Paragraph("Testing the iText pdf.");
Phrase phrase = new Phrase("This is a phrase but testing some formatting also. \nNew line here.");
Chunk chunk = new Chunk("This is a chunk.");
PdfPTable tab = new PdfPTable(3);
PdfPCell cell = new PdfPCell(new Phrase("Header", new Font(Font.FontFamily.HELVETICA, 24F)));
cell.Colspan = 3;
cell.HorizontalAlignment = 1; //0=Left, 1=Centre, 2=Right //Style
cell.BorderColor = new BaseColor(System.Drawing.Color.Red);
cell.Border = Rectangle.BOTTOM_BORDER; // | Rectangle.TOP_BORDER;
cell.BorderWidthBottom = 3f;
tab.AddCell(cell);
//row 1
for (int i = 1; i < 120; i++)
{
//row 1
tab.AddCell("R1C1");
tab.AddCell("R1C2");
tab.AddCell("R1C3");
//row 2
tab.AddCell("R2C1");
tab.AddCell("R2C2");
tab.AddCell("R2C3");
}
doc.Add(header);
doc.Add(paragraph);
doc.Add(phrase);
doc.Add(chunk);
doc.Add(tab);
doc.Close();
return output.ToArray();
}
}
Related
I am getting a pfd using the older version of itextsharp with this code
string Oldfile = #"C:/test.pdf"; // Gets the Template
(new FileInfo("C:/C:/test.pdf")).Directory.Create(); // Go create this folder if it's not there
string NewFile = "C:/test.pdf";
PdfReader reader = new PdfReader(Oldfile);
iTextSharp.text.Rectangle Size = reader.GetPageSizeWithRotation(1);
Document document = new Document(Size);
// MemoryStream memory_stream = new MemoryStream();
FileStream fs = new FileStream(NewFile, FileMode.Create, FileAccess.Write);
PdfWriter weiter = PdfWriter.GetInstance(document, fs);
document.Open();
PdfContentByte cb = weiter.DirectContent;
PdfImportedPage page = weiter.GetImportedPage(reader, 1);
//PdfImportedPage page2 = weiter.GetImportedPage(reader, 2);
cb.AddTemplate(page, 0, 0);
The problem I am having is when it gets that file it has 2 pages in that pdf but it only gets the 1st page and adds lines and saves the only 1st page of the pdf I want to be able to grab both of them or is there a way to merge them after wards
I bet you need to iterate all pages.
using System;
using System.IO;
using System.Collections.Generic;
using iTextSharp.text;
using iTextSharp.text.pdf;
namespace TestAnything
{
class Program
{
static void Main(string[] args)
{
List<string> filesToMerge = new List<string> { #"c:\temp\1.pdf", #"c:\temp\2.pdf" };
FileInfo destinationFile = new FileInfo(#"c:\temp\merge.pdf");
if (File.Exists(destinationFile.FullName))
File.Delete(destinationFile.FullName);
MergeFiles(filesToMerge, destinationFile);
}
public static void MergeFiles(List<string> sourceFiles, FileInfo destinationFile)
{
if (sourceFiles == null || sourceFiles.Count == 0)
throw new ArgumentNullException("blahhh.");
PdfReader reader = new PdfReader(sourceFiles[0]);
Document document = new Document(reader.GetPageSizeWithRotation(1));
PdfCopy writer = new PdfCopy(document, new FileStream(destinationFile.FullName, FileMode.Create));
document.Open();
try
{
foreach (string sourceFile in sourceFiles)
{
reader = new PdfReader(sourceFile);
reader.ConsolidateNamedDestinations();
for (int x = 1; x <= reader.NumberOfPages; x++)
writer.AddPage(writer.GetImportedPage(reader, x));
PRAcroForm form = reader.AcroForm;
if (form != null)
writer.CopyAcroForm(reader);
}
}
finally
{
if (document.IsOpen())
document.Close();
}
}
}
}
I have a pdf file with some data in it. Now, I want to use this existing pdf file and insert a table into it. Then I want to save the file with a different file name so that the existing pdf file remains the same as it was before.
Note: the existing pdf file was not created using iTextSharp. it was randomly downloaded. I have to use the existing pdf file like a template.
public void Main(List<string> jobpath)
{
string oldpath = #"C:\Files\sample_new.pdf";
string newpath = #"C:\Files\sample_new_1.pdf";
PdfReader reader = new PdfReader(oldpath);
Rectangle size = reader.GetPageSizeWithRotation(1);
Document doc = new Document(size);
FileStream fs = new FileStream(newpath, FileMode.Create, FileAccess.Write);
PdfWriter writer = PdfWriter.GetInstance(doc, fs);
doc.Open();
foreach (var list in jobpath)
{
cb.BeginText();
doc.NewPage();
doc.Open();
PdfPTable table = new PdfPTable(1);
table.HorizontalAlignment = Element.ALIGN_CENTER;
table.TotalWidth = 400f;
float[] widths = new float[] { 2f };
table.SetWidths(widths);
table.SpacingBefore = 40f;
table.SpacingAfter = 30f;
PdfPCell cell = new PdfPCell();
cell.Colspan = 3;
cell.HorizontalAlignment = 1;
table.AddCell(list);
doc.Add(table);
PdfImportedPage page = writer.GetImportedPage(reader, 1);
}
doc.Close();
}
With the above code I am able to add the table, but the contents of the old file is not getting copied in the new file.
With the following code I was able to add the content of an existing pdf into the new one. In this example only the first page was added.
string oldpath = #"C:\Files\sample_new.pdf";
string newpath = #"C:\Files\sample_new_1.pdf";
PdfReader reader = new PdfReader(oldpath);
iTextSharp.text.Rectangle size = reader.GetPageSizeWithRotation(1);
Document doc = new Document(size);
FileStream fs = new FileStream(newpath, FileMode.Create, FileAccess.Write);
PdfWriter writer = PdfWriter.GetInstance(doc, fs);
doc.Open();
PdfContentByte cb = writer.DirectContent;
PdfImportedPage page = writer.GetImportedPage(reader, 1);
cb.AddTemplate(page, 0, 0);
foreach (var list in jobpath)
{
doc.NewPage();
doc.Open();
PdfPTable table = new PdfPTable(1);
table.HorizontalAlignment = Element.ALIGN_CENTER;
table.TotalWidth = 400f;
float[] widths = new float[] { 2f };
table.SetWidths(widths);
table.SpacingBefore = 40f;
table.SpacingAfter = 30f;
PdfPCell cell = new PdfPCell();
cell.Colspan = 3;
cell.HorizontalAlignment = 1;
table.AddCell(list);
doc.Add(table);
}
doc.Close();
I am trying to crop pdf 5 mm from every edge i.e top,bottom,right and left. I tried with below code
public void TrimPdf(string sourceFilePath, string outputFilePath)
{
PdfReader pdfReader = new PdfReader(sourceFilePath);
float widthTo_Trim = iTextSharp.text.Utilities.MillimetersToPoints(5);
using (FileStream output = new FileStream(outputFilePath, FileMode.Create, FileAccess.Write))
using (PdfStamper pdfStamper = new PdfStamper(pdfReader, output))
{
for (int page = 1; page <= pdfReader.NumberOfPages; page++)
{
Rectangle cropBox = pdfReader.GetCropBox(page);
cropBox.Left += widthTo_Trim;
cropBox.Right += widthTo_Trim;
cropBox.Top += widthTo_Trim;
cropBox.Bottom += widthTo_Trim;
pdfReader.GetPageN(page).Put(PdfName.CROPBOX, new PdfRectangle(cropBox));
}
}
}
By using this code i am Able to Crop only Left and Bottom part. unable to crop top and right side
How can i get desire result ?
This solved my problem by using Below code
public void TrimLeftandRightFoall(string sourceFilePath, string outputFilePath, float cropwidth)
{
PdfReader pdfReader = new PdfReader(sourceFilePath);
float width = (float)GetPDFwidth(sourceFilePath);
float height = (float)GetPDFHeight(sourceFilePath);
float widthTo_Trim = iTextSharp.text.Utilities.MillimetersToPoints(cropwidth);
PdfRectangle rectLeftside = new PdfRectangle(widthTo_Trim, widthTo_Trim, width-widthTo_Trim , height-widthTo_Trim);
using (var output = new FileStream(outputFilePath, FileMode.CreateNew, FileAccess.Write))
{
// Create a new document
Document doc = new Document();
// Make a copy of the document
PdfSmartCopy smartCopy = new PdfSmartCopy(doc, output);
// Open the newly created document
doc.Open();
// Loop through all pages of the source document
for (int i = 1; i <= pdfReader.NumberOfPages; i++)
{
// Get a page
var page = pdfReader.GetPageN(i);
page.Put(PdfName.MEDIABOX, rectLeftside);
var copiedPage = smartCopy.GetImportedPage(pdfReader, i);
smartCopy.AddPage(copiedPage);
}
doc.Close();
}
}
here is What i want i want to add page numbers to every pdf page that i generated on the fly.
i used on end page method but it did not worked out even when i added the doc bottom margin.
I decided to add the page numbers after the pdf is generated from the file path.
here is my code for generating pdf:
Document doc = new Document(iTextSharp.text.PageSize.LETTER, 10, 10, 42, 35);
PdfWriter wri = PdfWriter.GetInstance(doc, new FileStream("t5.pdf", FileMode.Create));
doc.Open();//Open Document to write
iTextSharp.text.Font font8 = FontFactory.GetFont("ARIAL", 7);
Paragraph paragraph = new Paragraph("Some content");
doc.Add(paragraph);
doc.Add(paragraph);// add paragraph to the document
doc.Close();
FileStream stream = File.OpenRead("t5.pdf");
byte[] fileBytes = new byte[stream.Length];
stream.Read(fileBytes, 0, fileBytes.Length);
stream.Close();
AddPageNumbers(fileBytes);
using (Stream file = File.OpenWrite("t5.pdf"))
{
file.Write(fileBytes, 0, fileBytes.Length);
}
}
and her is my add pagenumbers method:
MemoryStream ms = new MemoryStream();
PdfReader reader = new PdfReader(pdf);
int n = reader.NumberOfPages;
iTextSharp.text.Rectangle psize = reader.GetPageSize(1);
Document document = new Document(psize, 50, 50, 50, 50);
PdfWriter writer = PdfWriter.GetInstance(document, ms);
document.Open();
PdfContentByte cb = writer.DirectContent;
int p = 0;
for (int page = 1; page <= reader.NumberOfPages; page++)
{
document.NewPage();
p++;
PdfImportedPage importedPage = writer.GetImportedPage(reader, page);
cb.AddTemplate(importedPage, 0, 0);
BaseFont bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
cb.BeginText();
cb.SetFontAndSize(bf, 10);
cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, +p + "/" + n, 100, 450, 0);
cb.EndText();
}
document.Close();
return ms.ToArray();
how ever it does not add the page numbers to the pdf document so what is the alternatives here? what can i do.
When posting a question here, please only post the smallest amount of code possible. Your "create a sample PDF with multiple pages" is 116 lines long. Inside of it you've got complicated PdfPTable and DataTable logic that is 100% unrelated to the problem. Instead, the following 13 lines is enough to make a multiple page PDF:
//Create a sample multiple page PDF and place it on the desktop
var outputFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "t5.pdf");
using (var fs = new FileStream(outputFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, fs)) {
doc.Open();
for (var i = 0; i < 1000; i++) {
doc.Add(new Paragraph(String.Format("This is paragraph #{0}", i)));
}
doc.Close();
}
}
}
Second, get rid of try/catch. Those are great for production (sometimes) but at the development level that's why we have IDEs and compilers, they'll tell us specifically what's wrong.
Now on to the bigger problem, you need to keep these two processes separate from each other. Every single brace and object from part part #1 must be closed, done and accounted for. Part #2 then needs to be fed a completely valid PDF but neither of the two parts should be "aware" of each other or depend on each other.
Since you just borrowed some code that wasn't intended for what you're trying to do I'm going to also ignore that and use some code that I know specifically will work. Also, since you're open to using a MemoryStream in the first place I'm just going to avoid writing to disk until I need to. Below is a full working sample that creates a multiple page and then adds page numbers in a second pass.
//Will hold our PDF as a byte array
Byte[] bytes;
//Create a sample multiple page PDF, nothing special here
using (var ms = new MemoryStream()) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, ms)) {
doc.Open();
for (var i = 0; i < 1000; i++) {
doc.Add(new Paragraph(String.Format("This is paragraph #{0}", i)));
}
doc.Close();
}
}
//Store our bytes before
bytes = ms.ToArray();
}
//Read our sample PDF and apply page numbers
using (var reader = new PdfReader(bytes)) {
using (var ms = new MemoryStream()) {
using (var stamper = new PdfStamper(reader, ms)) {
int PageCount = reader.NumberOfPages;
for (int i = 1; i <= PageCount; i++) {
ColumnText.ShowTextAligned(stamper.GetOverContent(i), Element.ALIGN_CENTER, new Phrase(String.Format("Page {0} of {1}", i, PageCount)), 100, 10 , 0);
}
}
bytes = ms.ToArray();
}
}
var outputFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "t5.pdf");
System.IO.File.WriteAllBytes(outputFile, bytes);
I had been used the first code create a water mark and removed and it work perfect
private void Form1_Load(object sender, EventArgs e) {
string workingFolder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string startFile = Path.Combine(workingFolder, "StartFile.pdf");
string watermarkedFile = Path.Combine(workingFolder, "Watermarked.pdf");
string unwatermarkedFile = Path.Combine(workingFolder, "Un-watermarked.pdf");
string watermarkText = "This is a test";
//SECTION 1
//Create a 5 page PDF, nothing special here
using (FileStream fs = new FileStream(startFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (Document doc = new Document(PageSize.LETTER)) {
using (PdfWriter witier = PdfWriter.GetInstance(doc, fs)) {
doc.Open();
for (int i = 1; i <= 5; i++) {
doc.NewPage();
doc.Add(new Paragraph(String.Format("This is page {0}", i)));
}
doc.Close();
}
}
}
//SECTION 2
//Create our watermark on a separate layer. The only different here is that we are adding the watermark to a PdfLayer which is an OCG or Optional Content Group
PdfReader reader1 = new PdfReader(startFile);
using (FileStream fs = new FileStream(watermarkedFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (PdfStamper stamper = new PdfStamper(reader1, fs)) {
int pageCount1 = reader1.NumberOfPages;
//Create a new layer
PdfLayer layer = new PdfLayer("WatermarkLayer", stamper.Writer);
for (int i = 1; i <= pageCount1; i++) {
iTextSharp.text.Rectangle rect = reader1.GetPageSize(i);
//Get the ContentByte object
PdfContentByte cb = stamper.GetUnderContent(i);
//Tell the CB that the next commands should be "bound" to this new layer
cb.BeginLayer(layer);
cb.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED), 50);
PdfGState gState = new PdfGState();
gState.FillOpacity = 0.25f;
cb.SetGState(gState);
cb.SetColorFill(BaseColor.BLACK);
cb.BeginText();
cb.ShowTextAligned(PdfContentByte.ALIGN_CENTER, watermarkText, rect.Width / 2, rect.Height / 2, 45f);
cb.EndText();
//"Close" the layer
cb.EndLayer();
}
}
}
//SECTION 3
//Remove the layer created above
//First we bind a reader to the watermarked file, then strip out a bunch of things, and finally use a simple stamper to write out the edited reader
PdfReader reader2 = new PdfReader(watermarkedFile);
//NOTE, This will destroy all layers in the document, only use if you don't have additional layers
//Remove the OCG group completely from the document.
//reader2.Catalog.Remove(PdfName.OCPROPERTIES);
//Clean up the reader, optional
reader2.RemoveUnusedObjects();
//Placeholder variables
PRStream stream;
String content;
PdfDictionary page;
PdfArray contentarray;
//Get the page count
int pageCount2 = reader2.NumberOfPages;
//Loop through each page
for (int i = 1; i <= pageCount2; i++) {
//Get the page
page = reader2.GetPageN(i);
//Get the raw content
contentarray = page.GetAsArray(PdfName.CONTENTS);
if (contentarray != null) {
//Loop through content
for (int j = 0; j < contentarray.Size; j++) {
//Get the raw byte stream
stream = (PRStream)contentarray.GetAsStream(j);
//Convert to a string. NOTE, you might need a different encoding here
content = System.Text.Encoding.ASCII.GetString(PdfReader.GetStreamBytes(stream));
//Look for the OCG token in the stream as well as our watermarked text
if (content.IndexOf("/OC") >= 0 && content.IndexOf(watermarkText) >= 0) {
//Remove it by giving it zero length and zero data
stream.Put(PdfName.LENGTH, new PdfNumber(0));
stream.SetData(new byte[0]);
}
}
}
}
//Write the content out
using (FileStream fs = new FileStream(unwatermarkedFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (PdfStamper stamper = new PdfStamper(reader2, fs)) {
}
}
this.Close();
}
}
}
but when I used digital sign some time when a I tried to remove the watermark some page lost the information , them I'm would like to used the PdfLayerRemover and I change to C# but when I made this
PdfDictionary ocProps = _reader.Catalog.GetAsDict(PdfName.OCPROPERTIES);
I had been used the first code create a water mark and removed and it work perfect but when I used digital sign some time when a I tried to remove the watermark some page lost the information , them I'm would like to used the PdfLayerRemover and I change to C# but when I made this
PdfDictionary ocProps = _reader.Catalog.GetAsDict(PdfName.OCPROPERTIES);
always get null value and the pdf has the watermark??? please if can help me and the pdf has ocpproperties because when I use this works but it remove additional information . but the way Itextshap version 5.5.2.0
if (content.IndexOf("/OC") >= 0 && content.IndexOf(watermarkText) >= 0) {
//Remove it by giving it zero length and zero data
stream.Put(PdfName.LENGTH, new PdfNumber(0));
stream.SetData(new byte[0]);
}