是否可以强制Excel自动识别UTF-8 CSV文件?

我正在开发一个应用程序的一部分,负责将一些数据导出到CSV文件。应用程序总是使用UTF-8,因为它在所有级别上都具有多语言特性。但是在Excel中打开这样的CSV文件(包含例如变音符,西里尔字母,希腊字母)并没有达到显示类似Г„/Г¤, Г–/Г¶的预期结果。我不知道如何强制Excel理解打开的CSV文件是UTF-8编码的。我还尝试指定UTF-8 BOM EF BB BF,但Excel忽略了这一点。

有什么解决办法吗?

附注:哪些工具可能像Excel一样?


更新

我不得不说,我把这个问题的提法搞糊涂了。当我问这个问题时,我要求一种方法,在Excel中打开UTF-8 CSV文件,没有任何问题,以流畅和透明的方式为用户。然而,我用了一个错误的公式要求这样做自动。这是非常令人困惑的,它与VBA宏自动化冲突。对于这个问题,我有两个最欣赏的答案:Alex https://stackoverflow.com/a/6002338/166589的第一个答案,我已经接受了这个答案;第二幅是稍后出现的马克·EYZ2的作品。从可用性的角度来看,Excel似乎缺乏良好的用户友好的UTF-8 CSV支持,所以我认为这两个的答案是正确的,我先接受了Alex的答案,因为它确实说明了Excel不能透明地做到这一点。这就是我和自动混淆的地方。Mark的回答为更高级的用户提供了一种更复杂的方式来实现预期的结果。两个答案都很好,但Alex的回答更适合我没有明确说明的问题。


更新2

在最后一次编辑5个月后,我注意到Alex的答案不知为何消失了。我真的希望这不是一个技术问题,我希望现在不再有关于哪个答案更好的讨论。所以我认为马克的答案是最好的。

635221 次浏览

Alex是正确的,但是由于你必须导出到csv,你可以在打开csv文件时给用户这样的建议:

  1. 另存为csv格式
  2. 打开Excel
  3. 使用“data”导入数据——>导入外部数据——>导入数据
  4. 选择文件类型“csv”并浏览到您的文件
  5. 在导入向导中将File_Origin更改为“65001 UTF”(或选择正确的语言字符标识符)
  6. 将分隔符更改为逗号
  7. 选择要导入的位置并完成

这样特殊字符才能正确显示。

首先将Excel电子表格保存为Unicode文本。使用ie浏览器打开TXT文件,点击“另存为”TXT编码-选择合适的编码,例如Win Cyrillic 1251

我们使用了以下方法:

  1. 转换CSV到UTF-16 LE
  2. 在文件开头插入BOM
  3. 使用制表符作为字段分隔符

简单的vba宏用于打开utf-8文本和csv文件

Sub OpenTextFile()


filetoopen = Application.GetOpenFilename("Text Files (*.txt;*.csv), *.txt;*.csv")
If filetoopen = Null Or filetoopen = Empty Then Exit Sub


Workbooks.OpenText Filename:=filetoopen, _
Origin:=65001, DataType:=xlDelimited, Comma:=True


End Sub

来源:=65001是UTF-8。 逗号:对于列

的.csv文件为True

保存在个人。XLSB使它始终可用。 个性化excel工具栏添加一个宏调用按钮,并从那里打开文件。 你可以添加更多的格式到宏,如列自动拟合,对齐等

