Golang excel to pdf

Creating PDF Reports in Go with UniPDF

Creating high quality PDF reports can be a challenge for an organization. A company has to create reports for budget, daily activities and project descriptions amongst many more. Creating these reports can be a time consuming process and the majority of them follow a specific template with minimal changes.

For such large-scale repetitive PDF reports that usually follow a template, it is wise to use a software library. UniPDF is one such GoLang based library that offers a diverse set of functionalities that can simplify the task of report generation.

Using the library, you can automate the redundant process of manually creating each PDF. It offers support for adding in images, tables, headers, footers and a lot more. The PDF report generation process is simplified and quickened with the help of the said tools and allows for creating beautifully designed PDF documents.

UniPDF makes it easier for you to place images in the PDF document, without having to worry about coordinates. This removes the burden from the user to calculate the right coordinates to place the image. In UniPDF, you simply input the path to the image, select its size and simply add it where you want to.

Support For Dynamic Content

The most important art of any PDF generation library is its ability to support dynamic content. Let’s say that you have to create PDF invoice or some other report, where each report has some sort of personalized information. Normally, you would have an employee manually create each PDF with personal information of each recipient.

Using UniPDF, you can do this much faster. If the recipient information is stored in a database, then you can have a script extract the data from the database and pass it to the UniPDF library.

This way, you can create hundreds of invoices or reports in a matter of seconds by simply writing a few lines of code. Similarly, you can create a GoLang script that can take data from a .csv file or any other source and create personalized PDF reports.

Generating a PDF Report Using UniPDF

UniPDF has numerous example scripts listed on the GitHub repository that you can use to get started with the library. For this article, we will be discussing the PDF report example in the unipdf-examples repository: pdf_report.go.

The example discusses the use of UniPDF’s creator package to create PDF reports. The creator package was introduced in the v.2 of UniPDF and has been briefly described in the v.2 public release. The package allows you to efficiently work with PDF documents and supports the functionality of adding text, images and other content.

Back to the example, if you’d like to run the default example and check the performance of the UniPDF library, go ahead and clone the unipdf-examples repository.

Inside the report folder: You can run the reporting example with command:

Code Breakdown

If you want to understand the code and learn how you can customize it, then read ahead. We’ll be explaining how you can include text, images and create tables in your PDF report. By the end of this guide, you should be able to create a basic PDF report using UniPDF. You can also find the full example here.

The first few lines of the code mention the packages that have to be included to run the code. The packages required to run the reporting example are:

import (
    "bytes"
    "fmt"
    "image"
    "math"
    "time"

    "github.com/wcharczuk/go-chart"

    "github.com/boombuler/barcode"
    "github.com/boombuler/barcode/qr"

    "github.com/unidoc/unipdf/v3/common"
    "github.com/unidoc/unipdf/v3/creator"
    "github.com/unidoc/unipdf/v3/model"
)

The creator and model are the main UniPDF packages and were originally released in the v.2 of UniDoc and further improved after the release of v.3.

The creator model makes it easy for you to edit the PDF documents and includes the functions needed for the manipulation of PDFs. The purpose of the creator package is to create beautifully formatted reports.

The model package builds on the core package of UniPDF and contains important functions that deals with the read and write of PDF documents.

As the names explain, the go-chart, barcode and qr packages enable the inclusion of the respective elements in the reports. The math and time packages let you perform mathematical calculations and the time measurement respectively. The fmt package is a native GoLang package that deals with I/O processes. Similarly, the remaining packages help by including some useful functionality.

How to Add Paragraphs

Let’s start with the basics. Let’s try to add some text on a new page of your PDF document. The first step would be the creation of your main() function.

Main Function

func main() {
    err := RunPdfReport("unidoc-report.pdf")
    if err != nil {
        panic(err)
    }
}

The main function simply calls the RunPdfReport(“report_name.pdf”) function. It checks that if the function fails to complete its execution then it will report an error.

RunPdfReport Function

This is where all the action takes place. This is a customized function that takes care of our requirements. It accepts an output path as an argument.

