Blog

News and announcements including new releases, bug fixes and anything newsworthy.

Generating PDF invoices with Go and UniDoc

Creating good-looking PDF invoices from your application tends up to be tedious most of the time. You need to deal with different layouts, design, text-positioning, etc., and that's something most software developers want to avoid.

The most common approach to building PDF files, including invoices, is having an HTML template, filling it up with data, and then converting it to PDF. When converting HTML to PDF, most tools have issues with the PDF layout: margins, page breaks, and text positioning.

By using UniDoc, a comprehensive Golang PDF Library, you'll be creating beautiful PDF invoices from your Go application with only a few lines of code. The example below creates a simple PDF invoice for Jane Doe, containing five products, notes, logo and pricing details.


import (
    "fmt"
    "log"
    "strconv"

    "github.com/unidoc/unidoc/pdf/creator"
    "github.com/unidoc/unidoc/pdf/model"
    "github.com/unidoc/unidoc/pdf/model/fonts"
)

func main() {
    // Instantiate new PDF creator
    c := creator.New()

    // Create a new PDF page and select it for editing
    c.NewPage()

    // Create new invoice and populate it with data
    invoice := createInvoice(c, "logo.png")

    // Write invoice to page
    checkErr(c.Draw(invoice))

    // Write output file.
    // Alternative is writing to a Writer interface by using c.Write
    checkErr(c.WriteToFile("simple_invoice.pdf"))
}

func createInvoice(c *creator.Creator, logoPath string) *creator.Invoice {
    // Create an instance of Logo used as a header for the invoice
    // If the image is not stored localy, you can use NewImageFromData to generate it from byte array
    logo, err := c.NewImageFromFile(logoPath)
    checkErr(err)

    // Create a new invoice
    invoice := c.NewInvoice()

    // Set invoice logo
    invoice.SetLogo(logo)

    // Set invoice information
    invoice.SetNumber("0001")
    invoice.SetDate("28/07/2016")
    invoice.SetDueDate("28/07/2016")
    invoice.AddInfo("Payment terms", "Due on receipt")
    invoice.AddInfo("Paid", "No")

    // Set invoice addresses
    invoice.SetSellerAddress(&creator.InvoiceAddress{
        Name:    "John Doe",
        Street:  "8 Elm Street",
        City:    "Cambridge",
        Zip:     "CB14DH",
        Country: "United Kingdom",
        Phone:   "xxx-xxx-xxxx",
        Email:   "johndoe@email.com",
    })

    invoice.SetBuyerAddress(&creator.InvoiceAddress{
        Name:    "Jane Doe",
        Street:  "9 Elm Street",
        City:    "London",
        Zip:     "LB15FH",
        Country: "United Kingdom",
        Phone:   "xxx-xxx-xxxx",
        Email:   "janedoe@email.com",
    })

    // Add products to invoice
    for i := 1; i < 6; i++ {
        invoice.AddLine(
            fmt.Sprintf("Test product #%d", i),
            "1",
            strconv.Itoa((i-1)*7),
            strconv.Itoa((i+4)*3),
        )
    }

    // Set invoice totals
    invoice.SetSubtotal("$100.00")
    invoice.AddTotalLine("Tax (10%)", "$10.00")
    invoice.AddTotalLine("Shipping", "$5.00")
    invoice.SetTotal("$115.00")

    // Set invoice content sections
    invoice.SetNotes("Notes", "Thank you for your business.")
    invoice.SetTerms("Terms and conditions", "Full refund for 60 days after purchase.")

    return invoice
}

Upon execution, the following PDF file will be generated:

Generated PDF invoice

You can download the PDF file from the above example here.

The above example demonstrated creating a simple PDF invoice. A very similar example is available as a test file here.

The generated invoice is highly customizable. Things like text formatting (font, color, size), page styling and size are easily changeable.

The following function manipulates various parts of the invoice:


func customizeInvoice(i *creator.Invoice) {
    // Load custom font
    fontHelvetica := model.NewStandard14FontMustCompile(fonts.HelveticaName)

    // Create colors from RGB
    lightBlue := creator.ColorRGBFrom8bit(217, 240, 250)
    red := creator.ColorRGBFrom8bit(225, 0, 0)

    // Set invoice title text style
    i.SetTitleStyle(creator.TextStyle{
        Color:    red,
        Font:     fontHelvetica,
        FontSize: 32,
    })

    // Set invoice address heading style
    i.SetAddressHeadingStyle(creator.TextStyle{
        Font:     fontHelvetica,
        Color:    red,
        FontSize: 16,
    })

    // Set columns and rows styling
    //  Line formatting can be changed immediately after adding a line
    for cn, col := range i.Columns() {
        col.BackgroundColor = lightBlue
        col.BorderColor = lightBlue
        col.TextStyle.FontSize = 9
        col.Alignment = creator.CellHorizontalAlignmentCenter

        for _, line := range i.Lines() {
            line[cn].BorderColor = lightBlue
            line[cn].TextStyle.FontSize = 9
            line[cn].Alignment = creator.CellHorizontalAlignmentCenter
        }
    }

    // Change Total text syle
    titleCell, contentCell := i.Total()
    titleCell.BackgroundColor = lightBlue
    titleCell.BorderColor = lightBlue
    contentCell.BackgroundColor = lightBlue
    contentCell.BorderColor = lightBlue

    // Set Note text style
    i.SetNoteHeadingStyle(creator.TextStyle{
        Color:    red,
        Font:     fontHelvetica,
        FontSize: 16,
    })
}

The code for manipulating invoice styling could be done in createInvoice func as well. Upon execution, following invoice is generated:

Modified PDF invoice

Thus, customized invoice generation is quite easy to do with UniDoc. If you have any further requirements please raise an issue on UniDoc's GitHub repository and we will gladly assist you with it.