PDFNet trying to add a text not working - c#

I am basically trying out PDFNet and tweaking one of the samples of PDFNet. Here is the code:
PDFNet.Initialize();
// Relative path to the folder containing test files.
string input_path = "../../../../TestFiles/";
string output_path = "../../../../TestFiles/Output/";
PDFDoc doc = new PDFDoc(input_path + "form1.pdf");
for (int index = 1; index <= doc.GetPageCount(); index++)
{
Page page = doc.GetPage(index);
ElementBuilder eb = new ElementBuilder(); // ElementBuilder is used to build new Element objects
eb.Reset(); // Reset GState to default
ElementWriter writer = new ElementWriter(); // ElementWriter is used to write Elements to the page
writer.Begin(page);
// Begin writing a block of text
string data = "Page " + index;
Element element = eb.CreateTextRun(data, Font.Create(doc, Font.StandardType1Font.e_times_roman, true), 100.0);
element.SetTextMatrix(10, 0, 0, 10, 100, 100);
GState gstate = element.GetGState();
gstate.SetTextRenderMode(GState.TextRenderingMode.e_stroke_text);
gstate.SetStrokeColorSpace(pdftron.PDF.ColorSpace.CreateDeviceRGB());
gstate.SetStrokeColor(new pdftron.PDF.ColorPt(1, 0, 0));
writer.WriteElement(element);
writer.End();
writer.Dispose(); // save changes to the current page
}
doc.Save(output_path + "element_builder.pdf", SDFDoc.SaveOptions.e_linearized);
doc.Close();
But problem is, no text is added to element_builder.pdf. It is just copied as it is and looks same as form1.pdf. Can anybody help me out?
This is the link to PDFNet http://www.pdftron.com/pdfnet/downloads.html
I am using 64 bit version for .Net 4.0

It seems that you are missing the calls eb.CreateTextBegin() and eb.CreateTextEnd(). You should try something like this:
PDFNet.Initialize();
// Relative path to the folder containing test files.
string input_path = "../../../../TestFiles/";
string output_path = "../../../../TestFiles/Output/";
PDFDoc doc = new PDFDoc(input_path + "form1.pdf");
ElementWriter writer = new ElementWriter();
ElementBuilder eb = new ElementBuilder();
for (int index = 1; index <= doc.GetPageCount(); index++)
{
Page page = doc.GetPage(index);
writer.Begin(page);
eb.Reset();
// Begin writing a block of text
string data = "Page " + index;
Element element = eb.CreateTextBegin(Font.Create(doc, Font.StandardType1Font.e_times_roman, true), 10.0);
writer.WriteElement(element);
eb.CreateTextRun(data);
element.SetTextMatrix(10, 0, 0, 10, 100, 100);
GState gstate = element.GetGState();
gstate.SetTextRenderMode(GState.TextRenderingMode.e_fill_text);
gstate.SetStrokeColorSpace(pdftron.PDF.ColorSpace.CreateDeviceRGB());
gstate.SetStrokeColor(new pdftron.PDF.ColorPt(1, 0, 0));
writer.WriteElement(element);
writer.WriteElement(eb.CreateTextEnd());
writer.End();
}
writer.Dispose();
eb.Dispose();
doc.Save(output_path + "element_builder.pdf", SDFDoc.SaveOptions.e_linearized);
doc.Close();
Btw. a possibly simpler way to add text to an existing page may be to use 'pdftron.PDF.Stamper' as shown in Stamper sample.

Related

I don't want to rotate page but iTextSharp programmatically rotates my pages

