Skip to main content

Excel Invoice Template in Power Automate: Fill It from a SharePoint List and Archive Every Invoice as PDF/A with PDF4me

· 32 min read
SEO and Content Writer

PDF4me Excel - Populate is a Power Automate action that fills an Excel invoice template with JSON data. Here a new SharePoint list item supplies the data, Populate writes it into the template's smart markers, and three more PDF4me actions turn the workbook into a compressed PDF/A invoice that SharePoint stores automatically.

Search for an excel invoice template and page one is a gallery. Microsoft, Vertex42, QuickBooks and Square all hand you a well-designed blank workbook, and every one of them stops at the download. None of them says how the template gets filled, which in practice means someone copying a customer's details into cells, exporting to PDF, naming the file and dropping it in a folder, one invoice at a time. This flow keeps the part those pages get right, a template anyone can design in Excel, and removes every step that comes after the download.

The flow at a glance
1. When an item is created
SharePoint trigger on the list named Excel Template. Every new row is one invoice.
2. Compose
Reshapes the flat list row into the nested RootData JSON the template expects.
3. Get file content using path
Reads the Excel invoice template from Shared Documents on every run.
4. Excel - Populate
PDF4me Excel. Writes the JSON into the smart markers on sheet 1.
5. Convert to PDF
PDF4me Convert. Renders the populated workbook as Invoice.pdf.
6. PDF - Compress
Optimize Profile Web. Runs before the archival standard is applied.
7. PDF - Create PdfA
Compliance PdfA2b. The step that turns an invoice into a record.
8. Create file
SharePoint writes ExcelArchived.pdf into /Shared Documents/ArchivedExcel.
The short version

A row lands in a SharePoint list. Power Automate reshapes it into JSON, fills an Excel invoice template with it, converts the workbook to PDF, compresses it, converts it to PDF/A-2b, and writes the result to a SharePoint folder. Eight actions, about thirty-six seconds per invoice, and nobody opens Excel.

Why-Based Q&A

Why use an Excel workbook as the invoice template? Because that is where invoices already get designed. Column widths, merged cells, fonts and borders are all set in Excel, so the person who owns the layout can change it without touching the flow or learning HTML. The only requirement is that each cell holding a value carries a smart marker instead of sample text, and step 4 shows exactly what those look like.

Why does the flow need a Compose action? Because a SharePoint list row is flat and the template is not. The list stores the two line items as ten separate columns, Item1Description through Item2TaxRate. The template has one item row that repeats for every entry in an Items array. Compose is where ten columns become a two-element array, and that array is what makes the row repeat.

Why convert the invoice to PDF/A instead of keeping the .xlsx? A workbook is a live document. Anyone who opens it can change a quantity, and a formula can recalculate to a different total on a different machine. A PDF fixes what was actually invoiced. PDF/A goes one step further and embeds everything needed to render the page, fonts included, which is what you want for a document that usually has to stay readable for years after it was sent.

Why keep the template in a SharePoint library rather than inside the flow? Because the flow reads it fresh on every run. Change the logo, the colours or the column order in SharePoint, and the next invoice uses the new layout without anyone editing the flow. SharePoint version history also keeps every earlier copy of the template, so a bad layout change can be rolled back from there.


What You'll Get

Input: a SharePoint list row holding the invoice header, the customer's details and two line items. Output: a compressed PDF/A-2b invoice, ExcelArchived.pdf, in the /Shared Documents/ArchivedExcel folder of the same site.

SharePoint list named Excel Template with four invoice rows, Shyam Prasad-INV, Sarah Brown - INV 01, Larry Wheels - 01 and Morris - INV, and columns Title, Date and time, DueDate, PONumber, PaymentTerms, CompanyEmail, CompanyAddress, CustomerName, CustomerEmail, CustomerCompany, CustomerAddress, CustomerCityStateZIP, then Description, Qty, UnitPrice, Discount and TaxRate for Item1 and Item2

The data source: one list row per invoice, twenty-two columns wide. The last row, Morris - INV, is the one that produced the sample output.

SharePoint Documents library open at the ArchivedExcel folder, showing ExcelArchived.pdf modified a few seconds ago by the Pdf4me Flow account

