Abstract / Overview

Build a durable invoice-numbering system in Google Sheets and drive row creation from Make.com. The sheet assigns unique IDs with prefixes and monthly resets using formulas. Make appends new invoices, wait for formulas to populate, reads back the assigned number, and optionally notifies clients. No scripts, no add-ons.

Assumption: You will write to one sheet named Invoices and one sheet named Settings. Time runs in a single IANA timezone (assume UTC unless stated).

ChatGPT Image Sep 5, 2025, 10_11_45 AM

Conceptual Background

Step-by-Step Walkthrough

1) Create the Settings sheet

Add these named values (row 1 are labels; row 2 are values):

SettingValueNotes
PrefixINVShown in every ID
SequenceWidth4Pads sequence to this length
PeriodMonthlyMonthly or Yearly
TimezoneUTCMatch your Make scenario

Define named ranges for A2:D2: Prefix, SequenceWidth, Period, Timezone.

2) Create the Invoices sheet

Header row (begin in A1):

CreatedAt | Customer | Email | Amount | Currency | InvoiceDate | PeriodKey | Seq | InvoiceID | UUID | Notes | Status | Duplicate?

Freeze row 1.

3) Enter array formulas (only once, in row 2)

All formulas below are array formulas. They auto-fill down as rows are appended.

A. Period key (PeriodKey in G2):

=ARRAYFORMULA(
  IF(A2:A="","",
    IF(LOWER(Settings!C2)="yearly",
       TEXT(A2:A,"YYYY"),
       TEXT(A2:A,"YYYYMM")
    )
  )
)

B. Sequence within the period (Seq in H2):
Counts how many rows in the same period were created at or before this row, then zero-pads.

=ARRAYFORMULA(
  IF(A2:A="","",
    TEXT(
      COUNTIFS(G2:G, G2:G, A2:A, "<="&A2:A),
      REPT("0", N(Settings!B2))
    )
  )
)

C. Final invoice ID (InvoiceID in I2):

=ARRAYFORMULA(
  IF(A2:A="","",
    Settings!A2 & "-" & G2:G & "-" & H2:H
  )
)

D. Duplicate detection (Duplicate? in M2):

=ARRAYFORMULA(
  IF(I2:I="","",
    IF(COUNTIF(I2:I, I2:I)>1,"DUPLICATE","")
  )
)

E. Optional sanity checks (not required but helpful):

=ARRAYFORMULA(IF(D2:D="","",IFERROR(D2:D>0, FALSE)))
=ARRAYFORMULA(IF(LEN(L2:L),L2:L,"Unpaid"))

Important: Columns A (CreatedAt) and J (UUID) are values written by Make, not user formulas.

4) Build registry and pivot views (optional but recommended)

5) Prepare Make.com connections

Add Google Sheets and, if you will send emails, Gmail. If you need Slack handoffs, add Slack. Set scenario timezone equal to Settings!D2.

6) Create the “Append and Return InvoiceID” scenario

Core steps:

  1. Trigger: choose one.

    • Webhook when your CRM or form submits an invoice request, or

    • Google Sheets → Watch changes on a staging tab, or

    • Scheduler that consumes a queue.

  2. Set variables: generate createdAt and uuid.

  3. Append row to Invoices.

  4. Wait 1–3 seconds to let formulas calculate.

  5. Find the row by UUID.

  6. Read InvoiceID and continue (e.g., create the PDF in Docs, email the client, or post to Slack).

  7. (Optional) update Status.

You will find a blueprint in the code section.

7) Test the flow

8) Operate day-to-day

Code / JSON Snippets

A) CSV seed for Invoices header

CreatedAt,Customer,Email,Amount,Currency,InvoiceDate,PeriodKey,Seq,InvoiceID,UUID,Notes,Status,Duplicate?

B) Named settings (CSV reference)

Setting,Value
Prefix,INV
SequenceWidth,4
Period,Monthly
Timezone,UTC

C) Make: minimal variable setup (Set multiple variables)

createdAt = {{ formatDate(now; "YYYY-MM-DDTHH:mm:ssZ"; Settings!Timezone) }}
uuid = {{ uuid() }}

D) Make: Gmail notice to team (optional)