I have pdf files in the "C:\\pdfs\\" directory. I want to get these pdf files and insert metadatas from the meta_data.txt file. With my lock of iTextSharp knowledge, I coded like this:
var pdf_files = Directory.GetFiles("C:\\pdfs\\", "*.pdf");
var i = 0;
foreach (var pdf_file in pdf_files)
{
var read = new PdfReader(pdf_file);
var size = read.GetPageSizeWithRotation(1);
var document = new Document(size);
var write = PdfWriter.GetInstance(document, new FileStream("C:\\temp\\" + "file_" + i, FileMode.Create, FileAccess.Write));
var datas = File.ReadAllLines("C:\\pdfs\\" + #"meta_data.txt");
var str = datas[i].Split('#');
document.AddTitle(str[1]);
document.AddSubject(str[2]);
document.AddCreator(str[3]);
document.AddAuthor(str[4]);
document.AddKeywords(str[5]);
document.Open();
var cb = write.DirectContent;
for (var pageNum = 1; pageNum <= read.NumberOfPages; pageNum++)
{
document.NewPage();
var page = write.GetImportedPage(read, pageNum);
cb.AddTemplate(page, 0, 0);
}
document.Close();
read.Close();
File.Delete(pdf_file);
File.Move("C:\\temp\\" + "file_" + i, "C:\\created\\" + "file_" + i);
i++;
}
This codes get an instance of main pdf files, while creation to temp directory, injects metadatas and later move the created directory. I don't find more practical method than this.
Anyway, in some pdf files (generated as an original pdf file) there is no problem like this:
But some other pdf files (generated from scan or very old dated pdf file) are rotated programmatically. And it seems disgusting like this:
Worse than all, I don't know how I fix the problem. Could you help me how I manage this problem.
The correct answer to this question looks like this:
PdfReader reader = new PdfReader(src);
using (PdfStamper stamper = new PdfStamper(reader,
new FileStream("C:\\temp\\" + "file_" + i, FileMode.Create, FileAccess.Write))) {
Dictionary<String, String> info = reader.Info;
info["Title"] = "Hello World stamped";
info["Subject"] = "Hello World with changed metadata";
info["Keywords"] = "iText in Action, PdfStamper";
info["Creator"] = "Silly standalone example";
info["Author"] = "Bruno Lowagie";
stamper.MoreInfo = info;
}
Habip OĞUZ ignored what I wrote in Chapter 6 of "iText in Action - Second Edition", namely that using Document, PdfWriter and AddTemplate() is wrong when you want to manipulate a single existing PDF. By using AddTemplate(), you throw away plenty of features, such as interactivity, structure, and so on. You also create a PDF that is suboptimal because every page will be stored as a Form XObject.

Why is my table not being generated on my PDF file using iTextSharp?

I'm trying to add a table to the PDF file I'm generating. I can add stuff "directly" but want to put the various paragraphs or phrases in table cells to get everything to align nicely.
The following code should add three paragraphs "free-form" first, then the same three in a table. However, only the first three display - the table is nowhere to be seen. Here's the code:
try
{
using (var ms = new MemoryStream())
{
using (var doc = new Document(PageSize.A4, 50, 50, 25, 25))
{
using (var writer = PdfWriter.GetInstance(doc, ms))
{
doc.Open();
var titleFont = FontFactory.GetFont(FontFactory.COURIER_BOLD, 11, BaseColor.BLACK);
var docTitle = new Paragraph("UCSC Direct - Direct Payment Form", titleFont);
doc.Add(docTitle);
var subtitleFont = FontFactory.GetFont("Times Roman", 9, BaseColor.BLACK);
var subTitle = new Paragraph("(not to be used for reimbursement of services)", subtitleFont);
doc.Add(subTitle);
var importantNoticeFont = FontFactory.GetFont("Courier", 9, BaseColor.RED);
var importantNotice = new Paragraph("Important: Form must be filled out in Adobe Reader or Acrobat Professional 8.1 or above. To save completed forms, Acrobat Professional is required. For technical and accessibility assistance, contact the Campus Controller's Office.", importantNoticeFont);
importantNotice.Leading = 0;
importantNotice.MultipliedLeading = 0.9F; // reduce the width between lines in the paragraph with these two settings
importantNotice.ExtraParagraphSpace = 4; // ? test this....
doc.Add(importantNotice);
// Add a table
PdfPTable table = new PdfPTable(10); // the arg is the number of columns
// Row 1
PdfPCell cell = new PdfPCell(docTitle);
cell.Colspan = 3;
cell.BorderWidth = 0;
//cell.BorderColor = BaseColor.WHITE; <= this works for me, but if background is something other than white, it wouldn't
cell.HorizontalAlignment = 0; //0=Left, 1=Centre, 2=Right
table.AddCell(cell);
// Row 2
PdfPCell cellCaveat = new PdfPCell(subTitle);
cellCaveat.Colspan = 2;
cellCaveat.BorderWidth = 0;
table.AddCell(cellCaveat);
// Row 3
PdfPCell cellImportantNote = new PdfPCell(importantNotice);
cellImportantNote.Colspan = 5;
cellImportantNote.BorderWidth = 0;
table.AddCell(importantNotice);
doc.Add(table);
doc.Close();
}
var bytes = ms.ToArray();
String PDFTestOutputFileName = String.Format("iTextSharp_{0}.pdf", DateTime.Now.ToShortTimeString());
PDFTestOutputFileName = PDFTestOutputFileName.Replace(":", "_");
var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), PDFTestOutputFileName);
File.WriteAllBytes(testFile, bytes);
MessageBox.Show(String.Format("{0} written", PDFTestOutputFileName));
}
}
}
catch (DocumentException dex)
{
throw (dex);
}
catch (IOException ioex)
{
throw (ioex);
}
catch (Exception ex)
{
String exMsg = ex.Message;
MessageBox.Show(String.Format("Boo-boo!: {0}", ex.Message));
}
Why is my borderless table invisible or nonexistant?
UPDATE
Based on Bruno's answer, and applying it to the output that I really need, this works:
using (var ms = new MemoryStream())
{
using (var doc = new Document(PageSize.A4, 50, 50, 25, 25)) {
//Create a writer that's bound to our PDF abstraction and our stream
using (var writer = PdfWriter.GetInstance(doc, ms))
{
//Open the document for writing
doc.Open();
// Mimic the appearance of Direct_Payment.pdf
var courierBold11Font = FontFactory.GetFont(FontFactory.COURIER_BOLD, 11, BaseColor.BLACK);
var docTitle = new Paragraph("UCSC - Direct Payment Form", courierBold11Font);
doc.Add(docTitle);
var timesRoman9Font = FontFactory.GetFont("Times Roman", 9, BaseColor.BLACK);
var subTitle = new Paragraph("(not to be used for reimbursement of services)", timesRoman9Font);
doc.Add(subTitle);
var courier9RedFont = FontFactory.GetFont("Courier", 9, BaseColor.RED);
var importantNotice = new Paragraph("Important: Form must be filled out in Adobe Reader or Acrobat Professional 8.1 or above. To save completed forms, Acrobat Professional is required. For technical and accessibility assistance, contact the Campus Controller's Office.", courier9RedFont);
importantNotice.Leading = 0;
importantNotice.MultipliedLeading = 0.9F; // reduce the width between lines in the paragraph with these two settings
// Add a table
PdfPTable table = new PdfPTable(1);
PdfPCell cellImportantNote = new PdfPCell(importantNotice);
cellImportantNote.BorderWidth = PdfPCell.NO_BORDER;
table.WidthPercentage = 50;
table.HorizontalAlignment = Element.ALIGN_LEFT;
table.AddCell(cellImportantNote);
doc.Add(table);
doc.Close();
}
var bytes = ms.ToArray();
String PDFTestOutputFileName = String.Format("iTextSharp_{0}.pdf", DateTime.Now.ToShortTimeString());
PDFTestOutputFileName = PDFTestOutputFileName.Replace(":", "_");
var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), PDFTestOutputFileName);
File.WriteAllBytes(testFile, bytes);
MessageBox.Show(String.Format("{0} written", PDFTestOutputFileName));
}
}
Please take a look at the SimpleTable7 example and compare the Java code with your [?] code:
This part is relevant:
PdfPCell cellImportantNote = new PdfPCell(importantNotice);
cellImportantNote.setColspan(5);
cellImportantNote.setBorder(PdfPCell.NO_BORDER);
table.addCell(cellImportantNote);
If I would convert your [?] code to Java, you'd have:
PdfPCell cellImportantNote = new PdfPCell(importantNotice);
cellImportantNote.setColspan(5);
cellImportantNote.setBorder(PdfPCell.NO_BORDER);
table.addCell(importantNotice);
Do you see the difference? You create a cellImportantNote instance, but you aren't using it anywhere. Instead of adding cellImportantNote to the table, you add the importantNotice paragraph.
This means that you are creating a table with 10 columns that has a single row of which only 6 cells are taken (because you have 1 cell with colspan 3, 1 cell with colspan 2 and 1 cell with colspan 1).
By default, iText doesn't render any rows that aren't complete, and since your table doesn't have any complete row, the table isn't being rendered.
If you look at the resulting PDF, simple_table7.pdf, you'll notice that I also added a second table. This table has only three columns, but it looks identical to the table you constructed. Instead of improper use of the colspan functionality, I defined relative widths for the three columns:
table = new PdfPTable(3);
table.setWidths(new int[]{3, 2, 5});
cell.setColspan(1);
table.addCell(cell);
cellCaveat.setColspan(1);
table.addCell(cellCaveat);
cellImportantNote.setColspan(1);
table.addCell(cellImportantNote);
document.add(table);
Note that I also avoid to use meaningless numbers. For instance, instead of:
cell.setHorizontalAlignment(0); // 0 means left
I use:
cell.setHorizontalAlignment(Element.ALIGN_LEFT);
This way, people can read what this line means without having to depend on comments.
Furtermore, I replaced:
cell.setBorderWidth(0);
with:
cell.setBorder(PdfPCell.NO_BORDER);
That too, is only a matter of taste, but I think it's important if you want to keep your code maintainable.

