Tutorials

Turn a Tracking Spreadsheet Into a Shared Web App: Checklist, Field Mapping and Permissions

A tracking sheet becomes an application when its rows live in a typed database behind a form. Here is the migration order, the column-to-field mapping, and the three audiences to separate before you invite anyone. Atoms documents the import limits and the role model this plan builds on.

Start building for free
13 min readPublished Updated
Spreadsheet migrating into a shared web app interface
On this page

Your team already has the data. It sits in a Google Sheets or Excel tracker that everyone edits, argues about, and half-trusts. A spreadsheet to web app migration is mostly a data-modelling job, and the part people underestimate is not the import. It is deciding which columns become typed fields, which rules the grid was quietly enforcing, and who is allowed to change what.

The practical version of the "apps spreadsheet" question is rarely about which product to buy. It is about what changes when the grid stops being the interface. This guide is a spreadsheet migration checklist with the field mapping and sheet permissions work attached to it, in the order that avoids rework.

Step 1: Decide what the sheet is really doing

A tracking sheet usually holds three jobs at once: it stores rows, it acts as the interface, and it enforces a permission model. Migrating makes sense when at least two of those have outgrown the grid. Storage outgrows it when rows carry relationships you keep re-typing. Interface outgrows it when people need a form that only shows the fields they own. Permission outgrows it when you need one group to submit and another to approve.

The permission side is where sheets are weakest and apps are strongest, so compare them precisely. A Drive file permission is a combination of a type (user, group, domain, or anyone) and a role from owner, organizer, fileOrganizer, writer, commenter, reader. You can create one with a request to the Drive permissions endpoint, passing the role, the type, and an email address or domain. Those permissions propagate down a folder tree, a child item can grant a more permissive role than its parent, and moving an item re-evaluates it against the new parent. My Drive files need an owner or writer to share, and an owner is required when the writersCanShare setting is off.

That model is excellent for documents and poor for application data. You cannot express "sales may edit the status column but not the price column" with a single file role. In an application, the equivalent question is answered by three separate layers, and step 6 covers them.

Step 2: Inventory the sheet before you move anything

Two failures cause most of the pain in these projects: importing into a table whose structure does not match the data, and discovering afterwards that the sheet was enforcing rules nobody wrote down.

Walk the sheet and record:

  • every column, including the ones that look like decoration;
  • the real data type behind each column, not the display format;
  • which columns are required in practice, and which are only usually filled;
  • the column that identifies a row (your candidate primary key);
  • any dropdown, checkbox, or conditional formatting rule;
  • formulas, especially ones that compute values other people copy;
  • who edits which columns, and who only reads;
  • how many rows you actually need, including archived ones.

That last one matters because imports have a ceiling. The built-in database in Atoms accepts a CSV file no larger than 10 MB, and the file's columns must match the destination table's schema. Splitting a giant tracker into current and archived tables is usually a better answer than fighting the limit.

Step 3: Map columns to fields

This is the step that decides how much validation you get for free later. One column becomes one field with a name, a data type, a default, a required flag, and a uniqueness rule. In the Atoms database view you can inspect a table's structure and see each field's name, data type, key status, requirements, constraints, and default value, and you can change the name, type, default, required status, or uniqueness of an eligible field. The database guide documents those controls, and it is worth reading before you finalise the mapping table.

A mapping table keeps the decisions visible:

Sheet column Destination field Type Rule to enforce Who may change it
Lead name lead_name text, required, unique no duplicates on import sales
Stage stage enum value must exist in the stage list sales
Owner owner_email text must match a member address manager
Expected value expected_value number zero or positive, no currency symbol manager
First contact first_contact date real date value, not text system
Notes notes long text optional sales

Three details in that table deserve attention before you touch data.

Numbers and dates are the classic casualties. When a value is written to a sheet through the API, the input option decides how it is interpreted: the RAW option inserts the input as a string, so a formula written as text stays text, while USER_ENTERED parses the input the way the sheet UI would, turning a date-like string into a date and an equals sign into a formula. When you read values back, the default render option returns formatted values and dates as serial numbers unless you ask for something else. If your tracker has ever produced a column of text that looks like dates, plan to normalise it during mapping rather than after import.

Uniqueness needs a real key. Imported rows are inserted as new records, and editing or deleting a row requires primary-key information in the database view. Pick the key before the first import, not after you find duplicates.

Required is not the same as "usually filled". Every blank cell in a required field becomes a decision you make once, at mapping time, instead of during the first week of production use.

Step 4: Move the rows with a rehearsal

Export the sheet to CSV, then rehearse the import on a development database before the production one. Atoms separates development and production environments, and its guidance is explicit that you should not rebuild or overwrite the production database on your own when something looks missing.

Before the real import, confirm four things: the file is within the size limit, the columns match the destination table, the table is writable rather than read-only, and there are no unsaved row edits pending in the table view. Read-only tables cannot receive an import at all, and pending edits can block the action.

