top of page

Make a PDF from Image files

Ever felt the frustration of trying to convert various image types into a PDF without shelling out for a "Premium" action in Power Automate? You're not alone! But guess what? We've cracked the code. Dive into our innovative technique that leverages an HtmlText control to generate HTML, enabling Power Automate to seamlessly create PDF documents. And the best part? This method effortlessly incorporates images from a SharePoint list image column. Ready to revolutionize your workflow? Let's get started!


SharePoint list with image columns

First, you’ll need a SharePoint list with some image columns. We can insert some images into the list, either JPEG or PNG. Then we connect this list as a data source for our app.


Screenshot of a new SharePoint list showing two image columns

Screen with HtmlText and Image controls

Next create a blank app with Power Apps. Add some Image controls to the screen (corresponding with the number of images you want to use) and an HtmlText control. We’re going to add some code (that refers to the image controls) that runs OnVisible property of the screen. The image controls are tied to the SharePoint list images, either through a variable or a LookUp based on the ID or another “key” column (our example is the ParentID column).


How we harness JSON and extract base64

The first thing we do is get the JSON string of the image via the JSON function, then we determine the image format (PNG or JPEG), then we set a formatting variable for string manipulation to extract the base64 string from the JSON string, finally we assign the base64 string to a variable that we can use in our HTML. That’s the key this technique!


Screen OnVisible code

Let’s break down the code in the screen OnVisible, line-by-line. Then we’ll put it all together once we’ve explained it. In this section, our examples show the code as though we’re pulling two images into the HtmlText control, but the steps below just show you how to do it for a single image. (You can repeat this technique for multiple images in your HtmlText control.)


First, we use a With function pointing towards an Image control. You could simply insert the JSON formula into your variable calculation for varImage1, but you’d have to do it 2x. The With function is more performant, as it’s similar to defining a context variable.