Adding form elements to a table with iTextSharp

I'm trying to create a PDF document that is essentially a list of users in a table format. I need the table to have checkboxes in it. So far, I have the table and the checkboxes separately but I cannot find a way to get the checkboxes in the table. I think I need to add them using the AddCell() method.
Here is my code:
static void Main(string[] args)
{
// create the document, filestream, writer
Document doc = new Document(PageSize.LETTER);
FileStream file = new FileStream(#"C:\Users\test\User List.pdf", FileMode.OpenOrCreate);
PdfWriter writer = PdfWriter.GetInstance(doc, file);
try
{
// metadata
doc.AddAuthor("Test User");
doc.AddCreator("Test Document");
doc.AddKeywords("Test Document");
doc.AddSubject("Test Document");
doc.AddTitle("Test Document - Test User");
// open up the PDF document
doc.Open();
PdfContentByte cb = writer.DirectContent;
Font _bf = new Font(Font.FontFamily.HELVETICA, 9);
// create a table
PdfPTable table = new PdfPTable(3);
PdfPCell cell = new PdfPCell(new Phrase("User List"));
PdfFormField field = PdfFormField.CreateCheckBox(writer);
field.SetWidget(new Rectangle(40, 500, 60, 530), PdfAnnotation.HIGHLIGHT_INVERT);
field.SetFieldFlags(PdfAnnotation.FLAGS_PRINT);
field.FieldName = "Delete";
writer.AddAnnotation(field);
cell.Colspan = 3;
cell.HorizontalAlignment = 0; //0 = left, 1 = center, 2 = right
cell.VerticalAlignment = 1;
table.AddCell("No.");
table.AddCell("Users");
table.AddCell("Delete");
// create form fields
PdfAppearance[] onOff = new PdfAppearance[2];
Rectangle rect;
PdfFormField checkbox;
RadioCheckField _checkbox;
onOff[0] = cb.CreateAppearance(10, 10);
onOff[0].Rectangle(1, 1, 8, 8);
onOff[0].Stroke();
onOff[1] = cb.CreateAppearance(10, 10);
onOff[1].SetRGBColorFill(255, 128, 128);
onOff[1].Rectangle(1, 1, 8, 8);
onOff[1].FillStroke();
onOff[1].MoveTo(1, 1);
onOff[1].LineTo(9, 9);
onOff[1].MoveTo(1, 9);
onOff[1].LineTo(9, 1);
onOff[1].Stroke();
for (int i = 0; i < 5; i++)
{
table.AddCell(i.ToString());
table.AddCell("User " + i);
//rect = new Rectangle(400, 675 - i*40, 415, 663 - i*40);
rect = new Rectangle(400, 735 - i * 40, 415, 723 - i * 40);
_checkbox = new RadioCheckField(writer, rect, "User "+(i+1), "Yes");
checkbox = _checkbox.CheckField;
checkbox.SetAppearance(PdfAnnotation.APPEARANCE_NORMAL, "Off", onOff[0]);
checkbox.SetAppearance(PdfAnnotation.APPEARANCE_NORMAL, "On", onOff[1]);
writer.AddAnnotation(checkbox);
// this is where I am trying to add the checkbox to the table
// what can I add to AddCell() to make the checkbox show up?
table.AddCell();
//ColumnText.ShowTextAligned(cb, Element.ALIGN_LEFT, new Phrase("User " + (i + 1), _bf), 50, 665 - i * 40, 0);
}
cb = writer.DirectContent;
doc.Add(table);
}
catch(DocumentException dex)
{
throw (dex);
}
finally
{
// close
doc.Close();
writer.Close();
file.Close();
}
}
Is there any way to do this using iTextSharp? Maybe there is a better library to use?
I'll reference the iText website showing how to pass a field to a custom IPdfPCellEvent implementation and how to create that that custom class and recreate it below in C#.
First, create a class the implements the IPdfPCellEvent:
public class ChildFieldEvent : IPdfPCellEvent {
/** A parent field to which a child field has to be added. */
protected PdfFormField parent;
/** The child field that has to be added */
protected PdfFormField kid;
/** The padding of the field inside the cell */
protected float padding;
/**
* Creates a ChildFieldEvent.
* #param parent the parent field
* #param kid the child field
* #param padding a padding
*/
public ChildFieldEvent(PdfFormField parent, PdfFormField kid, float padding) {
this.parent = parent;
this.kid = kid;
this.padding = padding;
}
/**
* Add the child field to the parent, and sets the coordinates of the child field.
*/
public void CellLayout(PdfPCell cell, iTextSharp.text.Rectangle rect, PdfContentByte[] cb) {
parent.AddKid(kid);
kid.SetWidget(new iTextSharp.text.Rectangle(
rect.GetLeft(padding),
rect.GetBottom(padding),
rect.GetRight(padding),
rect.GetTop(padding)
),
PdfAnnotation.HIGHLIGHT_INVERT
);
}
}
Then just set the CellEvent on any cells that should have fields in them.
//File to create
var testFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "test.pdf");
//Standard PDF creation, nothing special here
using (var fs = new FileStream(testFile, FileMode.Create, FileAccess.Write, FileShare.None)) {
using (var doc = new Document()) {
using (var writer = PdfWriter.GetInstance(doc, fs)) {
doc.Open();
//Create a root form object that we'll add "children" to. This way we don't have to add each "child" annotation to the writer
var root = PdfFormField.CreateEmpty(writer);
root.FieldName = "root";
//Create a two column table
var t = new PdfPTable(2);
//Add a basic cell
t.AddCell("First Name");
//Create our textfield, the rectangle that we're passing in is ignored and doesn't matter
var tf = new TextField(writer, new iTextSharp.text.Rectangle(0, 0), "first-name");
//Create a new cell
var cell = new PdfPCell();
//Set the cell event to our custom IPdfPCellEvent implementation
cell.CellEvent = new ChildFieldEvent(root, tf.GetTextField(), 1);
//Add the cell to our table
t.AddCell(cell);
//Add the table to the document
doc.Add(t);
//IMPORTANT! Add the root annotation to the writer which also adds all of the child annotations
writer.AddAnnotation(root);
//Clean up
doc.Close();
}
}
}

