Articles · App ExamplesUpdated September 2026

You add CSV export to an app in three steps: build the text, write a file, share it.

To add CSV export to an app, join your rows into comma separated text, write that text to a file in the app's own storage, then hand the file to the operating system share sheet. For a list the screen already holds, that is an afternoon and no server. Going the other way, out of a spreadsheet and into software, is harder, and is covered in Excel and app data.

The honest limit belongs at the top. A phone app cannot write into a Downloads folder the way a desktop program can. It writes inside its own sandbox, the share sheet passes the file to whatever the person taps, and at best you learn which app that was. If an export has to arrive somewhere specific, or has to be provable later, that job belongs on a server.

See how a value gets quoted

The short version

Making the file is a join. Deciding what goes in it is the work.

A CSV is a text file with commas in it. Producing one needs a header line, a loop and a join. The difficulty is all in the values: a comma inside a street address, a line break inside a note, a phone number that loses its leading zero, a column that should never have left the building.

So treat an export as two decisions. What the file contains, which is a privacy question with an audit trail attached. And how each value is written, which is a correctness question with a published answer.

The three steps, and where the file actually goes

Step one is the text. Put the column names in the first row, run every value through one escaping function, join each row with commas and the rows with line breaks. Step two is the file. Write that string into the app's own storage under a name carrying the date, like invoices-2026-10-01.csv, because the filename is the only label the person ever sees. Step three is the hand-off, and on a phone that means the share sheet.

That third step is where mobile differs from the web. A browser downloads a file and the system files it away. A phone app writes inside a sandbox, then asks the system to pass the file to another app: Files, Mail, Drive, a messaging app. Sharing a local file by its URI works on iOS and Android, but not on the web, where the file has to be hosted first. None of that is specific to exports, so build the add share sheet plumbing once and point the export at it.

Pick the directory deliberately. A cache directory suits a file about to be sent onward, because the system may reclaim it later. A documents directory keeps the file until you delete it, and quietly fills a phone with copies of the same table. Either way you may learn which app was chosen, and never whether the file was kept, mailed on or deleted that evening.

Writing values so a spreadsheet opens them correctly

The format has a published specification and it is short. RFC 4180 states that each record sits on a separate line delimited by a line break, that an optional header line may appear first with the same format as normal record lines, that fields containing line breaks, double quotes and commas should be enclosed in double quotes, and that a double quote appearing inside a quoted field must be escaped by preceding it with another double quote. It also registers text/csv as the media type.

In code that is one small function, and every value should go through it. Deciding case by case which values look risky is how a customer named Smith, Jones and Partners shifts every column after it by one, and nobody notices for a month.

What the spreadsheet does next is a separate problem your file cannot control, because a CSV carries no types. Leading zeros on phone numbers and postal codes vanish when a column is read as a number. Long identifiers become scientific notation. Dates are read by the reader's locale, so one file can mean two different days in two offices. Write dates year first in the ISO 8601 style, and write UTF-8. A byte order mark makes accented names survive a double click in Excel on Windows, and shows up as stray characters in some other parsers, so decide it by where the file is going. One last trap: where the comma is the decimal separator, spreadsheets commonly expect a semicolon between fields.

RFC 4180, common format and MIME type for CSV files

Try it

What one exported row actually looks like

Put something awkward in a value and watch the escaping. Commas, quotes and line breaks get wrapped. A leading equals sign gets defused.

The first two lines

name,note,amount
"Fry, Jane ""JJ""","Left at side door
Ring twice","'=1+1"

2 wrapped, 1 defused

A value holding a comma, a double quote or a line break is wrapped, and any inner quote is doubled. A value starting with =, +, - or @ gets a leading apostrophe.

How big an export can get before it needs a server

When you export data from an app on the phone, the whole file exists as a string in memory, then again as bytes on disk. For the list on the current screen that is nothing. For every record the account has ever held, it is a crash on an old handset that you never see, because your test device is new. No platform publishes a row limit worth quoting, so measure the string your own data produces before you offer an export everything button.

The app also has to hold the data before it can export it. Anything that pages through results holds a screen or two at a time, so exporting the lot means downloading the lot first or asking the server to assemble the file. Which of those is cheap depends on how the rows are stored and indexed, which makes it a mobile app database design question. A server that streams a query into a file has no size ceiling.

For a first version, let people export what they are already looking at, with the filters they already applied, instead of one button meaning everything. Less code, a smaller and more useful file, and how much is too much becomes a choice the person already made.

An export is a data protection event

The moment somebody exports, a controlled dataset becomes an ordinary file on a device you do not manage. Nothing about the button says so, which is why the record matters. Log who exported, when, which dataset, the filter that was applied, which columns were included, how many rows came out, and the role that person held at that moment. Log the app version too, because columns change.

Two rules about the log itself. Keep it on the server, not the device, so the exporter cannot edit it. And record the query and the counts rather than the rows, because a log holding the exported data is a second copy of the same problem. Under the EU breach notification rules a controller is asked to describe the categories and approximate number of records concerned, without undue delay and where feasible within 72 hours. Whether those rules cover you is a question for your own legal advice. Either way the log is what lets you answer with a number instead of a guess.

There is a second problem inside the file. OWASP calls it CSV injection, or formula injection, and describes it as what happens when untrusted input is embedded in a CSV file. It lists equals, plus, minus, at sign, tab, carriage return and line feed as leading characters that can make a value run as a formula. Its mitigations are to wrap each cell field in double quotes or prepend each one with a single quote, and it is candid that both can fail in Excel after a save and reopen. The cheapest defence is to refuse those leading characters at the point of entry.

Last, the export button is a permission and not a screen. Anyone who can see one record can now carry ten thousand out in a single file, which changes what read access means. Settle who may export before you build the button, and enforce it where the rows are assembled.

OWASP, CSV injection

How the file can leave the app

Route outWorks with no signalYou know where it wentSuits very large exportsEffort
Share sheet from the appYesthe app chosen, at bestNoan afternoon
Save to Files or DownloadsYesNoNoan afternoon
Email the file from the deviceNothe address, yesNoa day
Your server builds it, app opens a linkNoYesYesa backend job
Scheduled export to a shared driveNoYesYesa backend job plus credentials

Putting export into an app you are building

Export is rarely in the first version and rarely optional by the third. The request arrives from one person who wants the numbers in a spreadsheet, and it is worth asking what they do with them. Half the time the answer is a monthly total the app could show on a screen. The other half, they are feeding another system, which tells you which columns matter.

Newly is an AI app builder. You describe the app in plain English and it writes a real React Native and Expo project you own, runs it on a cloud iPhone or Android simulator while it builds, and ships it to TestFlight and to Google Play internal testing. It costs $25 a month and there is no free plan. It does not ship a backend of its own, so whether the file is assembled on the phone or on a server stays your decision, and the code leaves as a ZIP or through two way GitHub sync.

Write the escaping function first and test it with four values: one holding a comma, one holding a double quote, one holding a line break, and one starting with an equals sign. If those four survive the round trip into a spreadsheet and back, the rest is plumbing.

Questions people ask about CSV export

Build the text, write the file, share it. Put the column names in the first line, run every value through one escaping function, join each row with commas and the rows with line breaks. Write the string to a file under a name carrying the date, then pass that file to the share sheet. For a list already on screen, the whole feature is an afternoon.

Describe the report people keep asking you for

Name the columns, name who is allowed to see them, then build the export around those two answers instead of around a button.

Start building