Creating PPTX slides from templates - golang

Powerpoint presentations are used whether you are presenting a new product to the world or when you are explaining the budget to the stakeholders. More often than not, these presentations require the inclusion of data that is stored in a database of some sort. Manually extracting the data and converting it into meaningful presentations can be burdensome and slow.

This is especially true if you are not employing tools that can improve this process and automate the presentation creation process. This could be a simple Golang script that reads from your excel sheet and provides you with meaningful output.

However, you cannot directly create powerpoint presentations using Golang. This is where UniOffice helps you and provides you with an interface through which you can transform raw data into beautiful presentations with minimal manual labor.

Your data could be in an excel sheet, in a database or some other data source. Using UniOffice, you can get data from anywhere and use it in your presentations directly. In this article, we will show you how you can use a sample data stored in JSON format for creating presentations by using methods provided by UniOffice.

We’ll be using the empty template shown in the image below to create our required presentations. This tutorial is loosely based on the example found in our GitHub repository here.

Empty PPTX presentation used as a template - UniOffice Golang Figure 1: An empty presentation used as a template.

Creating Presentations Through UniDoc

The first step is to import all of the required packages:

import (
  "fmt"
  "log"

  "encoding/json"

  "github.com/unidoc/unioffice/common/license"
  "github.com/unidoc/unioffice/schema/soo/pml"

  "github.com/unidoc/unioffice/presentation"
)

The next thing you should do is insert your license key, you can get the license key by filling out the free trial form on the UniDoc website.

Once you have the license key, place it in the licenseKey variable and you are reading to start.

const licenseKey = `
-----BEGIN UNIDOC LICENSE KEY-----
Free trial license keys are available at: https://unidoc.io/
-----END UNIDOC LICENSE KEY-----
`

func init() {
  err := license.SetLicenseKey(licenseKey, `danish`)
  if err != nil {
     panic(err)
  }
}

In this tutorial, we are getting the data from a JSON, so for that purpose, we first define the struct that will be used to parse the JSON. Here are the two required structs.

type SaleInfo struct {
  Area string
  Sale string
  Customers int
  Manager string
}

type Data struct {
  Year int
  ID string
  SaleData []SaleInfo
}

We are defining a very basic sales data for some localities. Here is the example data that we will be using in the proceeding steps. The purpose of this tutorial is to guide you regarding the capabilities of the UniDoc library and show you what is possible. By following this guide, we hope that you will be able to extend the application to your own use cases.

jsonData := []byte(`
  {
     "year":2020,
     "id":"JI23SA",
     "saledata":[
        {
           "area": "Michigan",
           "sale": "10 million",
           "customers": 10000,
           "manager": "Henry"
        },
        {
           "area": "Cincinnati",
           "sale": "2 million",
           "customers": 490,
           "manager": "John Green"
        }
     ]
  }
`)

Next up, we have a basic template presentation, which you can download from our GitHub repository. The template is just used to select the theme of the presentation and we will now programmatically insert data into it now.

ppt, err := presentation.OpenTemplate("template.pptx")
if err != nil {
  log.Fatalf("unable to open template: %s", err)
}
defer ppt.Close()
for i, layout := range ppt.SlideLayouts() {
  fmt.Println(i, " LL ", layout.Name(), "/", layout.Type())
}

After opening the template, let’s read the aforementioned JSON into the struct we defined earlier. We can do this by using the encoding/json package that uses the Unmarshal() method to complete this step.

var res Data
err = json.Unmarshal(jsonData, &res)
if err != nil {
  fmt.Printf("Error: %v\n", err)
}
saleData := res.SaleData

We have all the sale data in the saleData variable. Now, let’s iterate through all the records and create a presentation for each one of them.

Let’s create the loop and for each record, clear the template presentation file before proceeding:

for _, data := range saleData { // Iterate through the sale data
// remove any existing slides
for _, s := range ppt.Slides() {
ppt.RemoveSlide(s)
}
.
.
}

The next step is to insert the relevant data into the relevant paragraphs. Since we are looping through the structs, we can access their properties using the (.) dot operator and consequently, place them inside the presentation.

.
.
l, err := ppt.GetLayoutByName("Title and Caption")
if err != nil {
  log.Fatalf("error retrieving layout: %s", err)
}

sld, err := ppt.AddDefaultSlideWithLayout(l)
if err != nil {
  log.Fatalf("error adding slide: %s", err)
}

ph, _ := sld.GetPlaceholder(pml.ST_PlaceholderTypeTitle)
ph.SetText(fmt.Sprintf("Sale Data For: %s", data.Area))
ph, _ = sld.GetPlaceholder(pml.ST_PlaceholderTypeBody)
ph.SetText("Created with github.com/unidoc/unioffice/")

tac, \_ := ppt.GetLayoutByName("Title and Content")

sld, err = ppt.AddDefaultSlideWithLayout(tac)
if err != nil {
  log.Fatalf("error adding slide: %s", err)
}

ph, _ = sld.GetPlaceholder(pml.ST_PlaceholderTypeTitle)
ph.SetText(fmt.Sprintf("Data for %s, Managed by %s", data.Area, data.Manager))
ph, _ = sld.GetPlaceholderByIndex(1)
ph.ClearAll()

para := ph.AddParagraph()
run := para.AddRun()
run.SetText(fmt.Sprintf("Here is the number of sales in %s: \$%s", data.Area, data.Sale))

para = ph.AddParagraph()
run = para.AddRun()
run.SetText(fmt.Sprintf("Number of Customers: %d", data.Customers))

para = ph.AddParagraph()
run = para.AddRun()
run.SetText(fmt.Sprintf("Manager: %s", data.Manager))
.
.

And lastly, let’s check for an error and move on to saving the file named after the area of the sale data.

.
.
if err != nil {
  log.Fatalf("error opening template: %s", err)
}
ppt.SaveToFile(fmt.Sprintf("%s.pptx",data.Area))
}
}

With this, we now should have multiple presentations ready according to our data. An example of a document created from the above code is shown in the figure below.

PPTX slides created from template - golang Figure 2: A presentation created from the template.

Sky’s the Limit

In this tutorial, we highlighted a powerful feature of UniDoc with a very simple data source. By understanding the core concepts behind UniDoc, you should be able to extend these principles onto complex projects and create enterprise level applications.

To check out more of our examples on how you can use UniOffice to fulfill your office requirements, check out our GitHub repository for UniOffice examples. We also host a rich set of examples for UniPDF, which you can check out here. If you want an additional feature to be added, open an issue on GitHub. We are actively improving ourselves to meet the requirements of our users.