migration

Google Forms to Google Sheets: what the link does not carry over

October 6, 2026 ・ Halict Editorial

Connecting Google Forms to Google Sheets is the easiest decision in the whole workflow. Two clicks, and every submission lands as a row. The hard part starts about three weeks later, when someone asks who is handling the request that came in on Tuesday, whether a reply was sent, and why the row that was definitely there yesterday now sits in a different order. None of that is a fault in the link. The link does exactly one job, and the jobs it does not do are the ones teams end up doing with their hands.

This is a map of the boundary. What the connection carries, what it never touches, what breaks it, and the point at which adding another column stops paying for itself.

The connection runs one way

A form with a spreadsheet destination pushes each submission into a sheet as a new row. It is a delivery, not a sync. The form keeps its own copy of every response, and the sheet receives a rendering of that copy at the moment it arrives.

Two facts make the direction concrete. The Apps Script Sheet class has a method that returns the URL of the form that sends responses to that sheet, and returns null when no form is attached. The association is stored on the sheet and points back at one form, not the other way around. On the automation side, the installable form submit trigger comes in two versions, one for Google Forms itself and one for Sheets when the form submits to a spreadsheet. Google documents them separately because they fire on different objects, and a script bound to the sheet only ever sees the arriving row.

The practical consequence is the one most teams discover by accident. Typing into a delivered row changes the sheet. It does not change the response held in the form. Anyone who opens the form's own response view later sees the original wording, and two versions of the same answer now exist in the same account. Neither one is marked as the correct one.

What crosses over, and what stays behind

The row carries the answers and the time of submission. What it does not carry is everything that turns an answer into a piece of work.

What the team needs Where it lives after the link is made
The answers as submitted In the row, and in the form's own response store
Time of submission In the row, as the first column
Who is handling this one Nowhere. A column has to be added and filled by hand
Whether it is open, waiting, or closed Nowhere. Same
The reply that was sent In someone's sent mail, not in the row
Notes from a phone call about it Nowhere, unless a comment or a column is invented for it
An uploaded file In Drive, as a link in the cell, owned by the form owner
A record of who changed what In the spreadsheet's version history, at file level

The gap is not a missing feature. A spreadsheet is a grid of values, and the things above are states that belong to a case rather than values that belong to a cell. Teams close the gap with extra columns, and the extra columns work until two people fill them at once.

It is worth knowing how firm this boundary is at the platform level. The Google Forms API exposes responses through two methods, get and list. There is no method to update or annotate a response. That is a deliberate shape: a response is a record of what someone said, and the platform treats it as immutable. Any status, owner, or reply belongs to a different system by design. The sheet becomes that different system by default, not by suitability.

The columns that get added by hand

The pattern is always the same. Column A holds the timestamp. Columns B through H hold the answers. Then, off to the right, a team adds Owner, Status, Replied, and Notes.

Three problems arrive with those columns, in order.

Order

Rows arrive in submission order, but people want to work in priority order. Sorting the sheet moves the answers and the hand-filled columns together, which is fine. Filtering is fine as well. What is not fine is sorting while a new response is arriving, because the appended row lands at the bottom of the underlying data, not at the bottom of the view someone is looking at.

Two hands on one cell

The hand-filled columns are the record of who is doing what. They are also the cells most likely to be edited by two people within the same minute. A spreadsheet resolves that by letting the last write stand. Nothing warns either person.

Access

Handing the work to a colleague means handing them the sheet, and a sheet is shared as a whole file. There is no way to give someone the four rows they are responsible for and nothing else. Protected ranges limit what a person can edit, not what a person can read, so a spreadsheet that collects salary expectations, medical notes, or customer complaints is shared at the granularity of the entire intake. Splitting the file by month or by team is the usual answer, and it works until a case needs to move between two of the copies. The alternative, keeping one file and granting view only access to most of the team, brings back the original problem: the people who cannot edit also cannot record that they handled anything.

The reply

The reply is the part of the process that never fits. It is written in Gmail, so it lives in the sender's mailbox. The row gets a checkbox saying a reply went out, with no way to see what it said. When the person who sent it is away, the next person starts from scratch. The column can record that a reply happened, but not the reply itself, and that is the gap that costs the most time.

Why the rows stop arriving

When a sheet stops receiving responses, the cause is usually one of a short list, and none of them announce themselves.

The destination was changed or removed. A form points at one destination at a time. Pointing it at a new sheet does not move the old rows, and the old sheet simply stops growing while still looking like the live one.

The header row was edited. The link writes into the sheet by position. Renaming a header is cosmetic, but inserting or deleting a column inside the answer range shifts what lands where, and the damage shows up only in rows submitted after the change.