UTF-8字节顺序标记将提示Excel 2007+您正在使用UTF-8。(见# EYZ0)。

以防有人遇到和我一样的问题,. net的UTF8编码类不会在GetBytes()调用中输出字节顺序标记。您需要使用流(或使用一个解决方案)来获取要输出的BOM。

这是一个老问题,但我刚刚遇到过类似的问题,解决方案可能会帮助其他人:

同样的问题是,将CSV文本数据写入文件,然后在Excel中打开生成的. CSV,将所有文本转移到单个列中。在阅读了上面的答案后,我尝试了下面的答案,这似乎可以解决问题。

在创建StreamWriter时应用UTF-8编码。就是这样。

例子:

using (StreamWriter output = new StreamWriter(outputFileName, false, Encoding.UTF8, 2 << 22)) {
/* ... do stuff .... */
output.Close();
}

Excel 2013中忽略BOM的错误似乎已经修复。我有同样的问题与西里尔字母,但添加BOM字符\uFEFF确实有所帮助。

我过去也遇到过同样的问题(如何生成Excel可以读取的文件,以及其他工具也可以读取的文件)。我使用的是TSV而不是CSV,但同样的编码问题出现了。

我没能找到任何方法让Excel自动识别UTF-8,我也不愿意/不能给文件的使用者复杂的如何打开它们的指令。所以我将它们编码为UTF-16le(带有BOM)而不是UTF-8。大小是原来的两倍,但Excel可以识别编码。而且它们的压缩性很好,所以尺寸很少(但遗憾的是并非永远)重要。

这是我的工作解决方案:

vbFILEOPEN = "your_utf8_file.csv"
Workbooks.OpenText Filename:=vbFILEOPEN, DataType:=xlDelimited, Semicolon:=True, Local:=True, Origin:=65001

密钥是Origin:=65001

有同样的问题与php生成的CSV文件。 当分隔符在内容的开头通过"sep=,\n"定义时(当然是在BOM之后),Excel会忽略BOM

因此,在内容的开头添加BOM ("\xEF\xBB\xBF")并通过fputcsv($fh, $data_array, ";");设置分号作为分隔符就可以实现这个目的。

是的,这是可能的。当写入流创建csv时,要做的第一件事是:

myStream.Write(Encoding.UTF8.GetPreamble(), 0, Encoding.UTF8.GetPreamble().Length)

老问题了,但最简单的解决方法是:

  1. 在记事本中打开CSV
  2. 另存为->选择正确的编码
  3. 打开新文件

只是为了帮助有兴趣在Excel上打开文件实现这个线程的用户。

我使用了下面的向导,它对我来说工作得很好,导入了一个UTF-8文件。 不是透明的,但是如果你已经有了这个文件,它是有用的
  1. 打开Microsoft Excel 2007。
  2. 单击Data菜单栏选项。
  3. 单击From Text图标。
  4. 导航到要导入的文件的位置。单击文件名,然后单击Import按钮。文本导入向导-步骤1或3窗口现在将出现在屏幕上。
  5. 选择最能描述您的数据的文件类型-分隔宽度或固定宽度。
  6. 从“文件来源”旁边的下拉列表中选择65001:Unicode (UTF-8)。
  7. 单击“下一步”按钮,显示“文本导入向导-步骤2或3”窗口。
  8. 在要导入microsoftexcel2007的文件中使用的分隔符旁边放置一个复选标记。“数据预览”窗口将根据所选的分隔符显示数据的显示方式。
  9. 单击“下一步”按钮,显示文本导入向导-步骤3。
  10. 为要导入的每一列数据选择适当的数据格式。如果愿意,您还可以选择不导入一列或多列数据。
  11. 单击Finish按钮完成将数据导入Microsoft Excel 2007。

来源:# EYZ0

如果你想让它完全自动化,点击一下,或者从一个网页自动加载到Excel中,但不能生成适当的Excel文件,那么我建议考虑SYLK格式作为替代方案。好吧,它不像CSV那么简单,但它是基于文本的,非常容易实现,它支持UTF-8没有问题。

我写了一个PHP类,接收数据并输出一个SYLK文件,该文件将通过单击文件直接在Excel中打开(或者如果您将文件写入具有正确mime类型的web页面,将自动启动Excel)。你甚至可以添加格式(如粗体,以特定的方式格式化数字等),改变列的大小,或自动调整列的文本,所有的代码可能不超过100行。

通过创建一个简单的电子表格并保存为SYLK,然后用文本编辑器读取它,就可以非常容易地对SYLK进行逆向工程。第一个块是您可以识别的标头和标准数字格式(您只需在创建的每个文件中反刍它们),然后数据只是一个X/Y坐标和一个值。

令人难以置信的是,有这么多答案,但没有一个能回答这个问题:

当我问这个问题时,我问了一种打开UTF-8的方法 CSV文件在Excel没有任何问题的用户,…" < / p >
标记为200+赞成的接受答案对我来说是无用的,因为我不想给我的用户如何配置Excel的手册。 除此之外:本手册将适用于一个Excel版本,但其他Excel版本有不同的菜单和配置对话框。每个Excel版本都需要一个手册

那么问题是如何使Excel显示UTF8数据与一个简单的双击?

好吧,至少在Excel 2007中,如果你使用CSV文件,这是不可能的,因为UTF8 BOM被忽略,你只会看到垃圾。这已经是Lyubomyr Shaydariv问题的一部分:

“我还尝试指定UTF-8 BOM EF BB BF,但Excel忽略了这一点。”

我也有同样的经历:将俄语或希腊语数据写入UTF8 CSV文件,并使用BOM在Excel中生成垃圾:

UTF8 CSV文件内容:

Colum1;Column2
Val1;Val2
Авиабилет;Tλληνικ

Excel 2007的结果:

CSV UTF8 Excel

一种解决方案是根本不使用CSV。这种格式被微软实现得很愚蠢,如果使用逗号分号作为分隔符,它取决于控制面板中的区域设置。因此,相同的CSV文件可能在一台计算机上正确打开,但在另一台计算机上却不能。“CSV”的意思是“逗号分隔值”,但例如在德文Windows上,默认情况下分号必须用作分隔符,而逗号则不起作用。(这里应该命名为SSV =分号分隔值)CSV文件不能在不同语言版本的Windows之间交换。这是UTF-8问题的附加问题。

Excel已经存在了几十年。微软这么多年都没能实现CSV导入这样一个基本的功能,真是太遗憾了。


但是,如果您将相同的值放入HTML文件中,并将该文件保存为UTF8文件,文件扩展名为XLS,您将得到正确的结果。

UTF8 XLS文件内容:

<table>
<tr><td>Colum1</td><td>Column2</td></tr>
<tr><td>Val1</td><td>Val2</td></tr>
<tr><td>Авиабилет</td><td>Tλληνικ</td></tr>
</table>

Excel 2007的结果:

UTF8 HTML Excel

你甚至可以在HTML中使用Excel能正确显示的颜色。

<style>
.Head { background-color:gray; color:white; }
.Red  { color:red; }
</style>
<table border=1>
<tr><td class=Head>Colum1</td><td class=Head>Column2</td></tr>
<tr><td>Val1</td><td>Val2</td></tr>
<tr><td class=Red>Авиабилет</td><td class=Red>Tλληνικ</td></tr>
</table>

Excel 2007的结果:

UTF8 HTML Excel

在这种情况下,只有表本身具有黑色边框和线条。如果你想要所有的单元格显示网格线,这在HTML中也是可能的:

<html xmlns:x="urn:schemas-microsoft-com:office:excel">
<head>
<meta http-equiv="content-type" content="text/plain; charset=UTF-8"/>
<xml>
<x:ExcelWorkbook>
<x:ExcelWorksheets>
<x:ExcelWorksheet>
<x:Name>MySuperSheet</x:Name>
<x:WorksheetOptions>
<x:DisplayGridlines/>
</x:WorksheetOptions>
</x:ExcelWorksheet>
</x:ExcelWorksheets>
</x:ExcelWorkbook>
</xml>
</head>
<body>
<table>
<tr><td>Colum1</td><td>Column2</td></tr>
<tr><td>Val1</td><td>Val2</td></tr>
<tr><td>Авиабилет</td><td>Tλληνικ</td></tr>
</table>
</body>
</html>

这段代码甚至允许指定工作表的名称(这里是“MySuperSheet”)

Excel 2007的结果:

enter image description here

是的,这是可能的。正如之前多个用户所指出的,当文件以UTF-8编码时,excel读取正确的字节顺序标记似乎存在问题。对于UTF-16,它似乎没有问题,所以它是UTF-8特有的。我为此使用的解决方案是添加BOM,两次。为此,我执行了两次下面的sed命令:

sed -I '1s/^/\xef\xbb\xbf/' *.csv

,其中通配符可以替换为任何文件名。然而,这会导致.csv文件开头的sep=发生突变。然后,.csv文件将在excel中正常打开,但在第一个单元格中有一个带有“sep=”的额外行。 "sep="也可以在源文件的.csv中删除,但是当用VBA打开文件时,应该指定分隔符:

Workbooks.Open(name, Format:=6, Delimiter:=";", Local:=True)

格式6是.csv格式。将Local设置为true,以防文件中有日期。如果Local未设置为true,日期将被美国化,这在某些情况下会破坏.csv格式。

一个真正令人惊叹的答案列表,但由于还缺少一个非常好的答案,我在这里提到它:用谷歌表打开csv文件,并将其保存到本地计算机作为excel文件。

与微软相比,谷歌已经成功支持UTF-8 csv文件,所以它只是在那里打开文件。导出到excel格式也可以。因此,尽管这可能不是所有人的首选解决方案,但它是非常安全的,点击次数也不像听起来那么多,特别是当您已经登录到谷歌时。

这并不是准确地解决问题,但由于我偶然发现了这一点,上面的解决方案不适合我或有要求,我不能满足,这里是另一种方式添加BOM时,你可以访问vim:

vim -e -s +"set bomb|set encoding=utf-8|wq" filename.csv
  1. 下载,安装LibreOffice Calc
  2. 在LibreOffice Calc中打开您选择的csv文件
  3. 谢天谢地,一个导入文本向导出现了……
  4. ...选择分隔符和字符编码选项
  5. 在Calc中选择结果数据并复制粘贴到Excel中

正如我在http://thinkinginsoftware.blogspot.com/2017/12/correctly-generate-csv-that-excel-can.html上发布的:

告诉负责生成CSV的软件开发人员纠正它。作为一个快速的解决方法,你可以使用gsed在字符串的开头插入UTF-8 BOM:

gsed -i '1s/^\(\xef\xbb\xbf\)\?/\xef\xbb\xbf/' file.csv

如果UTF-4 BOM不存在,该命令将插入。因此这是一个幂等命令。现在您应该能够双击该文件并在Excel中打开它。

我正在从一个简单的c#应用程序生成csv文件,也遇到了同样的问题。我的解决方案是确保文件是用UTF8编码编写的,如下所示:

// Use UTF8 encoding so that Excel is ok with accents and such.
using (StreamWriter writer = new StreamWriter(path, false, Encoding.UTF8))
{
SaveCSV(writer);
}

我最初有以下代码,其中口音在notepad++中看起来很好,但在Excel中被破坏:

using (StreamWriter writer = new StreamWriter(path))
{
SaveCSV(writer);
}

你的里程可能会有所不同——我使用的是。net 4和Office 365中的Excel。

嗨,我正在使用ruby on rails生成CSV。在我们的应用程序中,我们计划使用多语言(I18n),但在windows excel的CSV文件中查看I18n内容时遇到了一个问题。

Linux (Ubuntu)和mac都没问题。

我们发现windows excel需要重新导入数据才能查看实际数据。在导入时,我们将获得更多选择字符集的选项。

但这不能教育每一个用户,所以我们寻找的解决方案是只需双击打开。

然后在aghuddleston 要点的帮助下,确定了在windows excel中以open模式和bom方式显示数据的方法。在引用时添加。

示例I18n内容

在Mac和Linux中

瑞典语:Förnamn 中文:名字

在Windows中

瑞典语:Fö 中文:名字

def user_information_report(report_file_path, user_id)
user = User.find(user_id)
I18n.locale = user.current_lang
open_mode = "w+:UTF-16LE:UTF-8"
bom = "\xEF\xBB\xBF"
body user, open_mode, bom
end


def headers
headers = [
"ID", "SDN ID",
I18n.t('sys_first_name'), I18n.t('sys_last_name'), I18n.t('sys_dob'),
I18n.t('sys_gender'), I18n.t('sys_email'), I18n.t('sys_address'),
I18n.t('sys_city'), I18n.t('sys_state'), I18n.t('sys_zip'),
I18n.t('sys_phone_number')
]
end


def body tenant, open_mode, bom
File.open(report_file_path, open_mode) do |f|
csv_file = CSV.generate(col_sep: "\t") do |csv|
csv << headers
tenant.patients.find_each(batch_size: 10) do |patient|
csv <<  [
patient.id, patient.patientid,
patient.first_name, patient.last_name, "#{patient.dob}",
"#{translate_gender(patient.gender)}", patient.email, "#{patient.address_1.to_s} #{patient.address_2.to_s}",
"#{patient.city}", "#{patient.state}",  "#{patient.zip}",
"#{patient.phone_number}"
]
end
end
f.write bom
f.write(csv_file)
end
end

这里需要注意的重要事项是open mode和bom

open_mode = "w+:UTF-16LE:UTF-8"

bom = "\xEF\xBB\xBF"

在写入CSV之前插入BOM

f.write bom

f.write (csv_file)

Windows和Mac

双击即可直接打开文件。

Linux (ubuntu)

当打开一个文件时,询问分隔符选项->选择“TAB” # EYZ0 < / p >

您可以转换。csv文件到UTF-8与BOM通过notepad++:

  1. notepad++中打开文件。
  2. 转到菜单EncodingConvert to UTF-8-BOM
  3. 转到菜单FileSave
  4. 关闭记事本+ +。
  5. 在Excel中打开文件。

使用Microsoft Excel 2013 (15.0.5093.1000) MSO(15.0.5101.1000) 64位,来自Microsoft Office Professional Plus 2013在Windows 8.1上,非unicode程序的区域设置为"德语(德国)"

我尝试了我能在这个帖子上找到的一切,类似的,没有什么是完全有效的。然而,导入到谷歌表和简单地下载为csv工作就像一个魅力。如果你到了我的挫败点,可以试试。

几天前我遇到了同样的问题,但找不到任何解决方案,因为我不能使用import from csv特性,因为它使所有内容都被样式化为字符串。

我的解决方案是首先用notpad++和change the encode to ASCII打开文件。 然后在excel中打开文件,它就像预期的那样工作了

在php中,你只需要将$bom前置到$csv_string:

$bom = sprintf( "%c%c%c", 239, 187, 191); // EF BB BF
file_put_contents( $file_name, $bom . $csv_string );

使用MS Excel 2016, php 7.2.4进行测试

office 365的工作解决方案

  • 保存在UTF-16(没有LE, BE)
  • 使用分隔符\t

PHP代码

$header = ['číslo', 'vytvořeno', 'ěščřžýáíé'];
$fileName = 'excel365.csv';
$fp = fopen($fileName, 'w');
fputcsv($fp, $header, "\t");
fclose($fp);


$handle = fopen($fileName, "r");
$contents = fread($handle, filesize($fileName));
$contents = iconv('UTF-8', 'UTF-16', $contents);
fclose($handle);


$handle = fopen($fileName, "w");
fwrite($handle, $contents);
fclose($handle);

这是2022年3月,似乎我们不能同时使用BOM和sep=…线。 添加sep=\t或类似,使Excel忽略BOM.

使用分号似乎是Excel的默认理解,在这种情况下,我们可以跳过sep=…这样就行了。

这是微软365与Excel版本2110构建14527.20276。

找到了ASP的解决方案。使用POM下载UTF8格式的CSV文件:

byte[] csvBytes = Encoding.Default.GetBytes(csvString);
UTF8Encoding utf8 = new UTF8Encoding(true);
byte[] bom = utf8.GetPreamble();
var result = bom.Concat(csvBytes).ToArray();
return new FileContentResult(result, MediaTypeHeaderValue.Parse("text/csv; charset=utf-8"));

Excel是识别下载的CSV文件而不是UTF8。

只是分享一个全面的功能,可能会使您的生活更容易与CSV文件....请注意与此主题相关的最后一个函数参数

function array2csv($data, $file = '', $download = true, $mode = 'w+', $delimiter = ',', $enclosure = '"', $escape_char = "\\", $addUnicodeBom = false)
{
$return = false;


if ($file == '') {
$f = fopen('php://memory', 'r+');
} else {
$f = fopen($file, $mode);
}


if ($addUnicodeBom) {
$utf8_with_bom = chr(239) . chr(187) . chr(191);
fwrite($f, $utf8_with_bom);
}




foreach ($data as $line => $item) {


fputcsv($f, $item, $delimiter, $enclosure, $escape_char);
}


rewind($f);


if ($download == true) {
$return = stream_get_contents($f);
} else {
$return = true;
}


return $return;
}