Highlights
  • The loop isn't getting the answer. It's the ten minutes after: splitting text to columns, deleting a row of dashes, and retyping numbers the sheet decided were words.
  • A pipe table is a rendering, not a format. The clipboard splits on tabs, so ask for tabs and the whole cleanup step disappears.
  • The prompt build swaps the pretty table for tab separated values with bare numbers and ISO dates, and the rows land in the right cells on the first paste.
  • The script build puts a deterministic parser between the model and the sheet: match columns by name, coerce every cell to a declared type, and hold the rows that fail instead of writing a string where a number goes.
  • The schedule build runs the whole thing on a timer and appends straight to the sheet, which is where you stop pasting at all and automate the spreadsheet work end to end.

Welcome to The Loop. Every Wednesday we take one real, repetitive workflow that someone does by hand and unwind it into something you can run. This week it's the small humiliation that happens between having the answer and being able to use it: the table that looked perfect in the chat window and arrived in your spreadsheet as a single column of punctuation.

Here's the idea worth carrying out of this one. The boring task you repeat is a specification in disguise, and the repeated task here is the cleanup. Every time you split text to columns and delete the dashes and strip the dollar signs, you are performing the same specification by hand: six columns, these names, this one is a number, this one is a date. Write that sentence down once and you never perform it again. Describing replaces doing.

So let's sit next to somebody doing the cleanup, price what it actually costs, and then build the version where the rows arrive correct.

The Loop, in Full

Before you fix anything, you have to see the loop clearly. Picture Priya, who handles procurement for a fifty-person hardware company. Twice a week a folder of supplier quote emails lands on her, and she does the sensible modern thing: she pastes them into a chat tool and asks for one table with vendor, quote date, line item, unit price, quantity and lead time. The answer comes back in about eight seconds and it is correct. It is a beautiful table. On screen.

Then she copies it into the sheet, and the eight seconds buys her twelve minutes:

  1. Paste. Every row lands in column A as one string, pipes and all, forty rows deep. Row two of the sheet is a line of dashes, which is not data and never was.
  2. Split text to columns on the pipe character. Now there is an empty column A, because the table had a leading pipe, and an empty column H, because it had a trailing one. Delete both. Delete the dashes row.
  3. Trim. Every cell arrived with a space on each side, so vendor names don't match the ones already in the sheet and the lookup she built last month returns nothing.
  4. Fix the types. $1,240.00 is text. 12% is text. Sep 3 is text, and next month it will sort before April. She retypes the price column, or runs a find and replace on the dollar signs and commas and hopes nothing else contained a comma.
  5. Find the one row that shifted. A line item read bracket, powder coated, the model helpfully wrapped it in quotes on one row and not on another, and now that row's lead time is sitting under quantity. Nothing flagged it. She caught it because the number looked odd.
  6. Do it again on Thursday, because the next answer comes back with the columns in a different order and a "Notes" column she didn't ask for.

Not one of those twelve minutes needed her judgment. She made every real decision before she started: which six fields, in which order, and what each one means. Everything after that was transcription in a format that fights her. That's the tell for an automatable loop, and it's the same tell as the week we looked at how to move records out of a spreadsheet without retyping them: the thinking happened once, and the hands have been repeating it ever since.

The Manual Tax

The real cost of a loop is never just the minutes on the clock. It's the minutes, plus the mistakes, plus the time the work sits waiting. This loop is unusual in that the minutes are the cheapest part by a wide margin, and the expensive part leaves no trace.

The scale is documented. In a May 2026 survey of 1,003 US operations professionals, DOSS found copy-paste issues named as one of the three most common sources of spreadsheet error, cited by 45% of respondents, behind manual data entry mistakes at 59% and formula errors at 46%. The same survey puts time spent fixing spreadsheet mistakes at 3.6 hours per week per person, which is more than 22 working days a year, and the average cost of a single significant error at $4,315.