func RunPdfReport(outputPath string) error {
    robotoFontRegular, err := model.NewPdfFontFromTTFFile("./Roboto-Regular.ttf")
    if err != nil {
        return err
    }

    robotoFontPro, err := model.NewPdfFontFromTTFFile("./Roboto-Bold.ttf")
    if err != nil {
        return err
    }

The first few lines of the function open the font files of your choice, the ones listed here are available in the example repo. You can change them to any other font and you simply have to replace the name of the font file in the argument of the NewPdfFontFromTTFFile(“font_file.tff”) function.

Adding Paragraphs

To create the content, the first step is to initialize a creator object. This object has the functions to create new pages, add text, images and a whole lot more.

    c := creator.New()
    c.SetPageMargins(50, 50, 100, 70)

Creating a creator is as simple as shown above, we also define the margins of the page by using its native SetPageMargins(x,y,z,k) function.

    c.NewPage()

    ch := c.NewChapter("Feature Overview")

    chapterFont := robotoFontPro
    chapterFontColor := creator.ColorRGBFrom8bit(72, 86, 95)
    chapterRedColor := creator.ColorRGBFrom8bit(255, 0, 0)
    chapterFontSize := 18.0

    normalFont := robotoFontRegular
    normalFontColor := creator.ColorRGBFrom8bit(72, 86, 95)
    normalFontColorGreen := creator.ColorRGBFrom8bit(4, 79, 3)
    normalFontSize := 10.0

    ch.GetHeading().SetFont(chapterFont)
    ch.GetHeading().SetFontSize(chapterFontSize)
    ch.GetHeading().SetColor(chapterFontColor)

    p := c.NewParagraph("This chapter demonstrates a few of the features of UniDoc that can be used for report generation.")
    p.SetFont(normalFont)
    p.SetFontSize(normalFontSize)
    p.SetColor(normalFontColor)
    p.SetMargins(0, 0, 5, 0)
    ch.Add(p)

    // Paragraphs.
    sc := ch.NewSubchapter("Paragraphs")
    sc.GetHeading().SetMargins(0, 0, 20, 0)
    sc.GetHeading().SetFont(chapterFont)
    sc.GetHeading().SetFontSize(chapterFontSize)
    sc.GetHeading().SetColor(chapterRedColor)

    p = c.NewParagraph("Paragraphs are used to represent text, as little as a single character, a word or " +
        "multiple words forming multiple sentences. UniDoc handles automatically wrapping those across lines and pages, making " +
        "it relatively easy to work with. They can also be left, center, right aligned or justified as illustrated below:")
    p.SetFont(normalFont)
    p.SetFontSize(normalFontSize)
    p.SetColor(normalFontColorGreen)
    p.SetMargins(0, 0, 5, 0)
    p.SetLineHeight(2)
    sc.Add(p)

To start adding text, we first create a new page by using the creator. It’s worth mentioning here that you can create structured reports using UniPDF since it allows you to create hierarchical chapters and subchapters.

In the code above, we are creating a Feature Overview chapter, and defining its property such as font style, colour (RBG) and size of the heading and the paragraphs inside. These properties are assigned to the heading by using the GetHeading().SetFont() function.

The paragraphs are generated using the creator and are assigned to the chapter by ch.Add(p).

To create a subchapter, we use its parent chapter’s NewSubchapter(“name”) function. This creates a hierarchical link between the chapters and subchapters. After that, similar to the chapter, we set its font and styles.

Example of creating chapters and paragraphs for PDF reports
Fig 1: Creating Chapters and Adding Paragraphs

Formatted text via StyledParagraphs

A great feature of UniPDF is StyledParagraph, which allows you to change the style of different chunks of the same paragraph. Its implementation has been shown below.

    // Styled paragraphs.
    stChap := sc.NewSubchapter("Styled Paragraphs")
    sc.GetHeading().SetMargins(0, 0, 20, 0)
    sc.GetHeading().SetFont(chapterFont)
    sc.GetHeading().SetFontSize(chapterFontSize)
    sc.GetHeading().SetColor(chapterRedColor)

    stylPar := c.NewStyledParagraph()
    stylPar.SetLineHeight(3)

    boldStyle := c.NewTextStyle()
    boldStyle.Font = robotoFontPro
    boldStyle.Color = creator.ColorGreen
    chunk := stylPar.Append("This text is bolded and is in green color. We're showing how styled paragraphs work.")
    chunk.Style = boldStyle

    normStyle := c.NewTextStyle()
    normStyle.Font = robotoFontRegular
    normStyle.Color = creator.ColorBlue
    chunktwo := stylPar.Append("You can change the size, color and almost anything of the font using the StyledParagraph command. This font is in blue color and is not bold.")
    chunktwo.Style = normStyle

    hugeStyle := c.NewTextStyle()
    hugeStyle.Font = robotoFontRegular
    hugeStyle.FontSize = 25
    chunkthree := stylPar.Append("This is HUGE and black.")
    chunkthree.Style = hugeStyle

    stChap.Add(stylPar)

We’re creating a new subchapter titled Styled Paragraphs, which contains a styled paragraph, which is further decomposed to uniquely styled chunks. The first chunk has a bold font and is of colour green.

Similarly, we create two more styled chunks, one is of normal font but of the colour blue. The final chunk has the colour black and a huge font size. You can edit the code to create customized paragraphs containing different styles.

The code generates the output shown in figure 2.

Example of creating formatted styled paragraphs for PDF reports
Fig 2: Adding Styled Paragraphs

Adding Tables

Now let’s move on to tables, we’re going to extend the code we used above to also generate tables in a subchapter.

    // TABLES CHAPTER.
    subChap := sc.NewSubchapter("Tables")
    subChap.GetHeading().SetMargins(0, 0, 20, 0)
    subChap.GetHeading().SetFont(chapterFont)
    subChap.GetHeading().SetFontSize(chapterFontSize)
    subChap.GetHeading().SetColor(chapterFontColor)

    ptwo := c.NewParagraph("We can also create tables using UniPDF library. Its pretty simple, read the guide to learn how we created the tables shown  below.")
    ptwo.SetFont(normalFont)
    ptwo.SetFontSize(normalFontSize)
    ptwo.SetColor(normalFontColor)
    ptwo.SetMargins(0, 0, 5, 0)
    ptwo.SetLineHeight(2)
    subChap.Add(ptwo)

    // Tables
    issuerTable := c.NewTable(2)
    issuerTable.SetMargins(0, 0, 30, 0)
    pColor := creator.ColorRGBFrom8bit(72, 86, 95)
    bgColor := creator.ColorRGBFrom8bit(56, 68, 67)

We create a subchapter, Tables and give it an opening paragraph. A table is added under this chapter.

You can initialize a table by using the creator and pass the number of columns in the arguments. In this code, we’ve set the number of columns to 2. We’ve also defined the colours of the header and contents to make it easy to distinguish between the two.

    // Creating First ROW:
    p = c.NewParagraph("Issuer")
    p.SetFont(robotoFontPro)
    p.SetFontSize(10)
    p.SetColor(creator.ColorWhite)
    cell := issuerTable.NewCell()
    cell.SetBorder(creator.CellBorderSideAll, creator.CellBorderStyleSingle, 1)
    cell.SetBackgroundColor(bgColor)
    cell.SetContent(p)

    p = c.NewParagraph("UniDoc")
    p.SetFont(robotoFontRegular)
    p.SetFontSize(10)
    p.SetColor(pColor)
    cell = issuerTable.NewCell()
    cell.SetBorder(creator.CellBorderSideAll, creator.CellBorderStyleSingle, 1)
    cell.SetContent(p)

After the table has been initialized, we move forward to create the rows and in the code shown above, we’re adding two rows. We’re setting the background colours, borders and the colour of the font of the cells. Everything is customizable and you can change it to meet your needs.

Figure 3 shows the table created using the code above, it contains more rows than the ones mentioned in the code above.

Example of creating tables and inserrting row in PDF reports
Fig 3: Creating Tables and Adding Rows

Adding Images

Images can be added in the PDF reports by using UniPDF’s creator package, which contains an inbuilt image reader. It supports all major formats of images, in this example, we are adding a PNG file.

    // Adding Images.
    subChap = ch.NewSubchapter("Images")
    subChap.GetHeading().SetMargins(0, 0, 20, 0)
    subChap.GetHeading().SetFont(chapterFont)
    subChap.GetHeading().SetFontSize(chapterFontSize)
    subChap.GetHeading().SetColor(chapterFontColor)
    ptwo = c.NewParagraph("UniPDF also provides you with the power to add images in your PDF documents. This is a very simple process and you can position images quite accurately. This enables you to create aesthetically beautiful reports. The library supports multiple image formats, here's an example with a PNG image.")
    ptwo.SetFont(normalFont)
    ptwo.SetFontSize(normalFontSize)
    ptwo.SetColor(normalFontColor)
    ptwo.SetMargins(0, 0, 5, 0)
    ptwo.SetLineHeight(2)
    subChap.Add(ptwo)

    // Show logo.
    img, err := c.NewImageFromFile("./unidoc-logo.png")
    if err != nil {
        panic(err)
    }
    img.ScaleToHeight(50)

    subChap.Add(img)

In this code, we’re creating a new subchapter for images and giving it an opening paragraph. The image is read by using the creator’s NewImageFromFile(“path_to_img”) function and added to the chapter.

The code generates the following output:

Example of adding images to PDF reports
Fig 4: Adding Images

Adding Headers and Footers

To add a logo image in the header of your PDF report, we can call the creator’s DrawHeader() function.

    // Show logo.
    logoimg, err := c.NewImageFromFile("./unidoc-logo.png")
    if err != nil {
        panic(err)
    }

    c.DrawHeader(func(block *creator.Block, args creator.HeaderFunctionArgs) {
        // Draw the header on a block.
         logoimg.ScaleToHeight(25)
         logoimg.SetPos(58, 20)
         block.Draw(logoimg)
    })

The code is short and precise. You call the draw header function and in its arguments, you pass a block, which is equal the size of the page’s top margins.

We used the same logo we used earlier and set its size and position within the block before drawing it. The position we set in this context is relative to the position of the block.

The output can be viewed in the figure below

Example of creating a header and adding a logo to a PDF report
Fig 5: Adding Logo in Header

Similarly, we can create a footer by using the DrawFooter() function of the creator. The code for it is as follows:

    // Draw footer on each page.
    c.DrawFooter(func(block *creator.Block, args creator.FooterFunctionArgs) {
        // Draw the on a block for each page.
        p := c.NewParagraph("This is a footer")
        p.SetFont(robotoFontRegular)

        p.SetFontSize(8)
        p.SetPos(50, 20)
        p.SetColor(creator.ColorRGBFrom8bit(63, 68, 76))
        block.Draw(p)

        strPage := fmt.Sprintf("Page %d of %d", args.PageNum, args.TotalPages)
        p = c.NewParagraph(strPage)
        p.SetFont(robotoFontRegular)
        p.SetFontSize(8)
        p.SetPos(300, 20)
        p.SetColor(creator.ColorRGBFrom8bit(63, 68, 76))
        block.Draw(p)
    })

We’re creating a footer with a text on the left side and the page number in the center bottom. You can get the page number and the total number of pages by using the arguments passed in the function.

The positions of the paragraphs can easily be adjusted by changing the parameters of the SetPos(x,y) function.

The output of this code is as follows:

Example of creating a footerr and inserting text in a PDF report
Fig 6: Adding Text in Footer

Adding Table of Contents

To add a table of contents, you simply need to define the style of the heading and the contents while initializing a new TOC() object. The code is as follows:

    // Generate the table of contents.
    c.AddTOC = true
    toc := c.TOC()
    hstyle := c.NewTextStyle()
    hstyle.Color = creator.ColorRGBFromArithmetic(0.2, 0.2, 0.2)
    hstyle.FontSize = 28
    toc.SetHeading("Table of Contents", hstyle)
    lstyle := c.NewTextStyle()
    lstyle.FontSize = 14
    toc.SetLineStyle(lstyle)

    c.draw(ch)
    
    err = c.WriteToFile(outputPath)
    if err != nil {
	    return err
    }

We set the boolean AddTOC to true, which tells the creator that there is going to be a table of contents for this report. After which, we initialize the inbuilt TOC() object and define the style of the heading and the lines.

UniPDF automatically creates an anchored table of content consisting of the chapters and subchapters that you create. The last few lines simply draw the main chapter and then write the whole output to the output path.

The output of the code written above is shown in figure 7.

Example of creating a table of contents and inserting in a PDF report
Fig 7: Creating Table of Content

Conclusion

UniPDF is a highly customizable library written in GoLang, which makes it incredibly fast. Here, we learned how to create a PDF using UniPDF, which also supports compressing, securing and extracting text and images from PDFs.

Check out the examples in the UniPDF repository. They will help you get started on using the UniPDF library. If you feel that more examples are required, open a new issue on the repo and we will try to fulfill your requirements. If you run into any other issues, open an issue on the main unipdf repository or reach out to us.

  • func ConvertDoc(r io.Reader) (string, map[string]string, error)
  • func ConvertDocx(r io.Reader) (string, map[string]string, error)
  • func ConvertHTML(r io.Reader, readability bool) (string, map[string]string, error)
  • func ConvertImage(r io.Reader) (string, map[string]string, error)
  • func ConvertODT(r io.Reader) (string, map[string]string, error)
  • func ConvertPDF(r io.Reader) (string, map[string]string, error)
  • func ConvertPDFText(path string) (BodyResult, MetaResult, error)
  • func ConvertPages(r io.Reader) (string, map[string]string, error)
  • func ConvertPathReadability(path string, readability bool) ([]byte, error)
  • func ConvertPptx(r io.Reader) (string, map[string]string, error)
  • func ConvertRTF(r io.Reader) (string, map[string]string, error)
  • func ConvertURL(input io.Reader, readability bool) (string, map[string]string, error)
  • func ConvertXML(r io.Reader) (string, map[string]string, error)
  • func DocxXMLToText(r io.Reader) (string, error)
  • func HTMLReadability(r io.Reader) []byte
  • func HTMLToText(input io.Reader) string
  • func MimeTypeByExtension(filename string) string
  • func SetImageLanguages(…string)
  • func Tidy(r io.Reader, xmlIn bool) ([]byte, error)
  • func XMLToMap(r io.Reader) (map[string]string, error)
  • func XMLToText(r io.Reader, breaks []string, skip []string, strict bool) (string, error)
  • type BodyResult
  • type HTMLReadabilityOptions
  • type LocalFile
    • func NewLocalFile(r io.Reader) (*LocalFile, error)
    • func (l *LocalFile) Done()
  • type MetaResult
  • type Response
    • func Convert(r io.Reader, mimeType string, readability bool) (*Response, error)
    • func ConvertPath(path string) (*Response, error)

This section is empty.

This section is empty.

ConvertDoc converts an MS Word .doc to text.

ConvertDocx converts an MS Word docx file to text.

ConvertHTML converts HTML into text.

ConvertImage converts images to text.
Requires gosseract (ocr build tag).

ConvertODT converts a ODT file to text

ConvertPages converts a Pages file to text.

ConvertPathReadability converts a local path to text, with the given readability
option.

ConvertPptx converts an MS PowerPoint pptx file to text.

ConvertRTF converts RTF files to text.

ConvertURL fetches the HTML page at the URL given in the io.Reader.

ConvertXML converts an XML file to text.

DocxXMLToText converts Docx XML into plain text.

HTMLReadability extracts the readable text in an HTML document

HTMLToText converts HTML to plain text.

MimeTypeByExtension returns a mimetype for the given extension, or
application/octet-stream if none can be determined.

func SetImageLanguages(...string)

SetImageLanguages sets the languages parameter passed to gosseract.

Tidy attempts to tidy up XML.
Errors & warnings are deliberately suppressed as underlying tools
throw warnings very easily.

XMLToMap converts XML to a nested string map.

XMLToText converts XML to plain text given how to treat elements.

type HTMLReadabilityOptions struct {
	LengthLow             int
	LengthHigh            int
	StopwordsLow          float64
	StopwordsHigh         float64
	MaxLinkDensity        float64
	MaxHeadingDistance    int
	ReadabilityUseClasses string
}

HTMLReadabilityOptions is a type which defines parameters that are passed to the justext package.
TODO: Improve this!

var HTMLReadabilityOptionsValues HTMLReadabilityOptions

HTMLReadabilityOptionsValues are the global settings used for HTMLReadability.
TODO: Remove this from global state.

type LocalFile struct {
	*os.File
	
}

LocalFile is a type which wraps an *os.File. See NewLocalFile for more details.

NewLocalFile ensures that there is a file which contains the data provided by r. If r is
actually an instance of *os.File then this file is used, otherwise a temporary file is
created and the data from r copied into it. Callers must call Done() when
the LocalFile is no longer needed to ensure all resources are cleaned up.

func (l *LocalFile) Done()

Done cleans up all resources.

type MetaResult struct {
	
}

Meta data

Response payload sent back to the requestor

Convert a file to plain text.

ConvertPath converts a local path to text.

Pure data is for computers and nerds like you and me. Anyone else likes nicely formatted reports. Go and a good PDF package can help.


The above video is available on the
Applied Go channel on YouTube.
This article examines the code used in the video.


Numbers have an important story to tell. They rely on you to give them a clear and convincing voice.

(Stephen Few)

In the last article we exported orders from a spreadsheet and turned them into a report that we saved as CSV data.

Now our boss requests this data as a shiny PDF report on her desk. Let’s do that, no problem! But wait, the standard library has no PDF package, right? Luckily, after a short search, we find a package called
gofpdf on GitHub.

After go getting the package, we can start coding right away.

package main

import (
	"encoding/csv"
	"log"
	"os"
	"time"

	"github.com/jung-kurt/gofpdf"
)
	pdf = header(pdf, data[0])
	pdf = table(pdf, data[1:])
	pdf = image(pdf)

	if pdf.Err() {
		log.Fatalf("Failed creating PDF report: %sn", pdf.Error())
	}
	err := savePDF(pdf)
	if err != nil {
		log.Fatalf("Cannot save PDF: %s|n", err)
	}
}

