Example: Invoice

The forum is dedicated to powerful document creation library PDF.Flow.

Moderator: admin

Example: Invoice

Postby Nikolay.Gekht » Sun Dec 15, 2019 3:39 pm

Purpose

This example demonstrates a simple document that uses a table to customize layout of the information on a page.
Example also demonstrates usage of different fonts, URL, image and line.

The example source is available in github repo

Prerequisites

1) Visual Studio 2017 or above is installed.

To install a community version of Visual Studio use the following link: https://visualstudio.microsoft.com/vs/community/
Please make sure that the way you are going to use Visual Studio is allowed by the community license. You may need to buy Standard or Professional Edition.

2) .NET Core Framework SDK 2.1 or above is installed.

To install the framework use the following link: https://dotnet.microsoft.com/download

Description

# Input data

The invoice source data is located in the file Content/invoice.json.
Code: Select all
[
  {
    "Field": "Date",
    "Value": "2019-03-23 11:15AM PDT"
  },
  {
     "Field": "For service through",
     "Value": "2019-09-22"
   }
]


Output file

The example creates the file Invoice.pdf in the output (bin/(debug|release)/netcoreapp2.1 folder.

Writing the source code

Create new console application.

1.1. Run Visual Studio

1.2. File -> Create -> Console Application (.Net Core)

2. Modify class Program:

2.1. In the function Main() call WriteLine() to output the text you want to see in the console:

Code: Select all
Console.WriteLine("Gehtsoft.PDFFlow.Demos");
Console.WriteLine("----------------------");
Console.WriteLine("INVOICE");
Console.WriteLine("----------------------");   


Call method for contract generation:

Code: Select all
GenerateExample();


After generation is completed, ask user to press any key:

Code: Select all
Console.WriteLine("");
Console.WriteLine("Press any key for exit...");
Console.ReadKey();


2.2. In the same class Program define the expression for GenerateExample() method, so it will call GenerateExample() from InvoiceExample class:
private static void GenerateExample() => InvoiceExample.GenerateExample();


3. Generate Invoice

3.1. Under the Model subfolder create new class InvoiceData:

Code: Select all
namespace Gehtsoft.PDFFlow.Invoice.Model
{
    [DataContract]
    public class InvoiceData
    {
            [DataMember]
            public string Field { get; set; }
            [DataMember]
            public string Value { get; set; }
    }
}   


3.2. Create new class InvoiceExample.


3.3. Define fields of the InvoiceExample class:

Path to the output file:

Code: Select all
private static readonly string PdfFile;


Path to the project directory:
Code: Select all
private static readonly string ProjectDir;


Path to the JSON file, containing values to be rendered in a table:
Code: Select all
private static readonly string InvoiceJsonFile;


JSON content:
Code: Select all
private static readonly string InvoiceJsonContent;


Path to the image file:
Code: Select all
private static readonly string ImageUrl;


Various fonts:
Code: Select all
private static readonly Font DocumentFont;
private static readonly Font ItalicFont;
private static readonly Font FooterFont;
private static readonly Font BoldFont;
private static readonly Font UrlFont;
private static readonly Font TitleFont;
private static readonly Font HiddenFont;


Invoice text:
Code: Select all
private static readonly string[] InvoiceText;


List for storing table data:
Code: Select all
public static List<InvoiceData> InvoiceData { get; }




3.4. Create constructor static InvoiceExample()
and initialize fields:

Initialize path variables:
Code: Select all
PdfFile = Path.Combine(Environment.CurrentDirectory, "Invoice.pdf");
ProjectDir = Directory.GetCurrentDirectory();
InvoiceJsonFile = Path.Combine(ProjectDir, "Content", "invoice.json");
ImageUrl = Path.Combine(ProjectDir, "images", "InvoiceExample", "invoice.jpg");


Read invoice data:
Code: Select all
InvoiceJsonContent = File.ReadAllText(InvoiceJsonFile);
InvoiceData = JsonConvert.DeserializeObject<List<InvoiceData>>(InvoiceJsonContent);


Text to be rendered as Paragraph:
Code: Select all
InvoiceText = new[]
{
    "We received payment for your subscription.",
    "Thanks for staying with us!",
    "Questions? Please contact "
};


Initialize fonts:
Code: Select all
DocumentFont = new Font
{
    Name = FontNames.Helvetica,
    Size = 16f,
    Color = Color.Black
};
ItalicFont = DocumentFont.Clone();
ItalicFont.Name = "Times-Italic";
FooterFont = DocumentFont.Clone();
FooterFont.Color = Color.FromRgba(106.0 / 255.0, 85.0 / 255.9, 189.0 / 255.0);
FooterFont.Size = 12f;
BoldFont = DocumentFont.Clone();
BoldFont.Name = "Courier-Bold";
TitleFont = BoldFont.Clone();
TitleFont.Size = 28f;
HiddenFont = DocumentFont.Clone();
HiddenFont.Color = Color.White;
HiddenFont.Size = 0.01f;
UrlFont = DocumentFont.Clone();
UrlFont.Color = Color.Blue;
UrlFont.Underline = Stroke.Solid;
UrlFont.UnderlineColor = Color.Blue;



3.4. Create function GenerateExample().

Create new document by calling method New() of the DocumentBuilder. Then call method AddInvoiceSection, which will be described later. After the document structure is finished, call Build() with the desired file path as a parameter:

Code: Select all
internal static void GenerateExample()
{
    Console.WriteLine("Generating file " + PdfFile);
    if (File.Exists(PdfFile))
        File.Delete(PdfFile);
    DocumentBuilder
        .New()
        .AddInvoiceSection()
        .Build(PdfFile);
}   


3.5. Add invoice sections. Create extension method of the builder:

Code: Select all
internal static DocumentBuilder AddInvoiceSection(this DocumentBuilder builder)
{
}   


Call AddDefaultSection() which will create the first section with default section’s parameters and then change needed parameters:

Code: Select all
builder.AddDefaultSection(s =>
{
    SetSectionSettings(s);


Then call sub-methods which will generate parts of our document in the current section:
Code: Select all
    AddInvoiceTitle(s);
    AddInvoiceText(s);
    AddInvoiceTable(s);
    AddFooter(s);
});           


Method AddInvoiceSection() should return DocumentBuilder, so we could call builder’s method Build() as described in 3.4:
Code: Select all
return builder;
[code]

3.6. Change Section settings:

[code]
internal static void SetSectionSettings(Section s)
{
    s.SetMargins(30)
    .SetSize(PaperSize.A4)
    .SetOrientation(PageOrientation.Portrait)
    .SetNumerationStyle(NumerationStyle.Arabic);
}

3.7. Add invoice title as a Paragraph.

Just pass paragraph’s text as a string parameter of AddParagraph(). It returns Paragraph, so you can then set paragraph’s alignment, margins and font:

[code]
internal static void AddInvoiceTitle(Section s)
{
    s.AddImage(ImageUrl)
        .SetScale(ScalingMode.AutoSize)
        .SetAlignment(HorizontalAlignment.Center);
        s.AddParagraph("Receipt")
        .SetMargins(20, 0, 0, 10)
        .SetFont(TitleFont)
        .SetAlignment(HorizontalAlignment.Center);
        s.AddLine()
        .SetColor(Color.FromRgba(106.0 / 255.0, 85.0 / 255.9, 189.0 / 255.0))
        .SetStyle(Stroke.Solid).SetWidth(2);
}
[/code]

3.8. Add invoice text to the current section.

Add Paragraph to a current section with AddParagraph() method and set it’s font and margins.
Then call one of the AddText() methods which receives string as a parameter and pass invoice text there.
In order to add clickable URL to the current paragraph, just call Paragraph’s extension method AddUrl():

[code]
internal static void AddInvoiceText(Section s)
{
    Paragraph p =
        s.AddParagraph()
            .SetMargins(20, 0, 0, 10)
            .SetFont(DocumentFont);
       
        p.AddText(InvoiceText);
        p.AddUrl("support@yourhomeprovider.com");
}   
[/code]

3.9. Add table with the data from input JSON file.

Method AddTable() adds table to the section. Then hide table borders. After that you can just pass data to the table by calling SetDataSource(InvoiceData):

[code]
internal static void AddInvoiceTable(Section s)
{
    Table t = s.AddTable();
    t.HeaderRowStyle
        .SetBorderStyle(Stroke.None)
        .SetFont(HiddenFont)
        .Border.SetWidth(0.0f);
    t.ContentRowStyle
        .SetBorderStyle(Stroke.None)
        .SetFont(ItalicFont)
        .Border.SetWidth(0.0f);
    t.SetDataSource(InvoiceData);
}
[/code]

3.10. Add footer of the invoice.
 
Call method AddSinglePage() of section’s layout and then add repeating area, setting isFooter to True. In this case the area will be placed in the bottom of the page.
The content of the area is added in the configurer as area.AddLine(), area.AddItem<>() (you can add Paragraph, Image or Table as Item):

[code]
internal static void AddFooter(Section s)
{
    s.Layout.AddSinglePage()
        .AddRepeatingArea(s.Page, 160, true, area =>
        {
            area.AddLine()
                .SetColor(Color.FromRgba(106.0 / 255.0, 85.0 / 255.9, 189.0 / 255.0)).SetStyle(Stroke.Solid).SetWidth(2);               
            area.AddItem<Paragraph>(p =>
            {                   
                p.SetMargins(20, 0, 0, 10)
                .AddText("Your Home Provider").SetFont(BoldFont);                   
            });

            area.AddItem<Paragraph>(p =>
            {                   
                p.SetMargins(0, 0, 0, 0)
                    .SetFont(FooterFont)
                    .AddTextToParagraph("Your Home Provider, Inc.")
                    .AddTabSymbol()
                    .AddUrlToParagraph("support@yourhomeprovider.com")
                    .AddTabulation(280, TabulationType.Left);
            });
           
            area.AddItem<Paragraph>(p =>
            {
                p.SetMargins(0, 0, 0, 0)
                    .SetFont(FooterFont)
                    .AddTextToParagraph("666 John Doe Street")
                    .AddTabSymbol()
                    .AddUrlToParagraph("https://yourhomeprovider.com")
                    .AddTabulation(280, TabulationType.Left);
            });
            area.AddItem<Paragraph>(p =>
            {
                p.SetMargins(0, 0, 0, 0)
                    .SetFont(FooterFont)
                    .AddText(new[] { "Santa Barbara, CA 99999", "United States" });
            });
            area.AddItem<Paragraph>(p =>
            {
                    p.SetMargins(0, 0, 0, 0)
                        .SetFont(FooterFont)
                        .AddText("*VAT / GST paid directly by Your Home Provider, Inc., where applicable");
            });
    });
}


4. Generated PDF file should look as shown below:
Image
Nikolay.Gekht
FXCodeBase: Site Admin
 
Posts: 1235
Joined: Wed Dec 16, 2009 6:39 pm
Location: Cary, NC

Return to Gehtsoft PDF.Flow Library

Who is online

Users browsing this forum: No registered users and 1 guest