CSV or Excel for Import and Export? A Practical Guide for Business Applications

Almost every business application needs to import and export data, and the format question comes up every time. When CSV is the better choice, when XLSX is, the problems Excel causes with CSV files in Indonesia, measurements on 100,000 rows, and how to build imports that do not break on real user files.

Published 9 min read
Comma-separated numbers printed on white paper

Sooner or later every business application gets the same request: let users download this data, and let them upload that data back in. The next question is the format, and the two candidates are always CSV and Excel. Both work, and both cause real problems when used in the wrong place. A CSV export that opens as a single column in Excel, a phone number that loses its leading zero, a NIK that turns into 3.20123E+15, or an export that exhausts the server memory are all common, and all avoidable. The right choice depends mostly on who or what will read the file.

Three Formats, Not Two

When people say Excel they can mean two different formats, and the difference matters.

FormatWhat it isLimits
CSVPlain text, one row per line, values separated by a delimiter. No data types, no formatting, no sheets.No limit in the format itself. Excel opens only the first 1,048,576 rows.
XLSXThe current Excel format since 2007: a ZIP archive of XML files. Keeps data types, formatting, formulas, and multiple sheets.1,048,576 rows and 16,384 columns per sheet, 32,767 characters per cell.
XLSThe old binary Excel format from Excel 97 to 2003.65,536 rows and 256 columns per sheet.

For new features there is no reason to produce XLS. Every spreadsheet program in use today reads XLSX, and XLS brings tighter limits and older parsing code. When this article says Excel, it means XLSX. One related shortcut is worth avoiding as well: saving a CSV or an HTML table with an .xls extension. Excel opens it, but only after warning that the file format and extension do not match, and many users read that warning as a sign the file is unsafe.

Why CSV Files Look Broken in Excel

Most complaints about CSV are really complaints about how Excel opens CSV files. When a user double-clicks a CSV, Excel guesses the delimiter, the encoding, and the type of every column, and it guesses using the computer regional settings. Several problems follow, and they hit Indonesian users especially often.

  • Everything lands in one column. Windows with Indonesian regional settings uses a comma as the decimal separator, so the list separator is a semicolon. A comma-separated CSV then opens with every row stuffed into column A. The same file looks fine on a laptop set to English (United States).
  • Leading zeros disappear. Excel treats 081234567890 as a number and shows 81234567890. Postal codes, employee numbers, and product codes that start with zero are affected the same way.
  • Long numbers lose digits. Excel keeps only 15 significant digits. A 16-digit NIK or a bank account number appears as 3.20123E+15, and the last digit is replaced with zero. If the user saves the file, the original number is gone.
  • Names turn into strange characters. Without a byte order mark, Excel on Windows may read a UTF-8 file in the legacy Windows encoding, so a name like José or a non-Latin script is garbled.
  • Dates swap day and month. 04/03/2026 is 4 March in Indonesia and 3 April in the United States, and Excel picks one based on the regional settings.

Writing the CSV carefully helps only partly. Saving as UTF-8 with a byte order mark fixes the encoding, and ISO dates such as 2026-03-04 are read correctly almost everywhere. But nothing in a CSV file can tell Excel that a column is text, so leading zeros and long numbers stay at risk whenever someone double-clicks the file. Users who need to open a CSV in Excel should use Data, then From Text/CSV, where they can pick the delimiter and set columns to text, but most users will not.

What XLSX Fixes, and What It Costs

XLSX stores the type of each cell. A NIK written as text stays text, a date stays a date, and an amount stays a number that can be summed straight away. The file opens the same way on every computer regardless of regional settings, it can hold several sheets, and the header row can be frozen and formatted. For a file that a person will open in Excel, these differences are exactly what the user wants.

The cost is on the server. To see how large it is, we wrote the same 100,000 rows with seven columns (ID, name, NIK, phone number, date, amount, and status) as CSV and as XLSX, then read them back, using Python 3.10 with the standard csv module and openpyxl 3.1.5.

MeasurementCSVXLSX, regular modeXLSX, streaming mode
File size7.8 MB5.5 MB5.5 MB
After gzip2.5 MB5.3 MB5.3 MB
Time to write0.4 s7.3 s7.1 s
Peak memory while writing11 MB309 MB43 MB
Time to read all rows0.06 snot measured6.3 s

A few things stand out. An XLSX file is already compressed, so it starts smaller but gains almost nothing from gzip, while CSV ends up half the size once compressed. Writing XLSX took about seventeen times as long as CSV, and reading it back took about a hundred times as long. The biggest difference is memory: in regular mode the library keeps every cell in memory until the file is saved, so memory grows with the size of the export. The same library in streaming mode writes rows out as it goes and used about a seventh of the memory. The memory figures include around 10 MB for the Python interpreter itself.

Other languages show the same pattern. Most libraries have a convenient mode that builds the whole workbook in memory and a streaming mode for large files: Laravel Excel and PhpSpreadsheet in PHP with chunked queries and queued exports, or OpenSpout for pure streaming, ExcelJS with its streaming WorkbookWriter in Node.js, and excelize with its StreamWriter in Go. One warning for Node.js projects: the xlsx package on npm, from SheetJS, has stayed at version 0.18.5 with known vulnerabilities, including prototype pollution and ReDoS. Newer versions are published only on the SheetJS CDN, so check which one your project actually installs.

Which One to Use