ExcelArchived.pdf in the ArchivedExcel folder, written by the flow account a few seconds after the row was added.


What You Need

  • Power Automate. Open Power Automate. A cloud flow on standard connectors. SharePoint and the PDF4me connectors need no premium plan.
  • PDF4me API key. Get your API key. This flow uses three PDF4me connections, PDF4me Excel, PDF4me Convert and PDF4me PDF. One key authorises all three.
  • A SharePoint site with a list whose columns match the Compose mapping, plus a document library for the template and the output. The captured flow uses the list Excel Template, the folder /Shared Documents/Excel Template for the workbook, and /Shared Documents/ArchivedExcel for the invoices.
  • The Excel invoice template. pdf4me-excel-invoice-template.xlsx. One sheet, smart markers already in place.
  • The Compose JSON. compose-rootdata.json. The exact RootData mapping from step 2, ready to paste.
  • The finished invoice. excel-archived-invoice.pdf. PDF/A-2b, exactly what the captured run produced.

Grab the samples first. Upload the template to your SharePoint library, paste the JSON into the Compose action, then compare your first run against the finished invoice. Open its document properties and you should see PDF/A-2b declared. Knowing what a correct output looks like is the quickest way to tell whether your own run really worked.


The Flow at a Glance

  1. When an item is created (SharePoint trigger) watches the list named Excel Template.
  2. Compose builds the RootData JSON from the new row.
  3. Get file content using path reads the template from /Shared Documents/Excel Template.
  4. Excel - Populate (PDF4me Excel) merges the JSON into worksheet 1.
  5. Convert to PDF (PDF4me Convert) renders the workbook as Invoice.pdf.
  6. PDF - Compress (PDF4me PDF) with Optimize Profile Web.
  7. PDF - Create PdfA (PDF4me PDF) with Compliance PdfA2b.
  8. Create file (SharePoint) into /Shared Documents/ArchivedExcel.

Complete flow overview

Power Automate run history showing eight actions succeeding in order: When an item is created at 0.3 seconds, Compose at 0 seconds, Get file content using path at 0.5 seconds, Excel Populate at 0.8 seconds, Convert to PDF at 10 seconds, PDF Compress at 11 seconds, PDF Create PdfA at 11 seconds and Create file at 2 seconds

The run that produced the sample invoice. Convert, Compress and Create PdfA take ten to eleven seconds each, and everything else finishes in under a second apart from the two-second SharePoint write. Budget about thirty-six seconds per invoice.


Step 1: How do you trigger a flow when a SharePoint list item is created?

Flow so far: nothing yet, this is the trigger.

Every new row in the list is one invoice, so the trigger is the list itself.

  1. Create an Automated cloud flow and pick SharePoint > When an item is created.
  2. Configure:
    • Site Address: PDF4me Sharepoints - https://ynoox1.sharepoint.com/sites/PDF4meSharepoints
    • List Name: Excel Template

SharePoint trigger configuration

SharePoint When an item is created trigger panel with Site Address set to PDF4me Sharepoints at ynoox1.sharepoint.com/sites/PDF4meSharepoints and List Name set to Excel Template, advanced parameters showing 0 of 1, connected to SharePoint

One list, one trigger. The list's built-in Title column carries the invoice number, which is why the next step maps Number to Title.

Tip. Expressions use a column's internal name, not the name you see in the list. The list shows a column called Date and time, but the trigger returns it as Dateandtime, and that is the name the Compose has to use. A wrong name does not fail the run. The ? in triggerBody()?['Dateandtime'] quietly returns null instead, so the invoice simply comes out with an empty date.


Step 2: How do you turn a flat SharePoint row into JSON for an Excel template?

Flow so far: SharePoint trigger.

