Sheets mail mergeDevelopment & Customization

A Google Apps Script that sends personal emails from your Gmail to the people in your Google Sheet

Usually ready in 15 minutesRevisions includedQuality check
Packages
Payment protectionDetails
  • Revisions within the package are free.
  • If you do not respond within 3 days of delivery, the work is accepted automatically.

The money is reserved when you pay and released only once you accept the work.

A Google Apps Script that sends personal emails from your Gmail to the people in your Google Sheet

Example result

Example for the Standard package

Merging the monthly sales files of 9 shops into one Excel report

How it is run

python merge_sales.py --month 2026-10
2026-11-02 09:14:03 INFO  Folder: sales/2026-10, 9 files found
2026-11-02 09:14:03 INFO  shop-01.csv: 1,284 rows
2026-11-02 09:14:04 INFO  shop-02.xlsx: 967 rows
2026-11-02 09:14:04 WARN  shop-07.csv: 3 rows without a price skipped (lines 88, 412, 913)
2026-11-02 09:14:05 INFO  Done: 10,412 rows -> report-2026-10.xlsx (sheets "Sales" and "Totals")

Settings, not code

The column names of each shop live in settings.ini, so a new shop or a renamed column is a line there:

[columns]
date = Date, Sale date, Day
product = Product, Item, Name
quantity = Qty, Quantity, Pcs
price = Price, Unit price

A part of the code

def read_shop_file(path: Path, columns: dict[str, list[str]]) -> pd.DataFrame:
    """Reads one shop's file and gives it the report's column names."""
    table = pd.read_excel(path) if path.suffix == ".xlsx" else pd.read_csv(path, encoding="utf-8-sig")
    renamed = {}
    for name, variants in columns.items():
        found = next((c for c in table.columns if c.strip() in variants), None)
        if found is None:
            raise ReportError(f"{path.name}: no column for '{name}' (looked for {', '.join(variants)})")
        renamed[found] = name
    table = table.rename(columns=renamed)[list(columns)]
    table["shop"] = path.stem
    return table

Files: a ZIP archive with merge_sales.py (310 lines), settings.ini, requirements.txt and a README with installing Python, running the script and what each message in the log means. The client runs it on their own computer.

Client: a small chain of 9 stationery shops; each shop sends its sales for the month as a CSV or Excel file, with slightly different column names. Task: one script that reads every file in a folder, brings the columns to one shape, and writes a single Excel report with all sales and a sheet of totals by shop.

The client and all details are made up.

About this service

When you need to write the same email to 80 clients, students or partners with their name, date or amount in it, copying and pasting takes hours. This Google Apps Script lives in your Google Sheet and sends each row a personal email from your own Gmail: it fills {{Name}}, {{Date}} and any other column into your template, writes Sent and the time into the row and skips rows already sent, so you can run it again safely. It is meant for your own list of people who expect your emails, not for bought lists or cold mass mailing. Google limits how many emails a script can send a day, lower for a free Gmail than for Google Workspace; the script stops at the limit and carries on later. You install and run it in your account.

What is included

  • What you getA ZIP archive with the Apps Script code and a README that shows how to paste it into your sheet, allow access and send; the code is also shown on the order page.
  • Personal fieldsAny column of the sheet in the subject and the text
  • From your own GmailReplies come back to you, like any email you send
  • Sent marksEach row shows when it was sent, so nothing goes twice
  • Within Google's limitsStops at the daily limit and carries on later
  • Readable codeWith comments, easy to change the template later

How it works

  1. 1
    TaskYou send the sheet's columns and the email you want to send
  2. 2
    CodeWe write the script and the guide to installing it
  3. 3
    Try itYou paste it into a copy of the sheet and send to your own address first
  4. 4
    ChangesYou ask for changes within your package and send any error message

What we need from you

The column names of your sheet and two or three rows with made-up names and addresses, the subject and text of the email with the places where columns go, and whether it is plain text or with formatting from a Gmail draft. Who the people on the list are and how they came to it (your clients, members, students), roughly how many rows, and whether you use a free Gmail or Google Workspace. Attachments, if any, and where they are on your Drive.

We will ask you:

  • Who are you writing to?
  • What are the sheet's columns?
  • What should the email say?
  • Free Gmail or Google Workspace?

Compare packages

PackagesBasicSimple mail merge$16StandardMail merge with settings$33PremiumMail merge tool$67
Deadline1 day2 days3 days
Revisions123
Codeup to 150 linesup to 400 linesup to 1,000 lines
Files of code1up to 3up to 8
Settings fileNoYesYes
Clear error messages and a logNoYesYes
Run options and a guide to running it on a scheduleNoNoYes
Guide to installing and running it (README)YesYesYes
LanguageGoogle Apps ScriptGoogle Apps ScriptGoogle Apps Script
Order BasicOrder StandardOrder Premium

Payment protection

You pay when you order, but the money is released only for accepted work.

  • Fixed priceThe package price does not change after you pay.
  • The money is reservedWhen you pay, the amount is only reserved. It is released to the service once you accept the work.
  • Checked before deliveryEvery result goes through a quality check before it reaches you, and you see it on the order page before accepting it.
  • Free revisionsAsk for changes within your brief as many times as the package allows.
  • Acceptance after 3 daysIf within 3 days of delivery you neither accept the work nor ask for changes, it is accepted automatically. If you write in the order chat after delivery, the order waits; once we answer, we may start the 3 days again and will say so in the chat.
  • Redo or a full refundIf the result does not match your brief and the revisions did not fix it, or the work takes more than twice its deadline, write in the order chat: we will redo the work or refund the payment in full.
How it works →

Questions and answers

How many emails can it send a day?

As many as Google allows your account to send from a script, which is lower for a free Gmail than for Google Workspace; Google shows the current figures on its Apps Script quotas page. The script stops at the limit and the next run continues from the first unsent row.

Can I send to a list I bought?

No. The script is for people who know you and expect your emails, such as your clients or members. Bought lists and cold mass mailing break Google's rules and can get your account blocked.

Will it add an unsubscribe link?

It can add a line asking people to reply if they do not want these emails, and skip rows you mark as unsubscribed. For newsletters with one-click unsubscribing, a mailing service suits better.

Do you get access to my Gmail?

No. You paste the code into your own sheet, and Google asks you, not us, to allow it to send email. We never log in to your account.

Did not find your answer?

Packages