The question that decides it is who reads the file next. A person working in Excel needs XLSX. Another program needs CSV, or better, an API.

SituationRecommended formatWhy
Reports downloaded by finance, admin, or managementXLSXOpens correctly on any computer, keeps numbers summable and codes intact
Data sent to another system, a data warehouse, or a scriptCSV in UTF-8Simple to produce and parse, streams easily, every tool supports it
Bulk upload files whose format is set by a bank, marketplace, or government portalWhatever the specification saysMany require CSV or TXT with an exact delimiter and column order, and the spec always wins
Exports larger than about a million rowsCSV, compressed as ZIP or gzipBeyond the XLSX row limit, and much cheaper to generate
Several related tables in one downloadXLSX with one sheet per tableCSV can only hold one table per file
Data filled in by users and uploaded backAn XLSX template, with CSV also acceptedThe template can mark columns as text and add drop-down lists
Two systems exchanging data every dayAn API, or CSV on a schedule if an API is not possibleFiles sent by hand are easy to forget, edit, or send twice

Offering both is often the right answer for exports. A report page with a Download Excel button for people and a Download CSV button for analysts and integrations costs little extra, because both are produced from the same query.

Building an Export That Holds Up

  • Use streaming mode from the start, and read the data from the database in chunks or with a cursor instead of loading everything with a single query.
  • Generate large exports in a background job, then notify the user or show a download link when the file is ready. An HTTP request that runs for minutes is cut off by the proxy or the load balancer sooner or later.
  • In XLSX, write NIK, phone numbers, account numbers, and other codes as text cells, write amounts as numbers, and write dates as real dates.
  • In CSV, use UTF-8 with a byte order mark if the file will be opened in Excel, quote values according to RFC 4180, and use ISO 8601 dates.
  • Protect against formula injection. A cell whose value starts with =, +, -, or @ can run as a formula when the file is opened. OWASP recommends prefixing such values with a single quote, which matters whenever an export contains text that users typed, such as names, addresses, or notes.
  • Apply the same access rules as the screen the export comes from. An export that skips the permission filter is one of the most common ways data leaks out of business applications.

Building an Import That Does Not Break on Real Files

Imports are harder than exports, because the file comes from a user and can contain anything. A CSV saved by Excel on an Indonesian computer will often use semicolons, and unless the user chose CSV UTF-8 when saving, it will be in the legacy Windows encoding. An import feature has to expect that.

  1. 1Provide a template to download, preferably XLSX, with the expected headers, code columns already set to text, and drop-down lists for values such as status or category.
  2. 2If you accept CSV, detect the delimiter (comma, semicolon, or tab) and the encoding instead of assuming them, and match columns by header name rather than position.
  3. 3Set limits before parsing: maximum file size, maximum number of rows, and only the extensions you support. An XLSX file is a ZIP archive, so a small upload can expand into a very large file. Use a library that limits this, and reject .xlsm files that contain macros.
  4. 4Read the stored cell values and never evaluate formulas from an uploaded file.
  5. 5Validate every row and show a preview with the errors per row, for example row 37: NIK must be 16 digits, before anything is saved.
  6. 6Save everything in one transaction, or through a staging table, so a failure in the middle does not leave half the data imported. For large files, process the import in a background job and report the result when it is done.

In Short

CSV is the better format for machines and XLSX is the better format for people. Most problems come from using a CSV where people will open it by double-clicking, or from producing a large XLSX without streaming. Decide based on who reads the file next, use streaming and background jobs for large exports, and treat every uploaded file as untrusted input. If your application needs import and export features built or fixed, especially for large data or for integration with other systems, our custom software team can help.

Key takeaways

  • Use XLSX for files people will open in Excel, and CSV for files read by other systems, scripts, or very large exports. Do not produce the old XLS format.
  • Excel opens CSV using regional settings, so Indonesian users often see one column, lost leading zeros, NIKs in scientific notation, and garbled names.
  • In our test with 100,000 rows, XLSX took about 17 times longer to write than CSV, and regular mode used 309 MB of memory compared with 43 MB in streaming mode.
  • For exports, stream the data, run large jobs in the background, write codes as text, and guard against formula injection.
  • For imports, provide an XLSX template, detect delimiter and encoding, limit file size, validate every row with a preview, and save in a single transaction.
Share this article

Related articles

More articles on software development, AI, cloud, and infrastructure.

The word DATA printed in dots on a glass windowBackend Development

10 min read

Choosing the Right Database: PostgreSQL, MySQL, MongoDB, SQLite, or Redis?

For most business applications the right database is a boring one, and the hard part is knowing when it is not. What PostgreSQL, MySQL and MariaDB, SQLite, MongoDB, and Redis or Valkey are each good at, the questions that decide the choice, the versions that are reaching end of life, and the mistakes that are expensive to undo.

A laptop showing SQL queries in a code editorBackend Development

10 min read

Database Indexing in Practice: Why Queries Get Slow and Which Index Fixes Them

We loaded two million orders into PostgreSQL 18 and measured common queries with and without indexes. One index cut a query from 40 ms to 0.2 ms, another did nothing at all, and one query ran slower with an index than without. What the numbers show about composite indexes, column order, functions in WHERE, partial indexes, and the cost on writes.

Let’s talk

Looking for a software development partner?

Tell us about your project, what you need to build, and the challenges you are facing. We can discuss the technical approach, scope, timeline, and estimated cost.

Start a conversation