The template expects a nested structure: an invoice header, a company block, a customer block and a list of items. The list row is flat. Compose is the translation layer between the two.

  1. Add Data Operation > Compose.
  2. Paste this into Inputs. Every value is a triggerBody()?['<column>'] expression that points at one list column.
{
"RootData": {
"Invoice": [
{
"Number": "@{triggerBody()?['Title']}",
"Date": "@{triggerBody()?['Dateandtime']}",
"DueDate": "@{triggerBody()?['DueDate']}",
"PONumber": "@{triggerBody()?['PONumber']}",
"PaymentTerms": "@{triggerBody()?['PaymentTerms']}"
}
],
"Company": [
{
"Email": "@{triggerBody()?['CompanyEmail']}",
"Address": "@{triggerBody()?['CompanyAddress']}"
}
],
"Customer": [
{
"Name": "@{triggerBody()?['CustomerName']}",
"Email": "@{triggerBody()?['CustomerEmail']}",
"Company": "@{triggerBody()?['CustomerCompany']}",
"Address": "@{triggerBody()?['CustomerAddress']}",
"CityStateZIP": "@{triggerBody()?['CustomerCityStateZIP']}"
}
],
"Items": [
{
"Description": "@{triggerBody()?['Item1Description']}",
"Qty": "@{triggerBody()?['Item1Qty']}",
"UnitPrice": "@{triggerBody()?['Item1UnitPrice']}",
"Discount": "@{triggerBody()?['Item1Discount']}",
"TaxRate": "@{triggerBody()?['Item1TaxRate']}"
},
{
"Description": "@{triggerBody()?['Item2Description']}",
"Qty": "@{triggerBody()?['Item2Qty']}",
"UnitPrice": "@{triggerBody()?['Item2UnitPrice']}",
"Discount": "@{triggerBody()?['Item2Discount']}",
"TaxRate": "@{triggerBody()?['Item2TaxRate']}"
}
]
}
}

Compose code view

Power Automate Compose action in code view with inputs RootData containing Invoice, Company, Customer and Items arrays, each value mapped to a triggerBody expression such as Title, Dateandtime, DueDate, PONumber, PaymentTerms, CompanyEmail, CustomerName and Item1Description through Item2TaxRate

Invoice, Company and Customer are one-element arrays. Items has two elements, one for each set of item columns in the list.

How each template cell gets its value

Template cellSmart marker in the cellCompose pathSharePoint column
Invoice No. (B12)&=RootData.Invoice.Number(noadd)Invoice[0].NumberTitle
Date (B13)&=RootData.Invoice.Date(noadd)Invoice[0].DateDateandtime
Due Date (B14)&=RootData.Invoice.DueDate(noadd)Invoice[0].DueDateDueDate
PO Number (B15)&=RootData.Invoice.PONumber(noadd)Invoice[0].PONumberPONumber
Payment Terms (B16)&=RootData.Invoice.PaymentTerms(noadd)Invoice[0].PaymentTermsPaymentTerms
Email and Address (B4, B5)&=RootData.Company.Email(noadd) and .AddressCompany[0]CompanyEmail, CompanyAddress
Customer block (B6 to B10)&=RootData.Customer.Name(noadd) and four moreCustomer[0]CustomerName to CustomerCityStateZIP
Item row (A19 to E19)&=RootData.Items.Description, .Qty, .UnitPrice, .Discount, .TaxRateItems[0] and Items[1]Item1 and Item2 columns

The From block (B3) is plain text, PDF4me, so it is the same on every invoice. Replace it with your own company name in the template.


Step 3: Where does the flow read the Excel template from?

Flow so far: SharePoint trigger plus Compose.

The template is an ordinary file in a document library. The flow reads it on every run, so whatever is in SharePoint at that moment is the layout that gets used.

  1. Add SharePoint > Get file content using path.
  2. Configure:
    • Site Address: PDF4me Sharepoints - https://ynoox1.sharepoint.com/sites/PDF4meSharepoints
    • File Path: /Shared Documents/Excel Template/PDF4me_Excel_SharePoint_Template_.xlsx
    • Infer content type (advanced): Yes

Get file content using path configuration

SharePoint Get file content using path action with Site Address PDF4me Sharepoints, File Path /Shared Documents/Excel Template/PDF4me_Excel_SharePoint_Template_.xlsx and the advanced parameter Infer content type set to Yes, connected to SharePoint

The list and the template folder are both called Excel Template. They are different things: one is a list, the other is a folder in Shared Documents.


Step 4: How does Excel - Populate fill an Excel invoice template?