ITextsharp invalidates signatures when using lines or rectangles

When I use ITextSharp to digitally sign a document that is already digitally signed using this code it invalidates the other signatures. If I digitally sign using a text or image it works fine. Is this an Adobe/Itextsharp limitation or is something wrong with the code?
public void SignWithLine(string pdfFilePath, string outputFilePath, LineAnnotation lineAnnotation)
{
double xStartPoint = 89.285969238281268, yStartPoint = 343.08978515624881, xEndPoint = 72.7515234375, yEndPoint = 496.03341796874878, lineStroke = .24;
CertificateWrapper certificate = CertificateWrapper.GetCertificateInformationFromSignature(GetCertificateInformation());
PdfReader reader = new PdfReader(pdfFilePath);
PdfTemplate layer = null;
using (PdfStamper signature = PdfStamper.CreateSignature(reader, null, '\0', outputFilePath, true))
{
PdfSignatureAppearance signatureAppearance = signature.SignatureAppearance;
signatureAppearance.SignatureRenderingMode = PdfSignatureAppearance.RenderingMode.GRAPHIC;
Rectangle rect = new Rectangle((float)Math.Min(xStartPoint, xEndPoint), (float)Math.Min(yStartPoint, yEndPoint), (float)Math.Min(xStartPoint, xEndPoint) + (float)Math.Abs(xEndPoint - xStartPoint), (float)Math.Min(yStartPoint, yEndPoint) + (float)Math.Abs(yEndPoint - yStartPoint));
signatureAppearance.SetVisibleSignature(rect, lineAnnotation.PageIndex + 1, GetCertificateFieldName());
layer = signatureAppearance.GetLayer(2);
PdfContentByte cb = signature.GetUnderContent(lineAnnotation.PageIndex + 1);
cb.SetLineWidth((float)lineStroke);
cb.MoveTo((float)xStartPoint, (float)yStartPoint);
cb.LineTo((float)(xEndPoint), (float)(yEndPoint));
cb.Stroke();
signatureAppearance.CertificationLevel = PdfSignatureAppearance.NOT_CERTIFIED;
// Normal signature, not a certification
MakeSignature.SignDetached(signatureAppearance, certificate.DigitalSignature, certificate.Chain, null, null, null, 0, true);
signature.Close();
}
}
signature is your PdfStamper. You draw a line on
PdfContentByte cb = signature.GetUnderContent(lineAnnotation.PageIndex + 1);
i.e. You draw it in the content stream of a page. This counts as a change of the page content and, therefore, is forbidden by the original signature. For details on the allowed changes cf. this answer.
I found a way to do this by modifying the iTextSharp library.
// First I overloaded the SetVisibleSignature to pass a list of int
public void SetVisibleSignature(Rectangle pageRect, String fieldName, List pageList)
{
pages = pageList; // pages is a private List pages;
...
}
// Secondly, in the PreClose event you update it as shown below
sigField.Page = pagen;
if (pagen != 0)
writer.AddAnnotation(sigField, pagen);
else if (pages != null && pages.Count > 0)
pages.ForEach(f => writer.AddAnnotation(sigField, f)); // this annotates all pages with the same signature
else
throw new DocumentException("No pages specified for signature.");

