I'm developing a windows form application for generating invoices in PDF files.
This Winform application is using a PDF template for creating a PDF file.
This is the screenshot of the PDF template (this template was created using Adobe Acrobat XI Lite Portable):
I'm using itextsharp (version 5.5.13) in this code for generate the PDF file:
private void GenerateInvoice(DataTable tbl_template_variables, DataTable tbl_details_invoice)
{
using (PdfReader pdfReader = new PdfReader(plantilla__Invoice__manual))
{
try
{
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(location_output_file, FileMode.Create));
AcroFields pdfFormFields = pdfStamper.AcroFields;
// Loop DataTable and set the value in the specified field.
for (int i = 0; i < tbl_template_variables.Rows.Count; i++)
{
pdfFormFields.SetField(tbl_template_variables.Rows[i][0].ToString(), tbl_template_variables.Rows[i][1].ToString(), true);// set form pdfFormFields
}
#region Details's table Invoice
PdfPCell cell = null;
PdfPTable table = null;
table = new PdfPTable(9);
table.HorizontalAlignment = Element.ALIGN_LEFT;
table.SetWidths(new float[] { 22f, 22f, 22f, 22f, 22f, 22f, 22f, 22f, 22f });
//table.SpacingBefore = 5;
table.TotalWidth = 800f;
for (int i = 0; i < tbl_details_invoice.Rows.Count; i++)
{
DataRow row = tbl_details_invoice.Rows[i];
object Invoice_PDFColumn0_value = row.Field<string>("PROVIDER") == null ? string.Empty : row.Field<string>("PROVIDER").ToString();
object Invoice_PDFColumn1_value = row.Field<string>("DESCRIPTION") == null ? string.Empty : row.Field<string>("DESCRIPTION").ToString();
object Invoice_PDFColumn2_value = row.Field<string>("PPTO") == null ? string.Empty : row.Field<string>("PPTO").ToString();
object Invoice_PDFColumn3_value = row.Field<string>("JOB_MEDIA_TYPE") == null ? string.Empty : row.Field<string>("JOB_MEDIA_TYPE").ToString();
object Invoice_PDFColumn4_value = row.Field<string>("VEND_INV_NO") == null ? string.Empty : row.Field<string>("VEND_INV_NO").ToString();
//object Invoice_PDFColumn5_value = row.Field<string>("ORDER_MEDIA") == null ? string.Empty : row.Field<string>("ORDER_MEDIA").ToString();
//object Invoice_PDFColumn6_value = row.Field<string>("ACTIVITY_MONTH") == null ? string.Empty : row.Field<string>("ACTIVITY_MONTH").ToString();
object Invoice_PDFColumn7_value = row.Field<string>("COMMISSIONABLE") == null ? string.Empty : row.Field<string>("COMMISSIONABLE").ToString();
object Invoice_PDFColumn8_value = row.Field<string>("NON_COMMISSIONABLE") == null ? string.Empty : row.Field<string>("NON_COMMISSIONABLE").ToString();
string Invoice_PDFColumn9_value = row.Field<string>("IVA_PROVEEDOR") == null ? string.Empty : row.Field<string>("IVA_PROVEEDOR").ToString();
string Invoice_PDFColumn10_value = row.Field<string>("TOTAL") == null ? string.Empty : row.Field<string>("TOTAL").ToString();
//Columns table
cell = PhraseCell(new Phrase(Invoice_PDFColumn0.ToString(), GettypeStyle()));
table.AddCell(cell);
cell = PhraseCell(new Phrase(Invoice_PDFColumn1.ToString(), GettypeStyle()));
table.AddCell(cell);
cell = PhraseCell(new Phrase(Invoice_PDFColumn2.ToString(), GettypeStyle()));
table.AddCell(cell);
cell = PhraseCell(new Phrase(Invoice_PDFColumn3.ToString(), GettypeStyle()));
table.AddCell(cell);
cell = PhraseCell(new Phrase(Invoice_PDFColumn4.ToString(), GettypeStyle()));
table.AddCell(cell);
//cell = PhraseCell(new Phrase(Invoice_PDFColumn5.ToString(), GettypeStyle()));
//table.AddCell(cell);
//cell = PhraseCell(new Phrase(Invoice_PDFColumn6.ToString(), GettypeStyle()));
//table.AddCell(cell);
cell = PhraseCell(new Phrase(Invoice_PDFColumn7.ToString(), GettypeStyle()));
table.AddCell(cell);
cell = PhraseCell(new Phrase(Invoice_PDFColumn8.ToString(), GettypeStyle()));
table.AddCell(cell);
cell = PhraseCell(new Phrase(Invoice_PDFColumn9.ToString(), GettypeStyle()));
table.AddCell(cell);
cell = PhraseCell(new Phrase(Invoice_PDFColumn10.ToString(), GettypeStyle()));
table.AddCell(cell);
}
ColumnText ct = new ColumnText(pdfStamper.GetOverContent(1));
ct.AddElement(table);
//iTextSharp.text.Rectangle rect = new iTextSharp.text.Rectangle(18, 370, 800, 36);
iTextSharp.text.Rectangle rect = new iTextSharp.text.Rectangle(16, 320, 900, 16);
rect.Border = iTextSharp.text.Rectangle.LEFT_BORDER | iTextSharp.text.Rectangle.RIGHT_BORDER;
rect.BorderWidth = 15;
rect.BorderColor = new BaseColor(0, 0, 0);
rect.Border = iTextSharp.text.Rectangle.BOX;
ct.SetSimpleColumn(rect);
ct.Go();
#endregion
// flatten the form to remove editting options, set it to false
// to leave the form open to subsequent manual edits
pdfStamper.FormFlattening = true;
pdfStamper.FreeTextFlattening = true;
pdfStamper.Writer.CloseStream = true;
pdfStamper.Close();// close the pdf
}
catch (Exception ex)
{
// No errors (yet).
}
}
}
And this is the results (with just a few details):
The problem I'm facing with this code is that, if the details table has more rows, the rows are overwritten in the generated page (and no more pages are generated).
This is the result with overwritten data:
I'm looking the way for generating the PDF invoice correctly (if possible) using this PDF template.
This is the closest favorable result I got so far after tried:
- Modifying the PDF template for add variables under the detail headers and updating the field's value for add line breaks each time, but, it seems the size of the variable in the PDF matters and so, the line breaks aren't expanding the variable (and forcing) to generate more pages.
- Using HTMLWorker (deprecated) for force an HTML template (similar to PDF template's structure). This approach works well for generating multiple pages when printing the Details table's rows, but CSS is not applied.
- Using the combination of PdfDocument, PdfParagraph and similar classes (tried to follow the guidelines I found here), but I honestly have no idea how set in the specific coordinates and using the correct measure points for a set each element in the resulting PDF file.
- Download iText7 for use
HtmlConverter.ConvertToPdf
functionality, but in this case, I'm having problems generating the PDF rotated. The documentation is in java which I'm not familiar. - I found this documentation in Oracle for Create a PDF Template - focusing on "Defining Groups of Repeating Fields" section, but I can't find how to edit the source code of the PDF template neither if this can be used in a C# WinForms application.
All the mentioned attempts generate me more problems than solutions, hence, I want to focus one more time using the PDF template approach.
I'm running the whole week with this assignment and I'm out of ideas.
I'll edit my question for add related questions with the same problem I'm facing:
I'm hardly trying to avoid creating a give me the code question, but, any suggestion or any idea about how can I generate PDF files correctly are welcome.