4 ms·
You can specify what separator to use as the first line in the CSV file: sep=, My experience is that Excel 2007 and later will correctly parse the file and us
by davidpolberger 7y ago
You can specify what separator to use as the first line in the CSV file:
sep=,
My experience is that Excel 2007 and later will correctly parse the file and use the specified separator. However, other software, such as Google Sheets, will simply render the declaration as-is.
Then there's the issue of what character encoding to use to encode the file, whether to include a byte-order-mark with UTF-8 to make Excel recognize the file as UTF-8 and the effect that has on whether the separator line is recognized (spoiler: it isn't).
Here's part of the documentation I wrote for Calcapp's CSV exporter, which digs into these issues in more detail (Javadoc):
/**
* The prologue of files containing comma-separated values (CSV). This
* prologue contains an instruction detailing the separator character that is
* used in the file. This instruction is known to be understood by Microsoft
* Excel 2007 and later versions, but is rendered as-is by other spreadsheets,
* including Google Sheets.
* <p>
* Microsoft Excel expects either a comma or a semicolon to separate values in
* CSV files, depending on the Windows locale. The only way to produce a CSV
* file that can be read by Excel regardless of what locale Windows is set to
* use is to use a prologue similar to this one, which explicitly tells Excel
* which separator is used.
*/
private static final String PROLOGUE = "sep=" + SEPARATOR_CHARACTER + "\n";
/**
* The character set used to encode files containing comma-separated values
* (CSV): UTF-16LE (UTF-16 for little-endian systems). Using UTF-16LE allows
* characters that cannot be represented by the ASCII character encoding to be
* correctly read by Microsoft Excel and other spreadsheets.
* <p>
* There is no way to formally specify the character set used by a CSV file.
* With one exception, Excel assumes that CSV files use the ASCII character
* encoding, unless the first three bytes consist of a byte-order mark, in
* which case the UTF-8 encoding is used. (A byte-order mark is redundant for
* UTF-8, as it does not depend on endianness, but is traditionally used by
* Microsoft Windows applications to detect whether a text file uses the UTF-8
* encoding.)
* <p>
* Excel only recognizes a file as being encoded with UTF-8 if a byte-order
* mark is included, but doing so prevents Excel from recognizing the
* information of the {@linkplain #PROLOGUE prologue}, which in turn prevents
* CSV files from being produced which work regardless of the locale Windows
* is set to use. This is likely due to a bug, present in Excel 2007 and
* likely later versions as well (based on anecdotal evidence).
* <p>
* Fortunately, Excel does recognize another character set which can encode
* all of Unicode: UTF-16. Excel likely uses heuristics to determine that a
* file is encoded using UTF-16. (Text written using Western languages and
* encoded using UTF-16 tend to include many null bytes for various reasons,
* making the detection of UTF-16 trivial, but only for Western languages.)
* Unfortunately, UTF-16 is dependent on endianness, meaning that it would be
* desirable to include a byte-order mark at the beginning of the file.
* However, that does not work due to the aforementioned bug.
* <p>
* In other words, using UTF-16LE should work well for CSV files containing
* mostly Western text and parsed on little-endian systems. It is probable,
* though, that files produced using this converter will not work if the text
* mostly contains Chinese, Japanese or Korean characters or if the file is
* parsed on a big-endian system.
*/
public static final Charset CHARACTER_SET;
- Freak_NL 7y agoThat separator preamble seems Excel-specific though: https://tools.ietf.org/html/rfc4180 https://tools.ietf.org/html/rfc4180 If I'm going to mangle CSV into a non-standard form to conform to whatever Excel expects, I might as well go the extra mile and just provide an XLSX file. That was my solution to a data-export function in an API (it switches on the HTTP Accept header). It now offers a choice of CSV (RFC 4180), ODS, and XLSX, and people can just pick XLSX if their Excel is using one of its broken locales. It's not too hard to generate the XML for ODS (OpenOffice/LibreOffice etc.) and XLSX (Excel) from a bunch of tabular records once you've set up minimal empty template ODS/XLSX files to inject it in. It's certainly less work than explaining to Excel users that their software is broken and how to work around it. That said, ODS was much easier to get working.