Then add the two costs hiding behind the minutes:

  • Errors. A number stored as text is the perfect failure: visually identical to a real number, and invisible to SUM. The total comes out low, it comes out looking like a total, and nobody goes looking for the four rows that were skipped. The shifted row is worse still, because every value in it is real and in the wrong column, so a lead time of 14 is read as a quantity of 14 and ordered.
  • Latency. The answer existed eight seconds after Priya asked. It became usable twelve minutes later, and only because she was sitting there. Anything that has to be reformatted by a specific person before it can be read is a queue with one server, and it stops dead the week that person is out.

The table was never broken. It was rendered. You copied a picture of a table and asked a spreadsheet to read it as data, and it did exactly what you told it.

So the goal isn't a faster cleanup, and it definitely isn't a better macro for stripping dollar signs. The goal is to stop generating the mess: ask for a shape a spreadsheet already understands, and check the values on the way in rather than eyeballing them afterwards. Done once, that removes an entire category of work from the week, which is the whole reason to hand the retyping off entirely instead of getting better at it.

Unwinding the Loop

Automating starts with description, not code. Describe the loop precisely enough that a machine could follow it without you in the room, and most of the work is done before a line is written. For this loop the description has a nice property: it is almost entirely a description of the columns, and you already know them by heart.

Here's the clean handoff captured as a spec. The interesting parts are the decisions, not the steps:

Part of the loop What it is for this workflow
Trigger A batch of source documents that needs to become rows: quote emails, a pasted report, an answer from a chat tool that you intend to sort or sum.
Input The source text, plus a column contract: the exact column names, in order, and what each one is. Not a request for "a table."
Decision: what separates the fields? A tab. Nothing in a vendor name, a line item or a note contains a tab, so nothing needs quoting and no row can shift. Commas fail this test, pipes are not a delimiter at all.
Decision: what type is each column? Declared up front and enforced on arrival. Numbers bare, no currency symbol and no thousands separator. Dates as YYYY-MM-DD. Percentages as decimals. Empty means empty, not "N/A."
Decision: what happens when a value doesn't fit? Hold the row and say which field failed and what arrived. Never coerce a bad value into the cell and never write a blank in its place.
Output Rows in the right cells with the right types, appended below the existing data, with the held rows listed separately for a human to look at.
Success signal You sum the price column and get a number on the first try, with no split-text-to-columns anywhere in the process.

That fourth row is the one people skip, and it's the one that converts a formatting annoyance into a reliable pipe. Everything after this table is choosing how hands-off you want to be. If you'd rather answer questions than fill in a spec, that's exactly how BYOBot turns a task into a spec, one question at a time, and the two type rows are where the useful argument happens.

Try It Now

Tell BYOBot which table you keep rebuilding by hand and it'll design the clean version: the column contract, the parser, and the run that appends straight to your sheet.

Help me get AI tables into my spreadsheet without reformatting…

The Build: One Loop, Three Ways to Run It

The same described loop becomes three builds depending on how much you want running on its own. Start at the top and move down only when you're ready. This loop is unusually generous at the first step: the prompt build alone removes most of the pain, costs nothing, and takes about a minute to adopt.

The Prompt

The mistake is asking for a nicer table. You want the opposite of a table. A pipe table is presentation, defined for humans reading a document, and the GitHub Flavored Markdown spec that standardized it is explicit that the alignment row and the pipes are there to be rendered. Your spreadsheet renders nothing. It splits on tabs. So ask for tabs, and add the type rules in the same breath.

Output the result as tab-separated values. Not a markdown table.

Columns, in this exact order, with these exact header names:
vendor  quote_date  line_item  unit_price  qty  lead_time_days

Rules:
- One header row, then one row per record. No pipes. No separator
  row of dashes. No leading or trailing delimiter. No bold, no
  code fence, no preamble, no closing summary.
- Separate every field with a single TAB character. Never a comma,
  never multiple spaces.
- Numbers bare: 1240.00, not $1,240.00. 0.12, not 12%. No currency
  symbols, no thousands separators, no units inside the cell.
- Dates as YYYY-MM-DD. If the source gives a partial date, leave
  the field empty rather than guessing the year.
- Empty means empty. Do not write N/A, none, unknown or a dash.
- Text fields: strip every tab and line break, replace with a
  single space, so no record ever spans two lines.
- Quote nothing. If a value would need quoting, it is wrong.