Then import once, and treat it as one-way. Imported rows are added immediately and cannot be automatically undone, which is why the documentation suggests exporting the existing data first. A rehearsal copy is your undo.

Step 5: Rebuild the rules the grid was enforcing

Spreadsheet validation does not travel with a CSV. A file contains values, and the import checks only that the columns line up with the schema. Everything else needs to be re-declared in the new system, and the database schema is where the durable half of it belongs: types, defaults, required flags, uniqueness.

The remaining half belongs in the form. The sheet's dropdown becomes a select with the same allowed values. The "date must be in the future" rule becomes a form check that can explain itself. The column that managers edit becomes read-only for submitters. This is the part users notice, because a form that refuses bad input with a sentence is a better experience than a cell that quietly accepts a phone number where a date should be.

Decide deliberately what you are not rebuilding. Some rules existed only because a sheet has no other way to express intent. Copy the ones that protect data, drop the ones that merely warned a human.

Step 6: Split the audience before you share

In an application, access depends on the account someone signs in with, the workspace that holds the project, and their role in that workspace. A shared project link or a published app URL is a different kind of access from workspace membership, and copying a link does not add anyone to the workspace or give them an owner or editor role. Critically, someone who signs in to your published app does not become a workspace member. The access and permissions guide is the reference for checking a role when someone says they cannot open a project.

That single fact simplifies the permission design into three audiences:

Audience What they need How to give it
Builders edit the app, the schema, and the data workspace membership with an editing role
App users submit a form, read their own or public rows the published app URL and the app's own access settings
External collaborators the source sheet, not the app the sheet's existing Drive permission

Most permission arguments in sheet-based workflows come from collapsing those three into one sharing list. Keep them separate and the migration stops feeling risky.

Also decide early who can connect integrations. Connecting or disconnecting an integration may require workspace owner or authorised admin access, and disconnecting a connector stops future use without reversing changes it already made.

Step 7: Keep the sheet in the loop only where it earns its place

Sometimes the honest answer is that part of the process should stay in the grid, at least for now, whether the starting point is the Google Sheets app your team opens every morning or a workbook stored in OneDrive or a SharePoint site. An Excel to web app move that keeps a live spreadsheet on one side is a different architecture from a one-time import, so if the grid stays, be precise about what it costs.

Reading and writing sheet values programmatically is well documented. Single ranges are read and written with the values get and update methods, several ranges at once with the batch methods, and new rows can be appended after a table of data. Reads need the spreadsheet identifier and an A1-notation range, and a bare range such as A1:B2 applies to the first sheet in the file unless you name the sheet. On the Excel side, the equivalent path runs through Microsoft Graph: a workbook stored in OneDrive for Business, a SharePoint site, or a group drive is reachable by item id or path, and worksheets, ranges, tables, and charts can be read or modified. Graph sessions decide whether changes persist, and access needs the Files.Read scope for reading and Files.ReadWrite for writing. Both APIs are also narrower than a spreadsheet UI: the Excel API supports only the Office Open XML workbook format, so older .xls files are out of scope until they are converted.

What that architecture buys you is a second interface to the same cells. What it costs is a second place where validation, permissions, and failure modes live, because a write from an application still lands in a grid that other people edit by hand.

What is not supported today

Read this part out loud before you promise anything to your team.

There is no documented, one-click live connector that turns a Google Sheet or an Excel workbook into the data source of an Atoms project. The help centre's coverage check is unambiguous on this point: across 1,192 help URLs, nothing matches sheet, spreadsheet, Excel, form, or validation. What is documented is the pair of paths that actually work: import CSV data into the built-in database, or connect Supabase when the app should own its database, authentication, file storage, or backend functions.

Connector availability changes over time and can vary by account and release, so the reliable check is the connector catalogue inside the product. The documentation's own instruction is the right rule to adopt: if the capability or action you need is not shown for a connector, do not assume it is supported.

Two more limits belong in the plan. Imports cannot be automatically rolled back, so a rehearsal is mandatory rather than tidy. And there are no per-cell permissions inside a table; field-level control is a form and application concern, not a database one.

Build a web app from your spreadsheet with Atoms

Give Atoms one sample CSV, a column-to-field map, the primary key and the actions each role can take. Ask for a persistent app with forms and permission rules, then compare the imported records with the source. A polished table is only the first step: a saved change must survive reload and an unauthorized write must be refused by the server.

The following examples start from separate, eight-row synthetic CSV files. Their brands and records are fictional. They demonstrate one-time migration workflows; they do not imply a live Google Sheets or Excel connection.

Inventory tracker: Field Supply Stockroom

Turn material rows into a searchable stockroom with low-stock flags and a validated stock-editing form. Coordinators change quantities; specifiers have a read-only view.

Inventory column App field and rule
material_id Unique stable record ID
quantity and reorder_level Non-negative whole numbers; flag stock below the reorder level
unit_cost Non-negative decimal amount
family Filterable material category

