United Kingdom: +44 (0)208 088 8978

Interacting with Google Slides with .NET in F#

Interact with Google Slides API easily using .NET and F#. In this week's blog post we run through an example of how to customise an existing presentation programmatically.

We're hiring Software Developers

Click here to find out more

Following on from my previous post with regards to how we can use Google APIs in .NET

In this article we are going to take an existing presentation or template and replace some text and images in the presentation. This would most likely work in the flow of

  • Copy an existing presentation to a new file and get the id of that new file
  • Replace text and images in that new file to create a custom presentation

Installation

I will be using a new console application using .NET 6 (the project that this investigation is for uses this) and will install the following packages.

dotnet new console -f net6.0 -lang F# -n SlidesExample

dotnet add package Google.Apis
dotnet add package Google.Apis.Auth
dotnet add package Google.Apis.Slides.v1

Please refer to my previous post on how to set up the Google Cloud, authorise the app and create a Client Service.

Note that when adding the scopes to the OAuth and to your scopes array you will need the following scope 'https://www.googleapis.com/auth/presentations'.

Interacting with Google Slides

let slidesService = new SlidesService(clientService)

let updates = BatchUpdatePresentationRequest(
    Requests = ResizeArray<Request>())

First we create a SlidesService that we can use to make our request later on. Then we initialise a list of requests that we can send to the batch update API to prevent making multiple separate calls.

Replacing text

The main thing here is that we will want to replace any text that has the placeholder value of {{example-name}} and replace it with our alternative text which is Compositional IT.

let subStringMatch = SubstringMatchCriteria(
    Text = "{{example-name}}",
    MatchCase = true)

let replaceText = ReplaceAllTextRequest(
    ContainsText = subStringMatch,
    ReplaceText = "Compositional IT")

let replaceTextRequest = Request(
    ReplaceAllText = replaceText)

Replacing images

Here we will be doing a something similar to text replacement and use a placeholder value of {{example-logo}} but then we need to replace it with our image url and where to place it in the image shape. The Google documentation has details about the various image replace methods.

let replaceImageText = SubstringMatchCriteria(
    Text = "{{example-logo}}",
    MatchCase = true)

let replaceShape = ReplaceAllShapesWithImageRequest(
    ImageUrl = "https://d1q6f0aelx0por.cloudfront.net/product-logos/library-fsharp-logo.png",
    ImageReplaceMethod = "CENTER_INSIDE",
    ContainsText = replaceImageText)

let replaceImageRequest = Request(
    ReplaceAllShapesWithImage = replaceShape)

Making the request

Next we add the two created requests, that we made earlier, to the list of requests.

updates.Requests.Add(replaceTextRequest)
updates.Requests.Add(replaceImageRequest)

And we need to get the ID of an existing file that we have in our Google Drive. You can create your own slideshow slides like shown below or you can go to the sample repo where I have created a slideshow that you can upload to Drive and then convert to a Google Slides document.


After completing the previous step, you can easily obtain the document ID by simply opening the file and observing the URL displayed in the browser.

And finally, we make the request and log out the result to the console.

let updateResponse =
    task {
        return! slidesService.Presentations.BatchUpdate(updates, "1rcTWMDktfWUJRZVX7RdOqNHnLss7alvvCJNYJSqheHA").ExecuteAsync()
    }
    |> Async.AwaitTask
    |> Async.RunSynchronously

let textReplacements =
    updateResponse.Replies
    |> Seq.filter (fun response -> response.ReplaceAllText <> null)
    |> Seq.sumBy (fun response -> response.ReplaceAllText.OccurrencesChanged |> Int.fromNullable)

let imageReplacements =
    updateResponse.Replies
    |> Seq.filter (fun response -> response.ReplaceAllShapesWithImage <> null)
    |> Seq.sumBy (fun response -> response.ReplaceAllText.OccurrencesChanged |> Int.fromNullable)

printfn $"Processed {textReplacements} text replacements and {imageReplacements} image replacements"

When the app has finished running you should see Processed 2 text replacements and 1 images replacements in your console output.

result-page-1
result-page-2

Summary

There are a lot more operations that can be done using the Slides API so please check out the links in Resources which will allow you to create unique presentations from custom templates that can be re-used.

A copy of this code is available at https://github.com/martinbryant/google-apis-example/tree/main/examples/SlidesExample

Resources