If a required value is missing from the source, still output the
row, leave that field empty, and add one final line after the data
that starts with HELD: listing the row number and the field name.

Paste the result straight into the sheet and it lands in the right cells, because the clipboard and the spreadsheet have agreed on tabs since long before any of these tools existed. Two details earn their place. Asking for bare numbers means you apply currency as cell formatting afterwards, which is a display choice that belongs to the sheet rather than to the data. And the HELD: line is a small thing that changes the character of the output: instead of a confident table with three quietly invented dates in it, you get a table plus a list of what the source didn't actually say. That habit is worth carrying into everything else you automate around a spreadsheet.

The Script

Here is the honest part. The reformatting itself needs no intelligence whatsoever, and putting a model in charge of it is the wrong instinct. Reading forty quote emails and deciding what the line item is: that's a judgment call, and a model is good at it. Turning $1,240.00 into 1240 is arithmetic with a regular expression, and a model will do it correctly almost every time, which is a much worse property than doing it correctly every time. So the model produces rows and a plain deterministic parser decides whether they are allowed into the sheet.

The parser is the build, and it's smaller than it sounds. Python ships a csv module that handles tab-delimited input with one argument and will not be surprised by anything, and the write side is a single call to the Google Sheets API values.append endpoint with RAW input so nothing gets re-guessed on the way in.

# pseudo-shape of the normalizer BYOBot generates for you
SCHEMA = {
    "vendor":         {"type": "text",   "required": True},
    "quote_date":     {"type": "date",   "required": True},
    "line_item":      {"type": "text",   "required": True},
    "unit_price":     {"type": "number", "required": True,  "min": 0},
    "qty":            {"type": "int",    "required": True,  "min": 1},
    "lead_time_days": {"type": "int",    "required": False, "max": 365},
}

# 1. ACCEPT whatever shape arrived: TSV, CSV, or a pipe table
rows = parse_table(raw)        # strips pipes, drops the dashes rule,
                               # trims cells, ignores empty edge columns

# 2. MATCH columns by header NAME, never by position.
#    The order changes between runs. The names do not.
cols, missing = match_headers(rows[0], SCHEMA)
if missing:
    return hold_all(f"missing columns: {missing}")

out, held = [], []
for n, r in enumerate(rows[1:], start=2):
    rec, bad = {}, []

    # 3. COERCE each cell to its declared type: "$1,240.00" -> 1240.0
    for col, rule in SCHEMA.items():
        v = coerce(r[cols[col]], rule)
        bad.append(col) if v is FAIL else rec.update({col: v})

    # 4. REFUSE the row rather than writing a string where a number goes
    held.append((n, bad)) if bad else out.append(rec)

# 5. WRITE once, values not formulas, and report what was held back
append_rows(SHEET_ID, out, value_input_option="RAW")
report(written=len(out), held=held)

Step two is the one that pays for the whole script. Matching by header name rather than by column position means Thursday's answer can come back with the columns reordered, or with an extra column you didn't ask for, and nothing breaks: the parser takes the six it knows and ignores the rest. Step four is the discipline: a row that can't be made to fit is a row you look at, not a row you round off. You don't write this from scratch. BYOBot generates the full version against your actual columns, including the credentials and the held-row report, and the same skeleton covers every other table you feed that sheet, which is where it starts making sense to write straight into your sheets on a schedule.

The Schedule

Putting the script on a timer is the small part: a cron entry, a GitHub Actions workflow on the free tier, or a scheduled run inside BYOBot. What changes at this step is that the clipboard leaves the loop completely, and with it the requirement that Priya be at her desk. The quotes land, the run picks them up, the rows append, and the held rows arrive as a short message naming the three that need a human. The one thing to decide before you schedule it is what happens on a rerun, because appending the same batch twice is the most common way a clean pipe gets dirty: key each row on something stable, vendor plus quote date plus line item, and skip what's already there. Deciding that before you build rather than after is the same move as writing the workflow spec first, and it saves the same afternoon.

Here's how the three builds stack up, so you can pick your stopping point:

