Crea un generatore di fatture PDF in .NET
Categoria del blog: PDF ; Office ; .NET
02.07.2021
// The project, which uses this code, must have references to the following assemblies:
// - Vintasoft.Imaging
// - Vintasoft.Imaging.Office.OpenXml
// - Vintasoft.Imaging.Pdf
// - Vintasoft.Barcode
/// <summary>
/// Generates invoice, which is based on DOCX document template.
/// </summary>
public static void GenerateInvoiceUsingDocxTemplate()
{
// create DOCX document editor and use file "Invoice_template.docx" as document template
using (Vintasoft.Imaging.Office.OpenXml.Editor.DocxDocumentEditor editor =
new Vintasoft.Imaging.Office.OpenXml.Editor.DocxDocumentEditor("Invoice_template.docx"))
{
// generate test invoice data with 30 items
InvoiceData testData = GetTestData(30);
// fill invoice data
FillInvoiceData(editor, testData);
// save invoice to a DOCX document if necessary
//editor.Save("Invoice.docx");
// export invoice to a PDF document
editor.Export("Invoice_docx.pdf");
}
}
/// <summary>
/// Fills the invoice data using DOCX document editor.
/// </summary>
/// <param name="documentEditor">The DOCX document editor.</param>
/// <param name="invoiceData">The invoice data.</param>
private static void FillInvoiceData(
Vintasoft.Imaging.Office.OpenXml.Editor.DocxDocumentEditor documentEditor,
InvoiceData invoiceData)
{
// create QR code image 200x200 px
using (Vintasoft.Imaging.VintasoftImage qrCodeImage = invoiceData.GetBarcodeImage(200))
{
// set barcode image to the image element at index 1
documentEditor.Images[1].SetImage(qrCodeImage);
}
// fill the document header
documentEditor.Body["[company_name]"] = invoiceData.Company.CompanyName;
documentEditor.Body["[company_address]"] = invoiceData.Company.Address;
documentEditor.Body["[company_city]"] = invoiceData.Company.City;
documentEditor.Body["[company_phone]"] = invoiceData.Company.GetPhones();
documentEditor.Body["[invoice_number]"] = invoiceData.InvoiceNumber;
documentEditor.Body["[invoice_date]"] = System.DateTime.Now.ToShortDateString();
// get all tables of document
Vintasoft.Imaging.Office.OpenXml.Editor.OpenXmlDocumentTable[] tables = documentEditor.Tables;
// fill the "Customer Information" table
Vintasoft.Imaging.Office.OpenXml.Editor.OpenXmlDocumentTable customerInformationTable = tables[0];
SetCompanyInformation(customerInformationTable, "billing", invoiceData.BillingAddress);
SetCompanyInformation(customerInformationTable, "shipping", invoiceData.ShippingAddress);
// fill the "Shipping Method" table
Vintasoft.Imaging.Office.OpenXml.Editor.OpenXmlDocumentTable shippingMethodTable = tables[1];
shippingMethodTable["[shipping_method]"] = invoiceData.ShippingMethod;
// fill the "Order Information" table
Vintasoft.Imaging.Office.OpenXml.Editor.OpenXmlDocumentTable orderInformationTable = tables[2];
Vintasoft.Imaging.Office.OpenXml.Editor.OpenXmlDocumentTableRow templateRow = orderInformationTable[1];
int orderItemNumber = 1;
// for each item in invoice
foreach (InvoiceItem orderItem in invoiceData.OrderItems)
{
// copy template row and insert copy after template row
Vintasoft.Imaging.Office.OpenXml.Editor.OpenXmlDocumentTableRow currentRow = templateRow;
templateRow = (Vintasoft.Imaging.Office.OpenXml.Editor.OpenXmlDocumentTableRow)templateRow.InsertCopyAfterSelf();
// fill data of current row
currentRow["[p_n]"] = orderItemNumber.ToString();
currentRow["[p_description]"] = orderItem.Product;
currentRow["[p_qty]"] = orderItem.Quantity.ToString();
currentRow["[p_unit_price]"] = invoiceData.GetPriceAsString(orderItem.Price);
currentRow["[p_price_total]"] = invoiceData.GetPriceAsString(orderItem.TotalPrice);
orderItemNumber++;
}
// remove template row
templateRow.Remove();
// fill order information summary fields
orderInformationTable["[subtotal]"] = invoiceData.GetPriceAsString(invoiceData.Subtotal);
orderInformationTable["[tax]"] = invoiceData.GetPriceAsString(invoiceData.Tax);
orderInformationTable["[shipping]"] = invoiceData.GetPriceAsString(invoiceData.Shipping);
orderInformationTable["[grand_total]"] = invoiceData.GetPriceAsString(invoiceData.GrandTotal);
// fill the "Notes" table
Vintasoft.Imaging.Office.OpenXml.Editor.OpenXmlDocumentTable notesTable = tables[3];
notesTable["[date]"] = System.DateTime.Now.ToShortDateString();
notesTable["[time]"] = System.DateTime.Now.ToLongTimeString();
}
/// <summary>
/// Sets the company information.
/// </summary>
/// <param name="table">The table.</param>
/// <param name="fieldName">Name of the field.</param>
/// <param name="company">The company.</param>
private static void SetCompanyInformation(
Vintasoft.Imaging.Office.OpenXml.Editor.OpenXmlDocumentTable table,
string fieldName,
Company company)
{
string fieldFormat = string.Format("[{0}_{1}]", fieldName, "{0}");
table[string.Format(fieldFormat, "company")] = company.CompanyName;
table[string.Format(fieldFormat, "name")] = company.Name;
table[string.Format(fieldFormat, "address")] = company.Address;
table[string.Format(fieldFormat, "phone")] = company.GetPhones();
table[string.Format(fieldFormat, "city")] = company.City;
}
/// <summary>
/// Returns the invoice test data.
/// </summary>
/// <returns>The invoice test data.</returns>
public static InvoiceData GetTestData(int orderItemsCount)
{
Company vintasoftCompany = new Company();
vintasoftCompany.CompanyName = "VintaSoft LLC";
Company billingCompany = new Company();
billingCompany.CompanyName = "Billing Global Company Inc.";
billingCompany.Name = "Mr. Q";
billingCompany.Address = "Address1";
billingCompany.City = "City1";
billingCompany.Phones.Add("9876543210");
billingCompany.Phones.Add("7654321098 (fax)");
Company shipingCompany = new Company();
shipingCompany.CompanyName = "Shipping Global Company Inc.";
shipingCompany.Name = "Mr. Z";
shipingCompany.Address = "Address2";
shipingCompany.City = "City2";
shipingCompany.Phones.Add("1122334455");
shipingCompany.Phones.Add("5544332211 (fax)");
InvoiceData data = new InvoiceData();
System.Random random = new System.Random();
data.InvoiceNumber = string.Format("{0}-{1}", random.Next(100000, 999999), random.Next(0, 9));
data.Company = vintasoftCompany;
data.BillingAddress = billingCompany;
data.ShippingAddress = shipingCompany;
InvoiceItem[] availableProducts = new InvoiceItem[] {
new InvoiceItem("VintaSoft Imaging .NET SDK, Site license for Desktop PCs", 659.95f),
new InvoiceItem("VintaSoft Annotation .NET Plug-in, Site license for Desktop PCs", 449.95f),
new InvoiceItem("VintaSoft Office .NET Plug-in, Site license for Desktop PCs", 569.95f),
new InvoiceItem("VintaSoft PDF .NET Plug-in (Reader+Writer), Site license for Desktop PCs", 1499.95f),
new InvoiceItem("VintaSoft PDF .NET Plug-in (Reader+Writer+VisualEditor), Site license for Desktop PCs", 2999.95f),
new InvoiceItem("VintaSoft JBIG2 .NET Plug-in, Site license for Desktop PCs", 1139.95f),
new InvoiceItem("VintaSoft JPEG2000 .NET Plug-in, Site license for Desktop PCs", 689.95f),
new InvoiceItem("VintaSoft Document Cleaup .NET Plug-in, Site license for Desktop PCs", 569.95f),
new InvoiceItem("VintaSoft OCR .NET Plug-in, Site license for Desktop PCs", 509.95f),
new InvoiceItem("VintaSoft DICOM .NET Plug-in (Codec+MPR), Site license for Desktop PCs", 1199.95f),
new InvoiceItem("VintaSoft Forms Processing .NET Plug-in, Site license for Desktop PCs", 509.95f),
new InvoiceItem("VintaSoft Barcode .NET SDK (1D+2D Reader+Writer), Site license for Desktop PCs", 1379.95f),
new InvoiceItem("VintaSoft Twain .NET SDK, Site license", 539.95f)
};
for (int i = 0; i < orderItemsCount; i++)
{
int quantity = 1 + random.Next(10);
int index = random.Next(availableProducts.Length - 1);
data.OrderItems.Add(new InvoiceItem(availableProducts[index], quantity));
}
return data;
}
/// <summary>
/// Represents an information about company.
/// </summary>
public class Company
{
/// <summary>
/// The company name.
/// </summary>
public string CompanyName;
/// <summary>
/// The person name.
/// </summary>
public string Name;
/// <summary>
/// The company location city.
/// </summary>
public string City;
/// <summary>
/// The company location adress.
/// </summary>
public string Address;
/// <summary>
/// The company phone numbers.
/// </summary>
public System.Collections.Generic.List<string> Phones = new System.Collections.Generic.List<string>();
/// <summary>
/// Returns the phone numbers.
/// </summary>
public string GetPhones()
{
if (Phones.Count == 1)
return Phones[0];
System.Text.StringBuilder result = new System.Text.StringBuilder();
for (int i = 0; i < Phones.Count - 1; i++)
{
result.Append(Phones[i]);
result.Append(", ");
}
result.Append(Phones[Phones.Count - 1]);
return result.ToString();
}
}
/// <summary>
/// Represents an invoice order item.
/// </summary>
public class InvoiceItem
{
/// <summary>
/// Initializes a new instance of the <see cref="InvoiceItem"/> class.
/// </summary>
/// <param name="product">The product name.</param>
/// <param name="price">The product price.</param>
public InvoiceItem(string product, float price)
{
Product = product;
Quantity = 1;
Price = price;
}
/// <summary>
/// Initializes a new instance of the <see cref="InvoiceItem"/> class.
/// </summary>
/// <param name="source">The source <see cref="InvoiceItem"/>.</param>
/// <param name="quantity">The product quantity.</param>
public InvoiceItem(InvoiceItem source, float quantity)
{
Product = source.Product;
Price = source.Price;
Quantity = quantity;
}
/// <summary>
/// The product name.
/// </summary>
public string Product;
/// <summary>
/// The product quantity.
/// </summary>
public float Quantity;
/// <summary>
/// The product price.
/// </summary>
public float Price;
/// <summary>
/// Gets the product total price.
/// </summary>
public float TotalPrice
{
get
{
return Price * Quantity;
}
}
}
/// <summary>
/// Represents an invoice data.
/// </summary>
public class InvoiceData
{
/// <summary>
/// The list of order items.
/// </summary>
public System.Collections.Generic.List<InvoiceItem> OrderItems = new System.Collections.Generic.List<InvoiceItem>();
/// <summary>
/// The invoice number.
/// </summary>
public string InvoiceNumber;
/// <summary>
/// The shipping method.
/// </summary>
public string ShippingMethod = "Email";
/// <summary>
/// The company billing address.
/// </summary>
public Company BillingAddress = new Company();
/// <summary>
/// The company shipping address.
/// </summary>
public Company ShippingAddress = new Company();
/// <summary>
/// The object that represents information about the company.
/// </summary>
public Company Company = new Company();
/// <summary>
/// The currency to be used in the invoice.
/// </summary>
public string Currency = "EUR";
/// <summary>
/// Gets or sets the tax value.
/// </summary>
public float Tax = 0;
/// <summary>
/// Gets or sets the shipping price.
/// </summary>
public float Shipping = 0;
/// <summary>
/// Gets the subtotal value.
/// </summary>
public float Subtotal
{
get
{
float value = 0;
for (int i = 0; i < OrderItems.Count; i++)
value += OrderItems[i].TotalPrice;
return value;
}
}
/// <summary>
/// Gets the grandtotal value.
/// </summary>
public float GrandTotal
{
get
{
return Subtotal + Shipping + Tax;
}
}
/// <summary>
/// Returns the price as a string.
/// </summary>
/// <param name="price">The price.</param>
/// <returns>The price in string representation.</returns>
public string GetPriceAsString(float price)
{
return string.Format("{0} {1}", price.ToString("f2", System.Globalization.CultureInfo.InvariantCulture), Currency);
}
/// <summary>
/// Creates the QR code image.
/// </summary>
/// <param name="size">The barcode size.</param>
/// <returns>An instance o f<see cref="Vintasoft.Imaging.VintasoftImage"/> class that contains QR code image.</returns>
public Vintasoft.Imaging.VintasoftImage GetBarcodeImage(int size)
{
Vintasoft.Barcode.BarcodeWriter writer = new Vintasoft.Barcode.BarcodeWriter();
writer.Settings.Barcode = Vintasoft.Barcode.BarcodeType.QR;
writer.Settings.Value = string.Format("INVOICE={0};TOTAL={1}", InvoiceNumber, GetPriceAsString(GrandTotal));
writer.Settings.SetWidth(size);
Vintasoft.Imaging.VintasoftImage result =
new Vintasoft.Imaging.VintasoftImage(writer.GetBarcodeAsBitmap(), true);
result.Crop(new System.Drawing.Rectangle(0, 0, result.Width, result.Width));
return result;
}
}