Security Report

This guide will show how to create a security-report document using creator templates.

Before you begin

Before you begin, you should first get your API key from your UniCloud account.

If this is your first time using UniPDF SDK, follow this guide to setup a local development environment.

Clone the project repository

In your terminal, clone the examples repository. It contains the Go code we will be using for this guide.

git clone https://github.com/unidoc/unipdf-examples.git

Navigate to the templates/security-report folder in the unipdf-examples directory.

cd unipdf-examples/templates/security-report

How it works

The following code shows how a security report document document is created using the template.

/*
* This example showcases the usage of creator templates by creating a sample
* security report.
*
* Run as: go run pdf_security_report.go
*/
package main
import (
"bytes"
"io"
"log"
"os"
"sort"
"text/template"
"github.com/unidoc/unichart"
"github.com/unidoc/unichart/dataset"
"github.com/unidoc/unichart/dataset/sequence"
"github.com/unidoc/unichart/render"
"github.com/unidoc/unipdf/v4/common"
"github.com/unidoc/unipdf/v4/common/license"
"github.com/unidoc/unipdf/v4/creator"
)
func init() {
// Make sure to load your metered License API key prior to using the library.
// If you need a key, you can sign up and create a free one at https://cloud.unidoc.io.
err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
if err != nil {
panic(err)
}
common.SetLogger(common.NewConsoleLogger(common.LogLevelDebug))
}
func main() {
c := creator.New()
c.AddTOC = true
c.SetPageMargins(30, 30, 70, 40)
// Read main content template.
mainTpl, err := readTemplate("templates/main.tpl")
if err != nil {
log.Fatal(err)
}
// Draw main content template.
chartMap := map[string]render.ChartRenderable{}
tplOpts := &creator.TemplateOptions{
HelperFuncMap: template.FuncMap{
"CreateLineChart": func(name string, points int, min, max float64) string {
chartMap[name] = createLineChart(points, min, max)
return name
},
"CreateBarChart": func(name string, valMap map[string]interface{}) string {
chartMap[name] = createBarChart(valMap)
return name
},
"CreateStackedBar": createStackedBar,
"CreateStackedBarChart": func(name string, bars ...unichart.StackedBar) string {
chartMap[name] = createStackedBarChart(bars...)
return name
},
"CreatePieChart": func(name string, valMap map[string]interface{}) string {
chartMap[name] = createPieChart(valMap)
return name
},
},
ChartMap: chartMap,
}
if err := c.DrawTemplate(mainTpl, nil, tplOpts); err != nil {
log.Fatal(err)
}
// Draw header.
c.DrawHeader(func(header *creator.Block, args creator.HeaderFunctionArgs) {
// Skip front page.
if args.PageNum == 1 {
return
}
// Read header template.
headerTpl, err := readTemplate("templates/header.tpl")
if err != nil {
log.Fatal(err)
}
// Draw header template.
if err := header.DrawTemplate(c, headerTpl, nil, nil); err != nil {
log.Fatal(err)
}
})
// Draw footer.
c.DrawFooter(func(footer *creator.Block, args creator.FooterFunctionArgs) {
// Skip front page.
if args.PageNum == 1 {
return
}
// Read footer template.
footerTpl, err := readTemplate("templates/footer.tpl")
if err != nil {
log.Fatal(err)
}
// Draw footer template.
data := map[string]interface{}{
"PageNum": args.PageNum,
"TotalPages": args.TotalPages,
}
if err := footer.DrawTemplate(c, footerTpl, data, nil); err != nil {
log.Fatal(err)
}
})
// Draw front page.
c.CreateFrontPage(func(args creator.FrontpageFunctionArgs) {
// Read front page template.
frontPageTpl, err := readTemplate("templates/front-page.tpl")
if err != nil {
log.Fatal(err)
}
// Draw front page template.
if err := c.DrawTemplate(frontPageTpl, nil, nil); err != nil {
log.Fatal(err)
}
})
// Write output file.
if err := c.WriteToFile("unipdf-security-report.pdf"); err != nil {
log.Fatal(err)
}
}
// readTemplate reads the template at the specified file path and returns it
// as an io.Reader.
func readTemplate(tplFile string) (io.Reader, error) {
file, err := os.Open(tplFile)
if err != nil {
return nil, err
}
defer file.Close()
buf := bytes.NewBuffer(nil)
if _, err = io.Copy(buf, file); err != nil {
return nil, err
}
return buf, nil
}
// createPieChart creates a sample pie chart based on the provided values map.
func createPieChart(valMap map[string]interface{}) render.ChartRenderable {
vals := make([]dataset.Value, 0, len(valMap))
for key, val := range valMap {
fVal, _ := val.(float64)
vals = append(vals, dataset.Value{
Label: key,
Value: fVal,
Style: render.Style{
FontSize: 6,
StrokeWidth: 1,
},
})
}
sort.Slice(vals, func(i, j int) bool {
return vals[i].Value < vals[j].Value
})
return &unichart.PieChart{
Values: vals,
}
}
// createPieChart creates a sample line chart based on the provided configuration.
func createLineChart(points int, min, max float64) render.ChartRenderable {
mainSeries := dataset.ContinuousSeries{
XValues: sequence.Wrapper{Sequence: sequence.NewLinearSequence().WithStart(1.0).WithEnd(float64(points)).WithStep(1)}.Values(),
YValues: sequence.Wrapper{Sequence: sequence.NewRandomSequence().WithLen(points).WithMin(min).WithMax(max)}.Values(),
}
linRegSeries := &dataset.LinearRegressionSeries{
InnerSeries: mainSeries,
}
return &unichart.Chart{
Series: []dataset.Series{
mainSeries,
linRegSeries,
},
}
}
// createPieChart creates a sample bar chart based on the provided values map.
func createBarChart(valMap map[string]interface{}) render.ChartRenderable {
chart := &unichart.BarChart{
BarWidth: 20,
BarSpacing: 20,
Bars: parseChartValMap(valMap),
}
// Set Y-axis custom range.
var max float64
for _, bar := range chart.Bars {
if max < bar.Value {
max = bar.Value
}
}
rng := &sequence.ContinuousRange{}
rng.SetMin(0)
rng.SetMax(max)
chart.YAxis.Range = rng
return chart
}
// createPieChart creates a sample stacked bar chart based on the provided bar values.
func createStackedBarChart(bars ...unichart.StackedBar) render.ChartRenderable {
return &unichart.StackedBarChart{
YAxis: render.Style{
FontSize: 6,
},
BarSpacing: 5,
IsHorizontal: true,
Bars: bars,
}
}
// createStackedBar creates a stacked bar based on the provided values map.
// This function is exposed via a helper function so that stacked bar can
// created directly inside template files.
func createStackedBar(name string, valMap map[string]interface{}) unichart.StackedBar {
return unichart.StackedBar{
Name: name,
Width: 20,
Values: parseChartValMap(valMap),
}
}
// parseChartValMap parses a value map and returns it as a dataset slice.
func parseChartValMap(valMap map[string]interface{}) []dataset.Value {
vals := make([]dataset.Value, 0, len(valMap))
for key, val := range valMap {
fVal, _ := val.(float64)
vals = append(vals, dataset.Value{
Label: key,
Value: fVal,
Style: render.Style{
FontSize: 6,
},
})
}
sort.Slice(vals, func(i, j int) bool {
return vals[i].Value < vals[j].Value
})
return vals
}