Adding a new page using iTextSharp

I have a class that build the content for my table of contents and that works, fine and dandy.
Here's the code:
public void Build(string center,IDictionary<string,iTextSharp.text.Image> images)
{
iTextSharp.text.Image image = null;
XPathDocument rapportTekst = new XPathDocument(Application.StartupPath + #"..\..\..\RapportTemplates\RapportTekst.xml");
XPathNavigator nav = rapportTekst.CreateNavigator();
XPathNodeIterator iter;
iter = nav.Select("//dokument/brevhoved");
iter.MoveNext();
var logo = iTextSharp.text.Image.GetInstance(iter.Current.GetAttribute("url", ""));
iter = nav.Select("//dokument/gem_som");
iter.MoveNext();
string outputPath = iter.Current.GetAttribute("url", "")+center+".pdf";
iter = nav.Select("//dokument/titel");
iter.MoveNext();
this.titel = center;
Document document = new Document(PageSize.A4, 30, 30, 100, 30);
var outputStream = new FileStream(outputPath, FileMode.Create);
var pdfWriter = PdfWriter.GetInstance(document, outputStream);
pdfWriter.SetLinearPageMode();
var pageEventHandler = new PageEventHandler();
pageEventHandler.ImageHeader = logo;
pdfWriter.PageEvent = pageEventHandler;
DateTime timeOfReport = DateTime.Now.AddMonths(-1);
pageWidth = document.PageSize.Width - (document.LeftMargin + document.RightMargin);
pageHight = document.PageSize.Height - (document.TopMargin + document.BottomMargin);
document.Open();
var title = new Paragraph(titel, titleFont);
title.Alignment = Element.ALIGN_CENTER;
document.Add(title);
List<TableOfContentsEntry> _contentsTable = new List<TableOfContentsEntry>();
nav.MoveToRoot();
iter = nav.Select("//dokument/indhold/*");
Chapter chapter = null;
int chapterCount = 1;
while (iter.MoveNext())
{
_contentsTable.Add(new TableOfContentsEntry("Test", pdfWriter.CurrentPageNumber.ToString()));
XPathNodeIterator innerIter = iter.Current.SelectChildren(XPathNodeType.All);
chapter = new Chapter("test", chapterCount);
while(innerIter.MoveNext())
{
if (innerIter.Current.Name.ToString().ToLower().Equals("billede"))
{
image = images[innerIter.Current.GetAttribute("navn", "")];
image.Alignment = Image.ALIGN_CENTER;
image.ScaleToFit(pageWidth, pageHight);
chapter.Add(image);
}
if (innerIter.Current.Name.ToString().ToLower().Equals("sektion"))
{
string line = "";
var afsnit = new Paragraph();
line += (innerIter.Current.GetAttribute("id", "") + " ");
innerIter.Current.MoveToFirstChild();
line += innerIter.Current.Value;
afsnit.Add(line);
innerIter.Current.MoveToNext();
afsnit.Add(innerIter.Current.Value);
chapter.Add(afsnit);
}
}
chapterCount++;
document.Add(chapter);
}
document = CreateTableOfContents(document, pdfWriter, _contentsTable);
document.Close();
}
I'm then calling the method CreateTableOfContents(), and as such it is doing what it is supposed to do. Here's the code for the method:
public Document CreateTableOfContents(Document _doc, PdfWriter _pdfWriter, List<TableOfContentsEntry> _contentsTable)
{
_doc.NewPage();
_doc.Add(new Paragraph("Table of Contents", FontFactory.GetFont("Arial", 18, Font.BOLD)));
_doc.Add(new Chunk(Environment.NewLine));
PdfPTable _pdfContentsTable = new PdfPTable(2);
foreach (TableOfContentsEntry content in _contentsTable)
{
PdfPCell nameCell = new PdfPCell(_pdfContentsTable);
nameCell.Border = Rectangle.NO_BORDER;
nameCell.Padding = 6f;
nameCell.Phrase = new Phrase(content.Title);
_pdfContentsTable.AddCell(nameCell);
PdfPCell pageCell = new PdfPCell(_pdfContentsTable);
pageCell.Border = Rectangle.NO_BORDER;
pageCell.Padding = 6f;
pageCell.Phrase = new Phrase(content.Page);
_pdfContentsTable.AddCell(pageCell);
}
_doc.Add(_pdfContentsTable);
_doc.Add(new Chunk(Environment.NewLine));
/** Reorder pages so that TOC will will be the second page in the doc
* right after the title page**/
int toc = _pdfWriter.PageNumber - 1;
int total = _pdfWriter.ReorderPages(null);
int[] order = new int[total];
for (int i = 0; i < total; i++)
{
if (i == 0)
{
order[i] = 1;
}
else if (i == 1)
{
order[i] = toc;
}
else
{
order[i] = i;
}
}
_pdfWriter.ReorderPages(order);
return _doc;
}
The problem is however. I want to insert a page break before the table of contents, for the sake of reordering the pages, so that the table of contents is the first page, naturally. But the output of the pdf-file is not right.
Here's a picture of what it looks like:
It seems like the _doc.NewPage() in the CreateTableOfContents() method does not execute correctly. Meaning that the image and the table of contents is still on the same page when the method starts the reordering of pages.
EDIT: To clarify the above, the _doc.NewPage() gets executed, but the blank page is added after the picture and the table of contents.
I've read a couple of places that this could be because one is trying to insert a new page after an already blank page. But this is not the case.
I'll just link to the pdf files aswell, to better illustrate the problem.
The pdf with table of contents: with table of contents
The pdf without table of contents: without table of contents
Thank you in advance for your help :)

Categories

Resources