Field Supply Stockroom synthetic demo workflow

Try the live Field Supply Stockroom demo · Open this example in Atoms

Try this journey: compare the import receipt and eight record IDs with the source CSV, change one quantity, then reload. Sign in as the viewer and confirm a write is denied. Reloading must not import the eight rows again.

Work-order tracker: Crew Board Dispatch

Turn a maintenance tracker into a dispatch queue. A coordinator assigns work and sets priority; a technician updates the status of assigned jobs.

Dispatch column App field and rule
work_order_id Unique stable work-order ID
priority and status Controlled choices used by filters and forms
assigned_to Technician assignment; blank means unassigned
due_date Date, independent of display formatting

Crew Board Dispatch synthetic demo workflow

Try the live Crew Board Dispatch demo · Open this example in Atoms

Try this journey: filter urgent unassigned work, assign a job and save a technician's update. Check the change after reload and verify that the technician cannot update a job assigned to someone else.

Applicant tracker: Fellowship Review Desk

Turn applicant rows into a review workflow with assigned reviewers, score validation and a coordinator shortlist. Keep record IDs stable so a score change updates the intended application.

Application column App field and rule
applicant_id Unique stable application ID
requested_funding Non-negative amount
reviewer Assigned reviewer identity
score Optional until reviewed; whole number from 0 to 100

Fellowship Review Desk synthetic demo workflow

Try the live Fellowship Review Desk demo · Open this example in Atoms

Try this journey: open an assigned application, reject an out-of-range score, then save a valid score and reload. The coordinator must see the updated record; a different reviewer must not gain access through a direct link.

Copy this spreadsheet migration brief

Attach a small synthetic CSV before moving live records. Replace the bracketed fields with your own map and permissions.

text
Build a web app from the attached [filename.csv]. The workflow is [task].
Use [column] as the stable primary key. Map [columns] to [typed fields]
with [required, unique, range and choice rules].
Import the source exactly once into a persistent database. Show an import
receipt with the filename, source row count, imported row count and field
map. Preserve every ID; reject duplicates rather than silently inserting.
[Role A] can [actions]. [Role B] can [actions or assigned rows only].
Enforce those rules on the server, including direct record URLs, writes
and exports. Provide search, filters and validated create/edit forms.
Verify one saved edit after reload and a new login. Check a denied write
from the restricted role. Provide the original CSV and an authorized
current-data export. Report checks that could not be completed.

Build an app from your spreadsheet with Atoms: open the builder section, attach a sample and paste your adapted brief. If external clients will use the app, add the client portal ownership and two-account checklist before sharing it.

Conclusion

The migration succeeds or fails at the mapping table, not at the import button. Write down every column and the rule it must satisfy, choose the primary key, rehearse the CSV import on a development database, then separate builders, app users, and external collaborators before you send a single link. If you want to start from a working base instead of a blank page, describe your tracker to Atoms through the app builder use case and let it build the first version, then bring your rows across through the database import.

A little more clarity

Frequently asked questions

01Q1: Can Atoms read my Google Sheet directly?

There is no documented live connector for that today, and the connector catalogue inside the product is the authoritative list because availability varies by account and release. The supported route is to export your sheet to CSV and import it into the built-in database, or to connect Supabase when the application should own its database. If a connector you need is not shown, do not assume it is supported.

Dropdown rules and conditional formatting do not travel with a CSV. Rebuild the ones that protect data as database constraints (types, required, unique) and form checks, and decide explicitly which ones you are dropping. Formulas need individual decisions too, because a computed column either becomes application logic or stays a manual field.

03Q3: Is there a size limit for the import?

Yes. A CSV import must be no larger than 10 MB, its columns must match the destination table's schema, and the destination table must be writable. Imported rows are added immediately and cannot be automatically undone, so export your existing data first and rehearse on a development environment.

04Q4: Who counts as a user of the app?

Anyone who opens your published app URL and signs in to the app. They do not become workspace members, and they do not gain an owner or editor role in the workspace. Workspace membership is for the people who build and maintain the project; the app's own access settings govern what its users can see and do.

05Q5: How do I keep the sheet and the app in sync afterwards?

Either move the workflow fully into the app, or accept a second interface and pay for it deliberately. Reading and appending sheet values through an API is documented, but every write still lands in a grid other people can edit by hand, and each side keeps its own validation and permissions. Most teams get more value from a one-time import plus a clear rule that the app is now the record of truth.

06Q6: Which column should become the primary key?

Pick the column that will still identify the row after three months of real use: an email, an order reference, or a generated identifier you add during mapping. Editing and deleting records require primary-key information, and duplicate rows imported without a key are far harder to untangle than a slightly longer mapping exercise.

Share this article
Made with Atoms

Your next idea starts here.

Turn what you learned into a working app or website.

Start building for free