To: [email protected]
Subject: New invoice {{InvoiceID}} created
Body: Customer {{Customer}}, Amount {{Amount}} {{Currency}}. Link: (Sheets link to the row)

E) Sample workflow JSON code (Make scenario blueprint)

Replace connection IDs, spreadsheet IDs, and sheet names with your own.

{
  "name": "Create Invoice Row → Return InvoiceID",
  "version": 3,
  "schedule": { "type": "immediate" },
  "modules": [
    {
      "id": "1",
      "name": "Trigger (Webhook)",
      "type": "webhooks",
      "func": "customWebhook",
      "params": { "hookId": "YOUR_WEBHOOK_ID" }
    },
    {
      "id": "2",
      "name": "Set vars",
      "type": "tools",
      "func": "setVars",
      "params": {
        "vars": {
          "createdAt": "{{ formatDate(now; \"YYYY-MM-DDTHH:mm:ssZ\"; \"UTC\") }}",
          "uuid": "{{ uuid() }}",
          "customer": "{{1.body.customer}}",
          "email": "{{1.body.email}}",
          "amount": "{{ toNumber(1.body.amount) }}",
          "currency": "{{ upper(1.body.currency) }}",
          "invoiceDate": "{{ ifempty(1.body.invoiceDate; formatDate(now; \"YYYY-MM-DD\")) }}",
          "notes": "{{ ifempty(1.body.notes; \"\") }}"
        }
      }
    },
    {
      "id": "3",
      "name": "Append row to Invoices",
      "type": "google-sheets",
      "func": "appendRow",
      "params": {
        "connectionId": "conn_sheets_1",
        "spreadsheetId": "YOUR_SPREADSHEET_ID",
        "sheetName": "Invoices",
        "values": [
          "{{2.createdAt}}",
          "{{2.customer}}",
          "{{2.email}}",
          "{{2.amount}}",
          "{{2.currency}}",
          "{{2.invoiceDate}}",
          "", "", "",                 /* PeriodKey, Seq, InvoiceID are formula-driven */
          "{{2.uuid}}",
          "{{2.notes}}",
          "Unpaid",
          ""                          /* Duplicate? formula */
        ]
      }
    },
    {
      "id": "4",
      "name": "Sleep for formulas",
      "type": "tools",
      "func": "sleep",
      "params": { "seconds": 2 }
    },
    {
      "id": "5",
      "name": "Find by UUID",
      "type": "google-sheets",
      "func": "searchRows",
      "params": {
        "connectionId": "conn_sheets_1",
        "spreadsheetId": "YOUR_SPREADSHEET_ID",
        "sheetName": "Invoices",
        "query": "UUID = {{2.uuid}}",
        "limit": 1,
        "considerHeaders": true
      }
    },
    {
      "id": "6",
      "name": "Return InvoiceID",
      "type": "webhooks",
      "func": "responseJson",
      "params": {
        "status": 200,
        "body": {
          "invoiceId": "{{5.values[0].InvoiceID}}",
          "rowNumber": "{{5.rowNumber}}",
          "createdAt": "{{2.createdAt}}"
        }
      }
    }
  ],
  "links": [
    { "from_module": "1", "to_module": "2" },
    { "from_module": "2", "to_module": "3" },
    { "from_module": "3", "to_module": "4" },
    { "from_module": "4", "to_module": "5" },
    { "from_module": "5", "to_module": "6" }
  ]
}

F) Optional: Slack confirmation (post JSON)

{
  "text": "Created invoice *{{5.values[0].InvoiceID}}* for {{2.customer}}: {{2.amount}} {{2.currency}}."
}

Use Cases / Scenarios

No-Code Alternative (Free)

If you prefer a visual, no-code approach, this same Typeform → Google Sheets flow can also be built using Make. It offers a free tier and lets you design the automation with simple drag-and-drop modules—useful if you want filters, branching, or additional app integrations later.

You can explore it here (free account): https://www.make.com/en/register?pc=rohit9910

Limitations / Considerations

Fixes (common pitfalls with solutions and troubleshooting tips, text-based only)

Diagram

innovation-automation

Budget calculation

Let:

Future enhancements