Flow so far: SharePoint trigger plus Compose plus Get file content using path.

This is the step that does the work the template galleries leave to you. Excel - Populate takes the workbook and the JSON, finds every smart marker, and writes the matching value into its cell.

  1. Add Excel - Populate from the PDF4me Excel connection.
  2. Configure:
    • File Content: the Body token from Get file content using path
    • JSON Data: the output of Compose (the token shows as Body)
    • File Name: Populate.xlsx
    • Worksheet Indexes: 1
  3. Open Advanced parameters and set three of the four:
    • Strict JSON Strings: Yes
    • Culture & Language Settings: en-US
    • Calculate Formulas: Yes

Excel - Populate configuration

PDF4me Excel Populate action with File Content set to the Body token from SharePoint, JSON Data set to the Body token from Compose, File Name Populate.xlsx, Worksheet Indexes 1, and advanced parameters Strict JSON Strings Yes, Culture and Language Settings en-US and Calculate Formulas Yes, connected to PDF4me Excel

Two inputs carry the work: the template bytes from SharePoint and the JSON from Compose. Everything else is formatting and scope.

The template uses two kinds of marker, and the difference between them is the whole trick:

  • Header cells such as Invoice No. hold &=RootData.Invoice.Number(noadd). The (noadd) modifier writes the value in place and never inserts a row.
  • The item row holds &=RootData.Items.Description, &=RootData.Items.Qty and so on, with no modifier. That row is written once for every element of the Items array, so two items produce two rows, and a third item would produce a third.

The full grammar, including modifiers, nested paths and formula handling, is in the Excel Populate syntax overview. For the Populate action on its own, with a Dropbox template and an inline JSON payload, see populating an Excel template from JSON in Power Automate.

Tip. Every value in the Compose sits inside quotes as a string interpolation, so quantities and prices reach the template as text. With Strict JSON Strings set to Yes they stay text, which prints correctly and is all this template needs. If you add a line total or a SUM, set it to No so numeric-looking strings become real numbers. Otherwise SUM skips them, because Excel does not add up numbers stored as text.


Step 5: How do you convert the populated workbook to PDF?

Flow so far: SharePoint trigger plus Compose plus Get file content using path plus Excel - Populate.

The populated workbook only exists inside the run. It is never saved as an .xlsx; it goes straight into the converter.

  1. Add Convert to PDF from the PDF4me Convert connection.
  2. Configure:
    • File Content: the Output File Content token from Excel - Populate
    • File Name: Invoice.pdf

Convert to PDF configuration

PDF4me Convert to PDF action with File Content set to the Output File Content token from Excel Populate and File Name set to Invoice.pdf, connected to PDF4me Convert

Output File Content is the populated workbook. It never touches SharePoint as an .xlsx.

Tip. The captured flow passes Invoice.pdf as the File Name and still converts correctly. The Convert to PDF reference asks for the source file's extension, though, so Invoice.xlsx is the safer value when you build your own.

Set the page layout in the template, not in the flow. Convert to PDF follows the workbook's page setup. The sample template is slightly wider than one Letter page, so the captured invoice has columns A to D on page one and only the Tax % column on page two. Open the template in Excel, go to Page Layout and set Scale to Fit > Width to 1 page, then save it back to SharePoint. Every invoice after that fits one page across.


Step 6: How do you compress the invoice and convert it to PDF/A?

Flow so far: everything through Convert to PDF.

Two actions from the PDF4me PDF connection, compress first and certify second. Reversing them would let compression rewrite a file that had already been made compliant.

  1. Add PDF - Compress.
    • File Content: the Body token from Convert to PDF
    • File Name: the headers/FileName token carried through from the previous action
    • Optimize Profile: Web
  2. Add PDF - Create PdfA.
    • File Content: the Body token from PDF - Compress
    • File Name: the headers/FileName token
    • Compliance: PdfA2b
    • Allow Upgrade: Yes
    • Allow Downgrade: Yes

Compress and Create PdfA parameters