Build What runs it Setup Runs unattended?
The prompt You, pasting tab separated output into the sheet A minute No
The script A parser that types every field and appends by API An hour, once On demand
The schedule The same run on a timer, with dedupe and a held-row report A few extra minutes Yes

Steal This Build

Five lines, and they're the whole build. Copy them, swap the column names for your own, hand them to BYOBot or write them yourself this afternoon.

  • Trigger: a batch of source material that needs to become rows, on a schedule or on arrival.
  • Request: tab separated values with named columns, bare numbers and ISO dates, never a rendered table.
  • Match: columns by header name, so a reordered or extended output changes nothing.
  • Coerce: every cell to its declared type, and hold the row when a value doesn't fit rather than writing it anyway.
  • Append: once, as raw values, keyed so a rerun can't duplicate what's already there, with the held rows reported by name.

The loop you just watched is supplier quotes, but the shape is universal. Anything that arrives as text and has to become rows wants the same three moves: ask for a machine format instead of a readable one, declare what each field is before you accept it, and refuse the values that don't fit instead of tidying them. Bank exports, survey results, a report another team sends as a formatted email, the output of any tool that renders instead of exporting: same loop, same fix, and it only has to be described once. That's what it looks like to automate a recurring spreadsheet job properly rather than getting quicker at the cleanup.

Build Your Version

Tell BYOBot about a loop in your week

Describe the task you keep doing by hand and BYOBot will design the full playbook: the prompt, the script, and the schedule that runs it for you.

Frequently Asked Questions

  • Because what you copied was never a table. The chat tool rendered text into something that looks like a grid on screen, and the clipboard carried the text, not the grid. A spreadsheet splits pasted text on tab characters and line breaks, and a pipe table contains neither between its columns, so every line arrives as one long string in one cell. The fix is not a better paste. It's asking for a format the clipboard already knows how to split, which means tab separated values. Tabs survive the copy, land in separate cells, and need no cleanup step at all. The same reframe applies anywhere you move data into Excel on a schedule: request the machine format, not the readable one.
  • Because the cell contains characters that aren't part of a number. A dollar sign, a thousands separator, a percent sign, a trailing unit like kg or days, a non-breaking space the model emitted instead of a regular one: any one of them makes the spreadsheet store the value as a string. It looks correct, right-aligns wrong, and then SUM quietly skips it, so your total is low and nothing warns you. Ask for bare numbers in the output and apply currency or percent as cell formatting afterwards. Formatting is a display choice and belongs to the sheet. The value belongs to the data.
  • CSV is a real improvement over a pipe table, but tab separated values is better for anything you intend to paste. The reason is the comma. Business text is full of commas, so a CSV field containing one has to be quoted, and the moment quoting is involved you need every tool in the chain to agree on how quotes and escaped quotes work. Tabs don't appear inside vendor names, line items or notes, so nothing has to be quoted and nothing can shift a row one column to the right. Save CSV for files you write to disk and hand to a parser that follows the spec. Use tabs for the clipboard.
  • Yes, and that's the version worth building once the same table shows up more than a few times a month. A short script calls the spreadsheet API and appends rows itself, which removes the clipboard from the loop entirely and lets you validate types before anything is written rather than after. The important design choice is where the intelligence sits. Let a model produce the rows if a model is what reads the source material, then hand those rows to a plain deterministic parser that checks every field against a declared type and refuses the ones that fail. No AI at parse time means the same input gives the same output every run, which is the quiet reason this is a good first job to hand off to an agent.
BYOBot Autopilot
BYOBot Autopilot
Automated AI publishing system · editorial rules by Luke Grace LinkedIn →

This article has been published in an automated fashion with fully AI-written copy. These articles are meant to curate AI news from around the globe and bring a fresh perspective to using AI tools to accomplish big things. No person reviewed this specific piece before it went live, so check anything that matters against the sources linked above. Luke Grace sets the rules the system writes to. He's an algorithms and natural language expert with over 13 years experience and the creator behind BYOBot, the Build Your Own Bot platform that helps anyone build a multi-tasking agent to take over their repetitive tasks. For consulting help or more advanced AI workflow orchestration, you can reach Luke on LinkedIn.