Skip to content

Every 15 minutes

Add emailed invoices to your Excel register

Invoices emailed to you are read, added as rows in your Excel invoice register, and the PDF is saved to OneDrive.

Runs
Every 15 minutes
Apps
Microsoft Excel, Outlook
AI
Yes, uses the built-in AI allowance
Access
Mail.ReadWrite, Files.ReadWrite

Send this to your assistant

Create a ClickRuntime automation: every 15 minutes, check Outlook for new emails with PDF attachments. If it's an invoice, read the supplier, invoice number, date, due date and total with AI, add a row to my Invoices table in Excel, save the PDF to my Invoices folder in OneDrive and mark the email as read.

Paste it into your assistant. It tells you what it will send or change before it runs live.

First time? Adding ClickRuntime to your assistant takes about two minutes.

Why use it

Why teams use this automation

A small company's bookkeeper keeps an Excel register of every supplier invoice. Invoices arrive in a shared Outlook inbox, and each one means opening the PDF, typing five fields into Excel and saving the file somewhere sensible. At month end there is always a backlog.

Reading each invoice as it arrives and filling in the register means the bookkeeper starts month end with the data already there.

What you get out of it

  • No retyping

    Supplier, number, dates and total go straight into the register.

  • PDFs filed in one place

    Every invoice is saved to the same OneDrive folder, named consistently.

  • Month end without the backlog

    The register is current every day, not only after a catch-up session.

  • Only invoices

    Other PDFs, such as brochures or quotes, are ignored.

How it works

What happens, step by step

  1. Every 15 minutes, ClickRuntime checks Outlook for new emails with PDF attachments.

  2. AI reads each PDF and decides whether it is an invoice, then pulls out the supplier, invoice number, dates and total.

  3. A row is added to your Invoices table in Excel and the PDF is saved to your Invoices folder in OneDrive.

  4. The email is marked as read and remembered, so it is never processed twice.

Before it runs live

  • Connect Microsoft Excel
  • Connect Outlook

What you get

RunsEvery 15 minutes
Add emailed invoices to your Excel registertoday, 9:00Succeeded
Excel · InvoicesAcme Fasteners | INV-2207 | 2026-10-17 | 2026-11-16 | 1,240.00

Build your own

Need it to work differently?

This template is a starting point. Copy the prompt and change it, or describe a different automation from scratch, with your own conditions, more apps or an AI step. Your assistant writes it, tests it and runs it on ClickRuntime.
  • Your own rules

    Conditions, thresholds, filters and exceptions, written the way you'd explain them to a colleague.

  • Any number of apps

    One automation can read from one app and update several others. Over 248 apps are ready, and anything with an API works too.

  • AI where it helps

    Summaries, classification, extraction and drafts use ClickRuntime's built-in AI, with no extra key.

  • On a schedule or on each event

    Runs as often as every 5 minutes, or the moment an app sends an event, and keeps track of what it already handled.

Changes you can ask for

  • Act only on the items that match your own rules, and skip the rest
  • Change what the AI looks for, or how it writes the result
  • Add another app, for example also send it to Slack
  • Combine it with other Microsoft Excel and Outlook steps into one automation

Under the hood

The code that runs this automation

This is the Python script that runs each time the automation starts. Your AI assistant writes it for you when you send the prompt, and you allow each step in your assistant. To change how the automation works, describe the change to your assistant and it updates the script for you. For every function it can use, see the script reference.
extract_invoices_from_outlook_into_excel.pyexample
import base64
import io
from pypdf import PdfReader
from clickruntime import on_trigger, report_fetched, http, credentials, ai, state

def graph(method, path, **kw):
    r = http.request(method, "https://graph.microsoft.com/v1.0" + path, headers={"Authorization": f"Bearer {credentials.connection('microsoft', 'work')}"}, **kw)
    return r.raise_for_status() or (r.json() if r.content else None)

pdf_text = lambda b64: " ".join(p.extract_text() or "" for p in PdfReader(io.BytesIO(base64.b64decode(b64))).pages)[:12000]

BOOK = "/me/drive/items/your-workbook-id/workbook"
SCHEMA = {"type": "object", "properties": {"invoice": {"type": "boolean"}, "supplier": {"type": "string"}, "number": {"type": "string"},
          "date": {"type": "string"}, "due": {"type": "string"}, "total": {"type": "number"}}}

@on_trigger
def run(event):
    since = state.get("since") or "2026-01-01T00:00:00Z"
    msgs = graph("GET", "/me/messages", params={"$filter": f"hasAttachments eq true and receivedDateTime gt {since}", "$orderby": "receivedDateTime", "$top": 25})["value"]
    report_fetched(len(msgs))
    if not msgs:
        return {"summary": "No new attachments"}
    added = 0
    for m in msgs:
        for a in graph("GET", f"/me/messages/{m['id']}/attachments")["value"]:
            if a.get("contentType") != "application/pdf":
                continue
            inv = ai.generate(pdf_text(a["contentBytes"]), system="Is this an invoice? Extract supplier, number, date, due date (YYYY-MM-DD) and total.",
                              json_schema=SCHEMA, max_output_tokens=120).json
            if inv["invoice"]:
                graph("POST", f"{BOOK}/tables/Invoices/rows/add", json={"values": [[inv["supplier"], inv["number"], inv["date"], inv["due"], inv["total"]]]})
                name = f"{inv['supplier']}_{inv['number']}_{inv['date']}.pdf".replace(" ", "_").replace("/", "-")
                http.put(f"https://graph.microsoft.com/v1.0/me/drive/root:/Invoices/{name}:/content", data=base64.b64decode(a["contentBytes"]),
                         headers={"Authorization": f"Bearer {credentials.connection('microsoft', 'work')}"}).raise_for_status()
                added += 1
        graph("PATCH", f"/me/messages/{m['id']}", json={"isRead": True})
    state.set("since", msgs[-1]["receivedDateTime"])
    return {"invoices": added}

FAQ

Common questions

How accurate is the extraction?
Very good on clear PDF invoices. Scanned images can be harder; a quick check of new rows is still sensible.
What is the file named in OneDrive?
Supplier, invoice number and date, such as Acme_INV-2207_2026-10-19.pdf.
What if an email has several invoices?
Each PDF is read separately and gets its own row.
What permissions does it need?
Mail.ReadWrite, Files.ReadWrite. Nothing else in your accounts is used.
Does it need AI?
Yes. It uses ClickRuntime's built-in AI, so you don't need an OpenAI or Anthropic key. Every plan includes a monthly AI allowance.
How many runs does it use?
One run each time it checks. Checks that find nothing new and stop right away aren't counted.
Can I change how it works?
Yes. Describe the change to your AI assistant, for example a different schedule, channel or filter. It updates the automation, tests it and tells you what changed.

Set up “Add emailed invoices to your Excel register” from your assistant

Copy the prompt above, or connect your assistant first. Free plan, no credit card.