The sheet was copied. A copy of a spreadsheet is not attached to the form. It looks identical and will never update again. Checking is quick from the script side, since the method that returns the attached form URL returns null on the copy.

A question was added. New questions append a new column. Anything built to the right of the answers, including the hand-filled status columns, is now sitting where the form wants to write.

The habit that prevents most of this is unglamorous: keep everything the team adds on a separate sheet, keyed on the timestamp or an ID, and treat the delivered sheet as read only. It costs a lookup formula and saves the afternoon spent working out which rows lost their status.

What a script can patch, and what it cannot

The next step after the manual columns is usually Apps Script, and it does genuinely close part of the gap. A form submit trigger can stamp a default owner, write a row into a tracking sheet, and send an acknowledgement. The limits on that are published, and they matter before the build rather than after.

Limit Consumer account Google Workspace account
Email recipients per day 100 1,500
Email recipients per message 50 50
Total trigger runtime per day 90 minutes 6 hours
Script runtime per execution 6 minutes 6 minutes
Triggers per user, per script 20 20

Those figures come from the Apps Script quota documentation, and Google notes that all of them are subject to change without notice. For an intake that receives a few dozen submissions a day and sends one acknowledgement each, the email allowance on a Workspace account is comfortable. For a recruitment round that sends a decision to several hundred people in an afternoon, the daily recipient count is the ceiling that gets hit first, and the failure mode is a script that stops partway with some people written to and some not.

The deeper limit is not a quota. A script can write a status into a sheet, but the response it refers to remains unchangeable through the API, the reply still leaves from a personal mailbox, and the audit trail is still the spreadsheet's file history. The script makes the workaround faster without changing its shape. Teams that keep going down this road end up maintaining a small application whose data model is a grid, and the person who wrote it becomes the only one who can change it.

Reading the sheet from the other side

There is a reason to keep the sheet even after the process moves elsewhere: it is the cleanest handover point to everything else. A Google spreadsheet exports as .xlsx, as OpenDocument, as PDF, and as zipped HTML. It also exports as CSV and TSV, and those two are worth reading carefully, because Google documents them as first sheet only. A workbook with a responses tab and an analysis tab exports one of them to CSV and silently drops the other.

For anything read by a program, the Sheets API is the steadier route than a scheduled download. Its published limits are 300 read requests and 300 write requests per minute per project, with 60 per minute per user per project, and a single request that runs longer than 180 seconds returns a timeout. Within those per minute limits there is no daily cap. Standard use carries no additional cost today, with charges for exceeding the quota limits planned later in 2026.

So the sheet is a good destination for reporting and a poor one for casework. That distinction is the useful one. Analysis wants a grid. A case wants an owner, a state, and a thread.

What to change first

Stop widening the responses sheet. Move the owner, the status, and the notes onto their own sheet keyed on the timestamp, and leave the delivered rows untouched, which alone removes most of the broken link reports. If the reply is the part that keeps going missing, the answer is not another column but a tool where the response, its state, and the message sent back sit on one screen. That is the comparison worth making next, and the features and the working demo show what that looks like in practice. Pricing for Halict and tools of that shape usually turns on how many people touch the queue rather than how many responses arrive, which is worth checking against the volumes before any migration.

Q1. Does editing a cell in the responses sheet change the answer in Google Forms?

No. The sheet receives a copy of the submission, so an edit changes the sheet only. The form keeps the answer as it was submitted, and the Forms API offers no method to update a stored response. After an edit, two different versions of that answer exist and nothing marks which is authoritative.

Q2. Can one Google Form send responses to two spreadsheets?

A form points at one response destination at a time. Changing the destination starts a new sheet rather than mirroring into both, and the previous sheet keeps its old rows while quietly ceasing to grow. To get the data into a second place, copy or query from the first sheet, or read it through the Sheets API.

Q3. Why does the status column end up next to the wrong answer?

Almost always because a question was added to the form, or a column was inserted or deleted inside the answer range. The link writes by position, so anything to the right of the answers can be displaced. Keeping hand-entered columns on a separate sheet, joined on the timestamp, avoids the problem entirely.

Q4. How do you check whether a sheet is still attached to its form?

From Apps Script, the Sheet class has a method that returns the URL of the form feeding that sheet and returns null when there is none. Running it on a suspect tab settles the question in seconds, which is faster than submitting a test response and waiting to see whether it lands.

Q5. Is Apps Script enough to send replies from the responses sheet?

It works for modest volumes. The published quotas allow 100 email recipients a day on a consumer account and 1,500 on a Google Workspace account, with 50 recipients per message and 90 minutes of total trigger runtime a day on consumer accounts. A large decision round hits the daily recipient limit, and the sent messages still live in one person's mailbox rather than against the response.

All guides

Google Forms to Google Sheets: what the link does not carry over | Halict