Skip to content
Start free

How do I save a CSV that opens correctly on the other end?

Choose how to write a CSV based on who will read it: with a BOM for someone opening it in Excel, with semicolons and a decimal comma for a system that expects them, and without pandas' index column.

Free course. Your Maestro, an AI, .

Until now you were the one receiving. Now it's your turn to send: the September and October sales report goes to two people. Your boss will open it with a double click in Excel. And the Valencia supplier, who asked you for the same figures to plan their shipments, will load it into their system, which expects the same format it sends: semicolons and a decimal comma.

Everything you learned about reading works in reverse. A CSV doesn't state its encoding, doesn't state its separator, doesn't state which columns are text. So the question when writing isn't "what's the right format?" but "who will read it, and what will they assume?"

  • Someone double-clicking in Excel. Microsoft documents that "You can open a CSV file encoded with UTF-8 normally if it was saved with BOM (Byte Order Mark)". That's your chance to make the BOM work in your favor: write it and the accents in Mérida arrive intact.
  • A system that expects semicolons. Give it exactly what it expects: ; between columns and , as the decimal mark. If you don't know what it expects, ask before sending.
  • Another program or a script. UTF-8, comma, decimal point and dates like 2026-09-02. DuckDB, for example, documents that its COPY always writes UTF-8.

From Excel

If the file comes out of an Excel sheet, Microsoft gives two ways to save a CSV, depending on the format you choose:

  1. Go to File and select Save as or Save a Copy.
  2. Under the File name, select the drop down and choose CSV (Comma delimited)(*.csv). Microsoft notes that other CSV formats are available if you scroll down.
  3. Select Save.
  1. Go to File and select Save as or Save a Copy.
  2. Under the File Format, select the drop down and choose CSV UTF-8 (Comma delimited)(*.csv). Other CSV formats are available if you scroll down.
  3. Select Save.

Three notes from Microsoft. First, the save-as-CSV page names the two formats, but it doesn't say whether the UTF-8 one carries a BOM: don't take it for granted, and if the file is going to someone who opens it with a double click, check its first three bytes, as revisar.py does in the exercise below. Second, "When you save a workbook in any of the text formats, all formatting will be removed": colors, column widths and other formatting don't travel in a CSV. Excel also reminds you, with a dialog box, that only the current sheet is saved. Third, Excel for the web can't save a CSV today; from there, use Editing > Open in Desktop App.

And remember module 3: if the sheet already lost zeros or digits, the CSV you save will have lost them too.

Common mistake: Windows-1252 only if they ask for it

If an old system asks you for Windows-1252, encoding="cp1252" writes it. But that table doesn't have room for everything: in the sandbox, an emoji in a comment made the write fail with UnicodeEncodeError. Use UTF-8 unless the reader demands something else.

Writing the report for your boss

Worked example · 4 steps

Your boss opens the sales report with a double click in Excel. With the default options, to_csv writes an index column and doesn't write a BOM. What do you change, and in what order do you think it through? Try each step before opening it.

Work out the next step yourself, then open it to compare.

Try it

The project has the report in datos/ventas.csv and a script, exporta.py, that writes both files with the default options. At the end it calls revisar, which prints whether each file starts with a BOM and its contents exactly as they are. Run uv run exporta.py and see what each person would receive. Then change the two to_csv calls: you saw the first one solved above; the second is for you. If you don't know which option a file is missing, ask your Maestro.

Your turn

Run uv run exporta.py. Change the two to_csv calls so that: para_excel.csv comes out without the index column and with a BOM; and para_valencia.csv comes out without the index and without a BOM, with ; between columns, a decimal comma and always two decimals (1520,00). Don't change revisar.py or the data.

    Python 3.12· runs with your account

    Check yourself: You send your boss a CSV made with pandas. She opens it with a double click and sees Mérida. You wrote it with to_csv("reporte.csv", index=False). What do you change?