With({jsonImage1: JSON(Image1.Image, JSONFormat.IncludeBinaryData)},

Next we use a series of Context variables. Why? Simply because we don’t have to reset them (since they don’t reside in memory beyond the active screen). Since the calculation of subsequent variables depends on the previous variable calculations, we need to use the UpdateContext formula several times, in a sequence.


Our first Context variable is for the image format. It looks for “.png” and “.jp” in the image text string within the JSON data. How can you view this text? Just insert a Text or Label control onto your screen, and make your Image1.Image the Text property, and you can see the complete text string.


Screenshot showing output from Text control and a text string value with .jpg highlighted.

Within that text string, you’ll be able to see the image file suffix, but you must search for it.

So, in the formula, we use the Find formula to look for the image format. The Find formula will either return blank or an integer, so we use a greater than operator to see if the value is greater than 0 to determine what type of image it is (PNG, JPEG or “unknown”). Then we use this value in the next context variable. Additionally, this variable also goes into the HtmlText control in the HTML text string. This is our “Format” variable:


UpdateContext({varImage1Format: If(Find(".png", Step1Image.Image) > 0,"png", If(Find(".jp", Step1Image.Image) > 0,"jpeg","unknown"))})

Our next variable helps us modify our text string to extract the base64. PNG files have base64 code beginning with “iVBOR” whereas JPEG base64 code begins with “/9j/”, so we need to feed different values into our Mid function when we’re extracting the base64 code from the JSON string of the image control. We could have used a single If function, but we wanted to have a way to confirm that the item is a JPEG. We use this variable as input into our next variable that extracts base64. This is our “String manipulation” variable.


UpdateContext({varImage1Code: If(varImage1Format = "png", 24, If(varImage1Format = "jpeg", 25, 24))}),

In our next variable, we slice off everything we don’t need to create the base64 code that our HtmlText control can recognize as an image. This is our “base64” variable.


UpdateContext({varImage1: Mid(jsonImage1, varImage1Code, Max(Len(jsonImage1) - varImage1Code, 0))})

That’s it for the OnVisible coding, here’s the complete block of code (including some remarks):


With({jsonImage1: JSON(Image1.Image, JSONFormat.IncludeBinaryData)},

            //Image1Format looks for .png or .jp(eg) in the text string to determine the format for the HTML

                UpdateContext({varImage1Format: If(Find(".png", Step1Image.Image) > 0,"png", If(Find(".jp", Step1Image.Image) > 0,"jpeg","unknown"))}),

            //Image1Code bases the position for the Mid function to check: 24 for png and 25 for jpeg

            UpdateContext({varImage1Code: If(varImage1Format = "png", 24, If(varImage1Format = "jpeg", 25, 24))}),

            UpdateContext({varImage1: Mid(jsonImage1, varImage1Code, Max(Len(jsonImage1) - varImage1Code, 0))})


Screenshot showing the Screen1 OnVisible property and our coding for two separate images.

Code for the HtmlText control

We inserted an HtmlText control on our screen. Since we’re just using the text from this control in our Power Automate flow, it’s not necessary to make it visible, but we did, just so we could ensure that the images render properly before initiating the flow to turn it into a PDF. To make the image format dynamic, we used our varImage1Format variable. The base64 text string from the image is in varImage1.


This is how we added the code inside of an HtmlText control to display the image:


"<img src='data:image/"&varImage1Format&";base64," & varImage1&"' >"

Screenshot showing the coding inside of teh HtmlText control using img src lines with varImage1format and varImage1 inserted as variables.

In our example above, the image on the left with the cat is a JPEG and the image on the right with the tank is a PNG. Both render properly in the HtmlText control.


(Your HTML can include text, tables, and dynamic content other than your images, but this post focuses on the image piece.) Now you have HTML text that you can submit to Power Automate to build your PDF. Let’s look at how to build your PDF flow.


Create the PDF flow

When you build the flow, if you’re not already in a solution, you should initialize the flow from Power Apps to link it to the app. Else, if you create it straight from Power Automate, you’ll need to add both app and flow into a solution so that you can add the flow to your app. Once you’ve created the flow and it’s tied to your app, you can then enter the flow from Power Automate to continue editing. Let’s go through the flow.


The trigger is “When Power Apps calls a flow (V2)”. Your input must include the text input including the HtmlText from your HtmlText control.


Screenshot from Power Automate showing the trigger When Power Apps calls a flow V2. It has a text input called HtmlText

Then use a OneDrive (for business) “Create file” action. This action will create a temporary HTML file in OneDrive that you can use for the next action. For the “File Name” you can use something like test.HTML. For the “File Content” use the dynamic content for the HTML text input from Power Apps.


The Create file action is depicted here with a file name of test.html and file content as the dynamic HtmlText input coming from the Power Apps trigger.

Next, we use a OneDrive (for business) “Convert file” action. The “File” input is the Id dynamic output from the “Create file” action. Ensure you select PDF (default) as the “Target type”. This step does not create the file; it merely reformats the HTML into PDF. You must save the code next.


Screenshot of the flow action Convert file. It shows the Id dynamic content from the Create file action as the File. and PDF as the Target type.

To save the PDF code, use a “Create file” SharePoint action. This action adds your new PDF to a document library so you can refer to it from your app. You can use dynamic content for the File Name or simply create a name with a suffix of “.pdf”. If you don’t have a unique file name, each subsequent time your flow runs it will fail, because the SharePoint “Create file” action must patch a unique File Name.


In the formula below, using the concat function, utcNow() provides a unique prefix, and then we add ‘.pdf’ to it to correctly identify the file:

concat(utcNow(),’.pdf’)

Optionally, you can include a “Respond to a Power App or flow” step that includes a link to your new document. You can title a text output as “Link” and add a formula using a concat function, similar to this:


concat(‘[your SharePoint document library]’, outputs(‘Create_file’)?[‘body/Path])

This formula adds your document library “https” address such as:

https://shanescows.sharepoint.com/sites/DoeHillDrive

                …to the dynamic content Path from your “Create file” action. You'll simply replace the part of the formula ([your SharePoint document library]) with your own document library.


Screenshot of the Respond to a Power App or flow action. It has a text output showing PetLink with the value as the concat formula with the document library name and the dynamic content of body/Path as the path.

This PdfLink value will be output to Power Apps during the flow run.


You can save (and publish if it’s in a solution) and close your flow.


Finish the app

Return to your app, select the (…) button from the left side rail, and then Power Automate. Make sure that the flow is in your app. Note the schema name under the title, because that’s what you’ll use to call the flow:

 


Screenshot showing the ellipsis on the left side rail highlighted, and the Power Automate flow panel. Highlighted is the schema name of the flow called Create PDF from HtmlText.

Next, we add two button controls to our screen, one for initiating the flow, and the other for using the link that returns from the flow. We’ll name one PDF and the other Link.

Because we used the Respond to a Power App or flow action in Power Automate, we can harvest that link data by adding a Set function to the button calling the flow in the OnSelect property of the PDF button. Here’s an example:

Set( varPdfLink,CreatePDFfromHtmlText.Run(HtmlText1.HtmlText).pdflink);
Screenshot showing the OnSelect property of our PDF button. It uses the formula we have above in the document text.

With the link saved to the global variable called varPdfLink, you can now use that with a Launch function in Power Apps that opens the new PDF document in another browser tab. You can add this code to the OnSelect property of your Link button.

Launch(varPdfLink)

If you run your app, you will be able to use any JPEG and PNG images in your PDF document. You can continue to add HTML code to your HtmlText control to add data to your PDF, but now you understand how to add different image types to the PDF.

Here’s how ours looks:


Please let us know what you think!


For more on this topic, don't forget to check out Shane's video on creating a PDF: Create a PDF from SharePoint Data using Power Apps and Power Automate flow for free

Comments


bottom of page