ActionParameterValue used hereWhat it controls
PDF - CompressOptimize ProfileWebTrades size against fidelity. A text-and-table invoice with no images has little for it to degrade.
PDF - Create PdfACompliancePdfA2bISO 19005-2, level B. The page renders the same way on any viewer, years from now.
PDF - Create PdfAAllow UpgradeYesLets the action settle on a higher level when the requested one is not reachable.
PDF - Create PdfAAllow DowngradeYesLets it settle on a lower level instead of failing outright.
PDF4me PDF Compress action with File Content set to the Body token, File Name set to the headers FileName token, and Optimize Profile set to Web, connected to PDF4me PDF

Compress works on the converted invoice, before anything is certified.

PDF4me PDF Create PdfA action with File Content set to the Body token, File Name set to the headers FileName token, Compliance PdfA2b, Allow Upgrade Yes and Allow Downgrade Yes, connected to PDF4me PDF

Create PdfA is the last action to touch the document, which is exactly where it belongs.

The same pair does the same job on files that are already in SharePoint in PDF archiving in Power Automate with an unattended SharePoint folder.


Step 7: Where does the finished invoice get saved?

Flow so far: everything through Create PdfA.

The last action writes the certified invoice back into the same SharePoint site.

  1. Add SharePoint > Create file.
  2. Configure:
    • Site Address: PDF4me Sharepoints - https://ynoox1.sharepoint.com/sites/PDF4meSharepoints
    • Folder Path: /Shared Documents/ArchivedExcel
    • File Name: ExcelArchived.pdf
    • File Content: the Body token from PDF - Create PdfA

SharePoint Create file configuration

SharePoint Create file action with Site Address PDF4me Sharepoints, Folder Path /Shared Documents/ArchivedExcel, File Name ExcelArchived.pdf and File Content set to the Body token from PDF Create PdfA, connected to SharePoint

Every PDF4me action outputs a token called Body, so the label alone does not tell you which one you picked. Hover it, or check the code view for body('PDF_-_Create_PdfA').

Change this before you go live. ExcelArchived.pdf is a fixed name, so every new list item writes to the same file and the folder never holds more than the latest invoice. Build the name from the row instead. The list item ID is unique by definition, so concat('Invoice-', triggerBody()?['ID'], '.pdf') always works. The invoice number in Title works too, as long as it never contains characters SharePoint rejects in file names, such as a slash, a colon, an asterisk or a question mark.


Run the Flow and Verify

  1. Save the flow at the top right.
  2. Add a new item to the list named Excel Template and fill in every column the template uses.
  3. Open the run history. All eight actions should be green, with Convert, Compress and Create PdfA taking most of the time.
  4. Open /Shared Documents/ArchivedExcel and check that the PDF is there, with Modified By showing the flow's account.
  5. Open the file itself and compare it with the list row, then check its document properties for the PDF/A declaration.

The invoice from the captured run is 37,876 bytes. It renders the row Morris - INV: customer Morris Luma at Invoicing.co, dated 2026-09-01 and due 2026-09-20, with two line items, PDF to Excel (quantity 60) and PDFA (quantity 45). Its XMP metadata declares pdfaid:part as 2 and pdfaid:conformance as B, which is PDF/A-2b seen from the inside. It is two pages rather than one, for the page-setup reason covered in step 5.

What did you actually build? An invoicing pipeline where the only manual step is entering the data. The layout lives in an Excel file that anyone can edit, the data lives in a list, and the output is a self-contained archival PDF filed without anyone deciding to file it. The pattern is not tied to Power Automate either: it carries over to Make, Zapier and n8n wherever the PDF4me Excel and PDF/A actions are available.


Common Variations You Can Add Without Rebuilding

Email the invoice to the customer
Add Office 365 Outlook Send an email (V2) after Create file. Put the CustomerEmail column in To and attach the Body output of PDF - Create PdfA, so the customer receives the same PDF/A file that was archived.
Format dates the way your customers read them
The sample prints 2026-09-01 because that is how the trigger returns a date. Wrap the Date and DueDate expressions in the Compose with formatDateTime and a pattern such as 'dd MMM yyyy'.
Add line totals and a grand total
Put the formulas in the template, set Strict JSON Strings to No so quantities and prices arrive as numbers, and leave Calculate Formulas on Yes so the totals are already worked out before the conversion.
Verify the standard instead of assuming it
Add Validate PDFA after Create PdfA and branch on the result. A failed conversion then shows up in the run history instead of in an audit.

