HTML for PDF reports in Go
Gunnsteinn Hall
Posted on March 29, 2021
As a developer, I sometimes need to create PDF reports for my applications.
Creating those entirely by programming can be cumbersome and every library is a bit different. Finally, getting things to look like the designer wanted can be challenging.
Wouldn't it be nice if we can make it look like the design without spending a ton of time on it?
Designers and frontenders can usually do HTML and CSS, so it makes sense to utilize HTML.
But websites usually don't look great when printed out and are not designed for multiple pages.
We have come up with a solution, which we believe addresses all of the above.
Meet UniHTML combined with UniPDF
UniHTML is a new plugin for UniPDF, one of our flagship libraries at UniDoc.
It is a container-based solution with a Go driver, as per the schematic:
The Docker image is publicly available on Docker Hub.
The UniPDF creator package enables creating flexible PDF reports and invoices. The UniHTML container-based module has a flexible web-rendering engine and in unison with UniPDF this brings together the capability to add full HTML support to UniPDF report generation.
Trying it out
Let's try it out.
Step 1. Create a free metered API key.
This is easy, simply signing up on https://cloud.unidoc.io for an account and creating a metered API key in the UI.
For step-by-step instructions on this, see:
Step 2. Get the UniHTML container running
$ docker run -p 8080:8080 -e UNIDOC_METERED_API_KEY=mymeteredkey unidoccloud/unihtml
Unable to find image 'unidoccloud/unihtml:latest' locally
latest: Pulling from unidoccloud/unihtml
6e640006d1cd: Pull complete
1a3def68b0c4: Pull complete
5b1718db67b4: Pull complete
8d4c41b870b6: Pull complete
b1a4436c2bab: Pull complete
3c3af5a4fff5: Pull complete
29863d0ede88: Pull complete
Digest: sha256:c1c69af194358179d836a648f07f71af07ed0c968938abe3a3e2550e49980728
Status: Downloaded newer image for unidoccloud/unihtml:latest
[INFO] server.go:173 Listening private API on: :8081
[INFO] server.go:164 Listening public API on: :8080
Step 3. Running an example.
Inspired by the blog post Creating beautiful HTML tables with CSS we put together the following HTML file to illustrate a PDF report with HTML tables.
sample.html
<html>
<head>
<style>
.styled-table {
border-collapse: collapse;
margin: 25px 0;
font-size: 0.9em;
font-family: sans-serif;
min-width: 400px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
}
.styled-table thead tr {
background-color: #009879;
color: #ffffff;
text-align: left;
}
.styled-table th,
.styled-table td {
padding: 12px 15px;
}
.styled-table tbody tr {
border-bottom: 1px solid #dddddd;
}
.styled-table tbody tr:nth-of-type(even) {
background-color: #f3f3f3;
}
.styled-table tbody tr:last-of-type {
border-bottom: 2px solid #009879;
}
.styled-table tbody tr.active-row {
font-weight: bold;
color: #009879;
}
</style>
</head>
<table class="styled-table">
<thead>
<tr>
<th>Name</th>
<th>Points</th>
</tr>
</thead>
<tbody>
<tr>
<td>Dom</td>
<td>6000</td>
</tr>
<tr class="active-row">
<td>Melissa</td>
<td>5150</td>
</tr>
<!-- and so on... -->
</tbody>
</table>
</html>
example.go
package main
import (
"fmt"
"os"
"github.com/unidoc/unihtml"
"github.com/unidoc/unipdf/v3/common/license"
"github.com/unidoc/unipdf/v3/creator"
)
func main() {
// Set the UniDoc license.
if err := license.SetMeteredKey("my api key goes here"); err != nil {
fmt.Printf("Err: setting metered key failed: %v\n", err)
os.Exit(1)
}
// Establish connection with the UniHTML Server.
if err := unihtml.Connect(":8080"); err != nil {
fmt.Printf("Err: Connect failed: %v\n", err)
os.Exit(1)
}
// Get new PDF Creator.
c := creator.New()
// AddTOC enables Table of Contents generation.
c.AddTOC = true
chapter := c.NewChapter("Points")
// Read the content of the sample.html file and load it to the conversion.
htmlDocument, err := unihtml.NewDocument("sample.html")
if err != nil {
fmt.Printf("Err: NewDocument failed: %v\n", err)
os.Exit(1)
}
// Draw the html document file in the context of the creator.
if err = chapter.Add(htmlDocument); err != nil {
fmt.Printf("Err: Draw failed: %v\n", err)
os.Exit(1)
}
if err = c.Draw(chapter); err != nil {
fmt.Printf("Err: Draw failed: %v\n", err)
os.Exit(1)
}
// Write the result file to PDF.
if err = c.WriteToFile("sample.pdf"); err != nil {
fmt.Printf("Err: %v\n", err)
os.Exit(1)
}
}
Results
Running the result:
$ go run example.go
creates sample.pdf
which looks like:
We note that we also have the table of contents
and the bookmarks that link to each chapter in the PDF.
Headers and footers can also be created easily.
Conclusion
UniHTML brings the ease of HTML to PDF report creation in UniPDF with a full rendering engine. This will make the process of PDF report generation really easy for teams that already have a HTML design and need to add professional PDF reports, where a plain PDF print-out of a website is not sufficient.
Posted on March 29, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.