Side Note: gofpdf Error Handling

A somewhat unusual feature of gofpdf is that it does not return errors in the usual way. Instead, if one of the methods of the Fpdf object triggers any error, the Fpdf object stores this error and lets all subsequent method calls “fall through”.

The error can then be verified by calling Fpdf’s Err() method, and printed by calling its Error() method.

if pdf.Err() {
    log.Fatalf("Cannot create PDF: %sn", pdf.Error())
}

We make use of this error mechanism in main(), after all PDF processing is done.

func loadCSV(path string) [][]string {
	f, err := os.Open(path)
	if err != nil {
		log.Fatalf("Cannot open '%s': %sn", path, err.Error())
	}
	defer f.Close()
	r := csv.NewReader(f)
	rows, err := r.ReadAll()
	if err != nil {
		log.Fatalln("Cannot read CSV data:", err.Error())
	}
	return rows
}
func path() string {
	if len(os.Args) < 2 {
		return "ordersReport.csv"
	}
	return os.Args[1]
}
func newReport() *gofpdf.Fpdf {
	pdf := gofpdf.New("L", "mm", "Letter", "")
	pdf.SetFont("Times", "B", 28)
	pdf.Cell(40, 10, "Daily Report")
	pdf.Ln(12)

	pdf.SetFont("Times", "", 20)
	pdf.Cell(40, 10, time.Now().Format("Mon Jan 2, 2006"))
	pdf.Ln(20)

	return pdf
}