How this compares to other ways of producing invoices

Each row describes the alternative. The last row is this flow.

ComparisonWho can change the layoutHow the template gets filledArchival format
Hand-filled Excel template vs this flowAnyone who uses ExcelCopy and paste, one invoice at a timePlain PDF unless someone sets the PDF/A export option
Excel VBA macro vs this flowWhoever maintains the macroAutomatically, on a desktop with the workbook openPlain PDF unless the export is set up for PDF/A
HTML template plus Convert HTML to PDF vs this flowSomeone comfortable with HTML and CSSAutomatically, in the cloudPDF
This flowAnyone who uses ExcelAutomatically, on every new list itemPDF/A-2b

The distinction that matters: the first two keep the layout in Excel but keep a person in the loop, and the third removes the person but moves the layout into code. Only this flow does both.


Common questions

Is there an invoice template in Excel?

Yes. Excel ships with invoice templates: in the desktop app, choose File > New and search for invoice, and Microsoft publishes more in its online template gallery. They are designed to be filled in by hand.

The template used in this post is built for a different job. Its value cells hold smart markers instead of sample text, so a flow can fill it. You can convert any invoice template you already like the same way: keep the design, and replace each value with a marker such as &=RootData.Invoice.Number(noadd).

How to generate invoice from Excel data?

Keep the data in rows, keep the layout in a template, and let something merge the two. Inside Excel alone that something is a Word mail merge or a VBA macro, and both run on someone's desktop.

In this flow the rows live in a SharePoint list, Compose turns one row into JSON, and Excel - Populate merges it into the template. If your data is already an Excel table in OneDrive or SharePoint, the Excel Online (Business) connector's List rows present in a table action can feed the same Compose inside an Apply to each loop, with items('Apply_to_each') in place of triggerBody(). Everything from step 3 onward stays as it is.

How to automate invoices in Excel?

Automating an invoice means removing every step a person does per invoice: typing the values in, exporting to PDF, naming the file and filing it. The template itself stays a normal Excel file.

This flow removes all four. The list row is the only input. The template is filled by Excel - Populate, exported by Convert to PDF, made archival by PDF - Create PdfA, and filed by Create file. Once the file name is built from the row, as step 7 describes, there is nothing left to do by hand.

Can Power Automate convert Excel to PDF?

Yes. In a cloud flow, the OneDrive for Business connector's Convert file action turns an .xlsx into a PDF, but only for a file stored in OneDrive, so SharePoint flows often copy the workbook there first and delete it afterwards.

PDF4me Convert to PDF takes the file content directly from any previous action. That is why the populated workbook in this flow is never saved anywhere: it goes from Excel - Populate straight into the converter, and the only file that ever lands in SharePoint is the finished PDF/A invoice.


Troubleshooting

A field on the invoice comes out blank

Check the column name inside the Compose expression. It must be the internal name, Dateandtime rather than Date and time. The question mark in triggerBody()?['Dateandtime'] turns a wrong name into null instead of an error, so the run stays green and the cell stays empty. If the name is right, check the JSON path against the marker: RootData, then Customer, then Name, spelled the same way in both.

The invoice is two pages, with one column on page two

The template is wider than one printed page. Convert to PDF follows the workbook's page setup, so fix it there: Page Layout, Scale to Fit, Width 1 page. Save the template back to SharePoint and the next run fits one page across.

Only one invoice file is ever in ArchivedExcel

The Create file File Name is the fixed text ExcelArchived.pdf, so every run targets the same name. Make it unique per row with the list item ID, as described in step 7.

The PDF opens fine but is not PDF/A

Create file is reading from PDF - Compress or Convert to PDF instead of PDF - Create PdfA. All three tokens are labelled Body, so the mistake is easy to make and nothing in the run history looks wrong. Confirm the expression is body('PDF_-_Create_PdfA').


Next Steps

The same eight-step pattern (list row, reshape to JSON, fetch the template, populate, convert, compress, certify, save) handles any document that starts life as a spreadsheet: quotes, delivery notes, statements and certificates.