The import section ind the init function in lines 10-36 imports necessary libraries and loads license key respectively.

The main function is defined in lines 38-139. In this function 39-41 the creator object is instantiated and the margins of the page is set. Also the table of contents generation is set to true using c.AddTOC = true in line 40. In line 44-47 the template file is read using the readTemplate function.

In lines 51-72 the template options object is defined. In lines 74-76 the template is drawn using c.DrawTemplate. In lines 79-95 the header section of the document is drawn. And the footer is drawn using the code in lines 98-119. The front page of the document is drawn using the following code in lines 122-133.

c.CreateFrontPage(func(args creator.FrontpageFunctionArgs) {
		// Read front page template.
		frontPageTpl, err := readTemplate("templates/front-page.tpl")
		if err != nil {
			log.Fatal(err)
		}

		// Draw front page template.
		if err := c.DrawTemplate(frontPageTpl, nil, nil); err != nil {
			log.Fatal(err)
		}
	})

The document is written to file in lines 136-138 using c.WriteToFile("unipdf-security-report.pdf").

The readTemplate function in lines 143-156 reads a template file and returns an io.Reader buffer.

In lines 159-180 the function createPieChart is defined. This function, as its name indicates, is used to create a pie chart. It returns render.ChartRenderable object using unichart.PieChart as can be seen from the code in lines 177-180.

The function createLineChart in lines 183-199 is used to create a line chart. The function createBarChart which is defined in lines 201-222 is used to create a bar chart. In this function the unichart.BarChart object is instantiated in lines 202-206 using the following code.

chart := &unichart.BarChart{
		BarWidth:   20,
		BarSpacing: 20,
		Bars:       parseChartValMap(valMap),
	}

This object is returned by the function after setting the values and the axis values in lines 209-221.

In lines 225-234 the function createStackedBarChart is defined to create stacked bar chart as its name indicates. The function createStackedBar in lines 239-245 is used to create stacked bar. The function parseChartValMap in lines 248-266 is used to parse a value map and returns it as a dataset slice.

Run the code

run the code by using the following command.

go run pdf_security_report.go

Sample Output

preview of the generated document.

Security Report

Got any Questions?

We're here to help you.