How Cell() and Ln() advance the output position

As mentioned in the comments, the Cell() method takes no coordinates. Instead, the PDF document maintains the current output position internally, and advances it to the right by the length of the cell being written.

Method Ln() moves the output position back to the left border and down by the provided value. (Passing -1 uses the height of the recently written cell.)

func header(pdf *gofpdf.Fpdf, hdr []string) *gofpdf.Fpdf {
	pdf.SetFont("Times", "B", 16)
	pdf.SetFillColor(240, 240, 240)
	for _, str := range hdr {
		pdf.CellFormat(40, 7, str, "1", 0, "", true, 0, "")
	}

func table(pdf *gofpdf.Fpdf, tbl [][]string) *gofpdf.Fpdf {
	pdf.SetFont("Times", "", 16)
	pdf.SetFillColor(255, 255, 255)
	align := []string{"L", "C", "L", "R", "R", "R"}
	for _, line := range tbl {
		for i, str := range line {
			pdf.CellFormat(40, 7, str, "1", 0, align[i], false, 0, "")
		}
		pdf.Ln(-1)
	}
	return pdf
}
func image(pdf *gofpdf.Fpdf) *gofpdf.Fpdf {
	pdf.ImageOptions("stats.png", 225, 10, 25, 25, false, gofpdf.ImageOptions{ImageType: "PNG", ReadDpi: true}, 0, "")
	return pdf
}
func savePDF(pdf *gofpdf.Fpdf) error {
	return pdf.OutputFileAndClose("report.pdf")
}

How to get and run the code

Step 1: go get the code. Note the -d flag that prevents auto-installing
the binary into $GOPATH/bin.

go get -d github.com/appliedgo/pdf

Step 2: cd to the source code directory.

cd $GOPATH/src/github.com/appliedgo/pdf

Step 3. Run the binary.

go run pdf.go

Then you should find a file named “report.pdf” in the same directory. The document should look like this:

The finished report

Try pimping up the report a bit! How about:

  • adjusting the column widths
  • ensuring the table always spans the printable width (and then change the orientation to portrait)
  • aligning the decimal points (hint: cheat a bit by using a fixed-width font)

Links

If you want to look into a real-world scenario, read [this blog post] (
https://blog.gopheracademy.com/advent-2017/building-medical-reports-in-go/) from the Gopher Academy Advent series 2017.

And
don’t go overboard with the formatting. Less is more.

Happy coding!

I am writing an api. I want to be able to download the table as pdf and excel with api. How can I convert a struct array to excel and pdf? Is there a library in Golang like datafram.to_excel , dataframe.to_csv in Python?

package main

import (
    "github.com/gocarina/gocsv"
    "github.com/gorilla/mux"
    "log"
    "net/http"
)

type Test struct {
    ID     int    `json:"ID"`
    Name   string `json:"Name"`
    Delete string `json:"Delete"`
}

func main() {

    r := mux.NewRouter().StrictSlash(true)
    r.HandleFunc("/a", func(rw http.ResponseWriter, req *http.Request) {

        tests := []*Test{
            {
                ID:     1,
                Name:   "a",
                Delete: "delete",
            },
            {
                ID:     2,
                Name:   "b",
                Delete: "delete",
            },
        }

        gocsv.Marshal(tests, rw)

    }).Methods(http.MethodGet)

    log.Fatal(http.ListenAndServe(":8000", r))
}

I found something like this to export csv file. Do you have anything you can recommend for PDF and Excel?

Golang is one of the fastest growing languages today. Its popularity has no doubt given rise to a lot of packages being built by the Go community, and we will take a look at one of these packages today.

In this article, we will be taking a look at how we can convert a text file to PDF format with Golang. Excited? So am I! Let’s get into it.

A look at the gofpdf package

The gofpdf package is a document generator with high-level support for text, drawing and images. It was created by Jung Kurt and you can find the GitHub repository here. The repository is currently archived and read-only, but the package is stable enough for our use case.

The package comes with a lot of features like page compression; clipping; barcodes; inclusion of JPEG, PNG, GIF, TIFF and basic path-only SVG images; document protection; charts, etc. The package has no other dependencies other than the Golang standard library.

Installing dependencies

We’ll install two packages, which in this case are the fmt library for printing text out to the console and the github.com/jung-kurt/gofpdf package for converting a text file to PDF format.

Create a file called main.go and paste in the following code:

package main

import (
   "fmt"

   "github.com/jung-kurt/gofpdf"
)

Now, in your terminal, navigate to the directory containing your main.go file and run the command go mod init go-pdf to initialize Go modules in the current directory.

Next, run go mod tidy to download all the required packages.

Run Go Mod Tidy To Download Required Packages

Creating our first PDF file

In order to create our first PDF, we’ll update the main.go file with the following code:

...
func main() {
   pdf := gofpdf.New("P", "mm", "A4", "")
   pdf.AddPage()
   pdf.SetFont("Arial", "B", 16)
   pdf.MoveTo(0, 10)
   pdf.Cell(1, 1, "Hello world")
   err := pdf.OutputFileAndClose("hello.pdf")
   if err == nil {
       fmt.Println("PDF generated successfully")
   }
}

Here, we create a new PDF object with gofpdf.New, set the orientation to portrait, the unit system to millimeters, the paper size to A4, and we leave the option for the font directory as a blank string. Then, we set the font to Arial with a weight of bold and set the font size to 16.

We proceed to create a cell that’s 40mm wide and 10mm high and we write the text “Hello world” in there. Then, we save it to a file called "hello.pdf" and we write out a message saying the PDF was created successfully.

After this, run the command go run main.go to run the code, and you should see a PDF file generated in your current directory.

Run The Command Go Run Main

PDF File Generated

Converting a text file to PDF

To convert a text file to a PDF, first we read the file using the io/ioutil library and write the output to a PDF file. Replace the code in your main.go file with the following:

package main

import (
   "fmt"
   "io/ioutil"

   "github.com/jung-kurt/gofpdf"
)

func main() {
   text, err := ioutil.ReadFile("lorem.txt")
   pdf := gofpdf.New("P", "mm", "A4", "")
   pdf.AddPage()
   pdf.SetFont("Arial", "B", 16)
   pdf.MoveTo(0, 10)
   pdf.Cell(1, 1, "Lorem Ipsum")
   pdf.MoveTo(0, 20)
   pdf.SetFont("Arial", "", 14)
   width, _ := pdf.GetPageSize()
   pdf.MultiCell(width, 10, string(text), "", "", false)
   err = pdf.OutputFileAndClose("hello.pdf")
   if err == nil {
       fmt.Println("PDF generated successfully")
   }
}

First, we read the text from the lorem.txt file, then we write the title of the document as we did before except we change the text to Lorem Ipsum. We move the cursor to the start of the line, then, we set the font size to 14, the font weight to normal, and we create a pdf.Multicell that spans the entire width of the page.

Here, we write the text content in the cell and save to a file called hello.pdf.

Create a file called lorem.txt and paste the following text:

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec varius leo quis augue finibus gravida sit amet vitae ligula. Ut sit amet scelerisque eros. Vivamus molestie purus nec orci porta commodo vel ut erat. Sed tincidunt est vitae ligula sodales, pellentesque aliquet libero ullamcorper. Pellentesque pretium lacinia aliquet. Sed at enim ut nunc aliquet fringilla. Morbi rutrum sed velit non volutpat.
Vivamus in venenatis eros. Phasellus purus mauris, mollis in condimentum sed, convallis dapibus neque. Etiam pharetra ut ex eu blandit. Morbi mattis consectetur posuere. Suspendisse tincidunt nunc vitae nibh condimentum lacinia. Suspendisse pulvinar velit a lectus tristique, sed congue nisi mattis. Proin a aliquet mauris, sed rutrum lorem. Morbi nec tellus ac mi ornare blandit eu sit amet velit.

Now, save and run the command go run main.go and a hello.pdf file should be generated in the current directory.

Hello.pdf File Generated

Conclusion

In this article, we took a look at the gofpdf library and some of its features for generating documents. We also have seen how easy it is to convert a text file to PDF format using the gofpdf library.

Unipdf is a gofpdf alternative that you would like to consider if you are interested in advanced page manipulations. It allows you to create and read PDF files, compress and optimize PDF files, watermark PDF files, process PDF files, and much more.

Check out the gofpdf GitHub repository if you are interested in exploring more about the package and its features.

Cut through the noise of traditional error reporting with LogRocket

LogRocket Dashboard Free Trial Banner

LogRocket is a digital experience analytics solution that shields you from the hundreds of false-positive errors alerts to just a few truly important items. LogRocket tells you the most impactful bugs and UX issues actually impacting users in your applications.

Then, use session replay with deep technical telemetry to see exactly what the user saw and what caused the problem, as if you were looking over their shoulder.

LogRocket automatically aggregates client side errors, JS exceptions, frontend performance metrics, and user interactions. Then LogRocket uses machine learning to tell you which problems are affecting the most users and provides the context you need to fix it.

Focus on the bugs that matter — try LogRocket today.

Like this post? Please share to your friends:
  • Going to the theatre read the word
  • Going round to have a word
  • Going on at the same time word
  • Giving off light word
  • Giving a definition to find a word