提问人:Lyubomyr Shaydariv 提问时间:5/14/2011 最后编辑:GuildensternLyubomyr Shaydariv 更新时间:10/3/2023 访问量:672532
是否可以强制 Excel 自动识别 UTF-8 CSV 文件?
Is it possible to force Excel recognize UTF-8 CSV files automatically?
问:
我正在开发一个应用程序的一部分,该应用程序负责将一些数据导出到 CSV 文件中。该应用程序始终使用 UTF-8,因为它在各个级别都具有多语言性质。但是在Excel中打开这样的CSV文件(包含例如变音符号,西里尔字母,希腊字母)并不能达到预期的结果,显示类似.而且我不知道如何强制 Excel 理解打开的 CSV 文件是以 UTF-8 编码的。我还尝试指定 UTF-8 BOM ,但 Excel 忽略了这一点。Г„/Г¤, Г–/Г¶
EF BB BF
有什么解决方法吗?
P.S. 哪些工具可能像 Excel 一样运行?
更新
我不得不说,我把社区与问题的表述混淆了。当我问这个问题时,我要求一种在 Excel 中打开 UTF-8 CSV 文件的方法,以流畅和透明的方式对用户没有任何问题。但是,我使用了错误的表述,要求自动执行。这非常令人困惑,并且与VBA宏自动化相冲突。对于这个问题,我最欣赏两个答案:亚历克斯的第一个答案,我已经接受了这个答案;马克的第二个,稍后出现。从可用性的角度来看,Excel 似乎缺乏良好的用户友好型 UTF-8 CSV 支持,所以我认为这两个答案都是正确的,我首先接受了 Alex 的答案,因为它确实表明 Excel 无法透明地做到这一点。这就是我在这里自动混淆的。Mark 的回答为更高级的用户提供了一种更复杂的方法来达到预期的结果。两个答案都很棒,但亚历克斯的答案更适合我没有明确说明的问题。
更新 2
在上次编辑五个月后,我注意到亚历克斯的答案由于某种原因消失了。我真的希望这不是一个技术问题,我希望现在不再讨论哪个答案更大。所以我接受马克的答案是最好的答案。
答:
Alex 是正确的,但由于您必须导出到 csv,因此您可以在打开 csv 文件时向用户提供以下建议:
- 将导出的文件另存为 csv
- 打开 Excel
- 使用数据导入数据-->导入外部数据-->导入数据
- 选择文件类型“csv”并浏览到您的文件
- 在导入向导中,将File_Origin更改为“65001 UTF”(或选择正确的语言字符标识符)
- 将分隔符更改为逗号
- 选择要导入的位置和完成位置
这样,特殊字符应该正确显示。
评论
首先将 Excel 电子表格另存为 Unicode 文本。使用 Internet Explorer 打开 TXT 文件,然后单击“另存为” TXT 编码 - 选择适当的编码,即 Win Cyrillic 1251
我们使用了以下解决方法:
- CSV 转换成UTF-16 LE
- 在文件开头插入 BOM
- 使用制表符作为字段分隔符
评论
用于打开 utf-8 文本和 csv 文件的简单 vba 宏
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
Origin:=65001 是 UTF-8。 逗号:对于以列形式分发的 .csv 文件为 True
将其保存在 Personal.xlsb 中,使其始终可用。 个性化 excel 工具栏,添加一个宏调用按钮并从那里打开文件。 您可以向宏添加更多格式,例如列自动调整、对齐等。
评论
UTF-8 字节顺序标记 (BOM) 将使 Excel 2007+ 了解您使用的是 UTF-8。(请参阅此 SO 帖子)。
如果有人遇到和我一样的问题,.NET 的 UTF8 编码类不会在调用中输出字节顺序标记。您需要使用流(或使用解决方法)来输出 BOM。GetBytes()
评论
UTF-8
UTF-8 with BOM
GetBytes()
GetPreamble()
GetBytes()
这是一个老问题,但我刚刚遇到了类似的问题,解决方案可能会对其他人有所帮助:
有同样的问题,将 CSV 文本数据写出到文件中,然后在 Excel 中打开生成的 .csv 会将所有文本移动到一列中。在阅读了上述答案后,我尝试了以下方法,这似乎解决了问题。
在创建 StreamWriter 时应用 UTF-8 编码。就是这样。
例:
using (StreamWriter output = new StreamWriter(outputFileName, false, Encoding.UTF8, 2 << 22)) {
/* ... do stuff .... */
output.Close();
}
评论
Close()
Dispose
忽略 BOM 的错误似乎已在 Excel 2013 中修复。我在使用西里尔字母时遇到了同样的问题,但添加 BOM 字符确实有所帮助。\uFEFF
评论
$utf8_with_bom = chr(239) . chr(187) . chr(191) . $csvText
;
我过去也遇到过同样的问题(如何生成 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文件也有同样的问题。
当分隔符是在内容开头定义时(当然是在 BOM 之后)定义 BOM 时,Excel 会忽略 BOM。"sep=,\n"
因此,在内容开头添加 BOM () 并将分号设置为分隔符 via 就可以了。"\xEF\xBB\xBF"
fputcsv($fh, $data_array, ";");
评论
是的,这是可能的。在编写创建 csv 的流时,首先要做的是:
myStream.Write(Encoding.UTF8.GetPreamble(), 0, Encoding.UTF8.GetPreamble().Length)
评论
老问题,但哎呀,最简单的解决方案是:
- 在记事本中打开 CSV
- 另存为 ->选择正确的编码
- 打开新文件
评论
只是为了帮助有兴趣在 Excel 上打开文件以实现此线程的用户,例如我。
我使用了下面的向导,它对我来说工作正常,导入了一个 UTF-8 文件。 不透明,但如果您已经拥有该文件,则很有用。
- 打开 Microsoft Excel 2007。
- 单击“数据”菜单栏选项。
- 单击“从文本”图标。
- 导航到要导入的文件的位置。单击文件名,然后单击“导入”按钮。文本导入向导 - 步骤 1 或 3 窗口现在将出现在屏幕上。
- 选择最能描述数据的文件类型 - 分隔或固定宽度。
- 从“文件源”旁边显示的下拉列表中选择“65001: Unicode (UTF-8)”。
- 单击“下一步”按钮以显示“文本导入向导 - 第 2 步或第 3 步”窗口。
- 在要导入到 Microsoft Excel 2007 的文件中使用的分隔符旁边打勾。“数据预览”窗口将根据您选择的分隔符显示数据的显示方式。
- 单击“下一步”按钮以显示文本导入向导 - 第 3 步(共 3 步)。
- 为要导入的每列数据选择适当的数据格式。如果需要,您还可以选择不导入一列或多列数据。
- 单击“完成”按钮以完成将数据导入 Microsoft Excel 2007 的过程。
来源: https://www.itg.ias.edu/content/how-import-csv-file-uses-utf-8-character-encoding-0
如果您想使其完全自动化,一键式,或者从网页自动加载到 Excel 中,但无法生成正确的 Excel 文件,那么我建议您查看 SYLK 格式作为替代方案。好的,它不像 CSV 那么简单,但它是基于文本的,非常容易实现,并且它支持 UTF-8 没有问题。
我编写了一个 PHP 类来接收数据并输出一个 SYLK 文件,只需单击该文件即可直接在 Excel 中打开(或者如果您将文件写入具有正确 mime 类型的网页,则会自动启动 Excel。您甚至可以添加格式(如粗体、以特定方式设置数字格式等)并更改列大小,或自动调整列大小到列中的文本,总而言之,代码可能不超过 100 行。
通过创建一个简单的电子表格并另存为 SYLK,然后使用文本编辑器读取它,对 SYLK 进行逆向工程非常容易。第一个块是您将识别的标题和标准数字格式(您只需在创建的每个文件中反刍),然后数据只是一个 X/Y 坐标和一个值。
令人难以置信的是,有这么多答案,但没有一个回答这个问题:
“当我问这个问题时,我问了一种打开 UTF-8 的方法 Excel 中的 CSV 文件对用户没有任何问题,...”
标记为具有 200+ 赞成票的已接受答案的答案对我来说毫无用处,因为我不想给我的用户提供如何配置 Excel 的手册。 除此之外:本手册将适用于一个 Excel 版本,但其他 Excel 版本具有不同的菜单和配置对话框。每个 Excel 版本都需要一本手册。
那么问题来了,如何让Excel通过简单的双击来显示UTF8数据呢?
好吧,至少在 Excel 2007 中,如果您使用 CSV 文件,这是不可能的,因为 UTF8 BOM 被忽略,您将只看到垃圾。这已经是 Lyubomyr Shaydariv 问题的一部分:
“我还尝试指定 UTF-8 BOM EF BB BF,但 Excel 忽略了这一点。”
我有同样的经历:将俄语或希腊语数据写入带有 BOM 的 UTF8 CSV 文件会导致 Excel 中的垃圾:
UTF8 CSV文件内容:
Colum1;Column2
Val1;Val2
Авиабилет;Tλληνικ
Excel 2007中的结果:
解决方案是根本不使用 CSV。这种格式由 Microsoft 愚蠢地实现,如果使用逗号或分号作为分隔符,它取决于控制面板中的区域设置。因此,相同的 CSV 文件可以在一台计算机上正确打开,但在另一台计算机上则无法打开。 “CSV”表示“逗号分隔值”,但例如,在德语 Windows 上,默认情况下,分号必须用作分隔符,而逗号不起作用。(这里应该命名为 SSV = 分号分隔值)CSV 文件不能在不同语言版本的 Windows 之间互换。这是 UTF-8 问题的另一个问题。
Excel 已经存在了几十年。遗憾的是,Microsoft 这些年来未能实现 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中的结果:
您甚至可以在 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中的结果:
在这种情况下,只有表格本身具有黑色边框和线条。如果您希望所有单元格都显示网格线,这在 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中的结果:
评论
是的,这是可能的。正如多个用户之前所指出的,当文件以 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 格式。
评论
一个真正惊人的答案列表,但由于仍然缺少一个相当不错的答案,我将在这里提及它:使用 google 表格打开 csv 文件并将其作为 excel 文件保存回本地计算机。
与Microsoft相比,Google已设法支持UTF-8 csv文件,因此它可以在那里打开文件。导出为 excel 格式也可以正常工作。因此,尽管这可能不是所有人的首选解决方案,但它是相当安全的,并且点击次数并不像听起来那么高,尤其是当您已经登录谷歌时。
这并不能准确地解决问题,但由于我偶然发现了这一点,并且上述解决方案对我不起作用或有我无法满足的要求,因此当您有权访问 vim 时,这是添加 BOM 的另一种方法:
vim -e -s +"set bomb|set encoding=utf-8|wq" filename.csv
- 下载并安装 LibreOffice Calc
- 在 LibreOffice Calc 中打开您选择的 csv 文件
- 谢天谢地,出现了一个导入文本向导......
- ...选择分隔符和字符编码选项
- 在 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);
}
您的里程可能会有所不同 - 我使用的是 Office 365 中的 .NET 4 和 Excel。
嗨,我正在使用 Ruby on Rails 生成 CSV。在我们的应用程序中,我们计划使用多语言(I18n),我们在Windows excel的CSV文件中查看I18n内容时遇到了一个问题。
Linux(Ubuntu)和Mac都很好。
我们发现 windows excel 需要再次导入数据才能查看实际数据。在导入时,我们将获得更多选项来选择字符集。
但这并不能为每个用户提供教育,因此我们寻找的解决方案是只需双击即可打开。
然后,我们确定了在 aghuddleston gist 的帮助下,在 Windows excel 中通过打开模式和 bom 显示数据的方式。在引用时添加。
示例 I18n 内容
在 Mac 和 Linux 中
瑞典语 : Förnamn 中文 : 名字
在 Windows 中
瑞典语 : Förnamn 中文 : 名字
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
这里需要注意的重要事项是开放模式和 BOM
open_mode = “w+:UTF-16LE:UTF-8”
bom = “\xEF\xBB\xBF”
在写入 CSV 之前,请插入 BOM
f.写入BOM
f.写入(csv_file)
Windows 和 Mac
双击可以直接打开文件。
Linux(ubuntu)
您可以通过Notepad ++将.csv文件转换为带有BOM的UTF-8:
- 在 Notepad++ 中打开文件。
- 转到菜单→。
Encoding
Convert to UTF-8-BOM
- 转到菜单→。
File
Save
- 关闭 Notepad++。
- 在 Excel 中打开文件。
在 Windows 8.1 上的 Microsoft Office Professional Plus 2013 中使用 Microsoft Excel 2013 (15.0.5093.1000) MSO (15.0.5101.1000) 64 位,非 Unicode 程序的区域设置设置为“德语(德国)”。
评论
我尝试了在这个线程上能找到的所有东西,但没有什么能完全发挥作用。但是,导入到谷歌表格并简单地下载为 csv 就像一个魅力。如果你来到我的挫败感点,那就试试吧。
几天前我遇到了同样的问题,找不到任何解决方案,因为我无法使用该功能,因为它使所有内容都设置为字符串样式。import from csv
我的解决方案是首先使用 notpad++ 和 .
然后只是在excel中打开文件,它按预期工作。change the encode to ASCII
在 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 的工作解决方案
- 保存在(无 LE、BE)
UTF-16
- 使用分隔符
\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=...行,它起作用了。
这是 Microsoft 365 与 Excel 版本 2110 内部版本 14527.20276。
找到了 ASP.NET Core 的解决方案,使用 POM 将 CSV 下载为 UTF8:
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;
}
在 Python 中,使用 Python 对带有 BOM 的 UTF-8 的名称。只是不会被Excel或其他Microsoft软件所接受。
从 https://docs.python.org/3/library/codecs.html:encoding=utf-8-sig
utf-8
为了提高检测UTF-8编码的可靠性,Microsoft发明了UTF-8的变体(Python称之为“utf-8-sig”)
参见 utf-8 和 utf-8-sig 有什么区别?
使用标准的 python csv 库,这将是:
with open('some.csv', 'w', newline='', encoding='utf-8-sig') as f:
writer = csv.writer(f)
writer.writerows(someiterable)
它也适用于其他库,例如 pandas:
df.to_csv('some.csv', encoding='utf-8-sig')
我做了一个彻底的改变:我没有向我的用户提供.csv,而是提供.xlsx :)
由于我是以编程方式生成 CSV 文件,并且只有人类操作这些文件,因此没有理由继续使用简单格式 .csv(更适合解析)。注意:.xlsx
文件受到广泛支持(不仅在 Excel 中)。
我不必更改所有逻辑,我只是使用我以前的 CSV 生成脚本,并添加了一个 Excel 库,只需几行即可将 CSV 转换为 XLSX。无论使用何种语言:),您都应该能够这样做
理想情况下,我宁愿没有Microsoft的东西,但有时你只是坐在“标准”上。
15 年后,我终于找到了解决方案:在没有 的情况下编写 CSV,它将在 Excel 2007+ 上运行。UTF-16-LE
BOM
Python 示例:
import csv
with open('test.csv', "w", encoding="utf-16-le", newline='') as csvfile:
w = csv.writer(csvfile, delimiter=';')
w.writerow(["abc", "def"])
w.writerow(["été", "hiver"])
输出的 CSV 文件可以直接使用 Excel 打开,并且:
- (1)口音没有问题
- (2)分隔符会自动解析为多列
注意:如果使用 代替 ,(1) 仍然可以,但不能 (2)。encoding="utf-16"
utf-16-le
评论
UTF-16-LE without BOM
csv
utf-16
utf-16-le
csv
utf8
csv
utf8
Pandas.DataFrame.to_csv()
对于那些有能力手动转换一些文件的人,这里有一些答案,提到了如何使用 Notepad++ 转换它们,但我想使用 VS Code (Visual Studio Code / VSCode) 添加解决方案:
- 在 VS Code 中打开 CSV 文件
- 在底部栏中,单击编码(在我的情况下,是右起第 4 个:“UTF-8”、“LF”、“纯文本”、通知铃)。如果将鼠标悬停在它上面,它将显示“选择编码”。如果找不到,另一种方法是单击VS Code“帮助”菜单(顶部栏)->“显示所有命令”->键入“更改文件编码”
- 它将在顶部栏中打开一个操作列表。点击“使用编码保存”
- 它将打开一个可能的编码列表。单击您想要的那个,您就可以开始了,在 Excel 中打开它并在那里显示正确的字符。就我而言,我选择了“UTF-8 with BOM”,它在 Excel 365 中工作(“Excel for Microsoft 365 MSO(版本 2311)”)
评论
\t
Ctrl-S