我正在开发负责将一些数据导出到 CSV 文件的应用程序的一部分。该应用程序始终使用 UTF-8,因为它在所有级别都具有多语言特性。但是在 Excel 中打开此类 CSV 文件(例如包含变音符号、西里尔字母、希腊字母)并不能达到显示类似 Г„/Г¤, Г–/Г¶
的预期结果。而且我不知道如何强制 Excel 理解打开的 CSV 文件是用 UTF-8 编码的。我还尝试指定 UTF-8 BOM EF BB BF
,但 Excel 忽略了这一点。
有什么解决方法吗?
PS 哪些工具可能表现得像 Excel?
更新
我不得不说我把社区与问题的表述混淆了。当我问这个问题时,我要求一种在 Excel 中以流畅和透明的方式打开 UTF-8 CSV 文件的方法,对用户没有任何问题。但是,我使用了一个错误的表述,要求自动进行。这非常令人困惑,并且与 VBA 宏自动化相冲突。这个问题有两个我最欣赏的答案:Alex https://stackoverflow.com/a/6002338/166589的第一个答案,我已经接受了这个答案;以及稍后出现的 Mark https://stackoverflow.com/a/6488070/166589 的第二个。从可用性的角度来看,Excel 似乎缺乏对用户友好的 UTF-8 CSV 支持,所以我认为 both 答案都是正确的,我首先接受了 Alex 的答案,因为它确实说明了Excel 无法透明地做到这一点。这就是我在这里与 automatically 混淆的地方。马克的回答为更高级的用户提供了一种更复杂的方法来达到预期的结果。两个答案都很好,但亚历克斯的答案更适合我没有明确指定的问题。
更新 2
在最后一次编辑五个月后,我注意到亚历克斯的答案由于某种原因消失了。我真的希望这不是一个技术问题,我希望现在不再讨论哪个答案更好。所以我接受马克的回答是最好的。
\t
作为分隔符的 UTF-16LE。将在英语和非英语 Excel 设置中工作。可以按 Ctrl-S
而不选择文件格式等。将保留 Unicode 字符。
Alex 是正确的,但由于您必须导出到 csv,因此您可以在打开 csv 文件时向用户提供以下建议:
将导出的文件另存为 csv 打开 Excel 使用 Data-->Import External Data --> Import Data 导入数据 选择“csv”文件类型并浏览到您的文件 在导入向导中将 File_Origin 更改为“65001 UTF” (或选择正确的语言字符标识符)将分隔符更改为逗号 选择导入位置并完成
这样特殊字符应该正确显示。
UTF-8 字节顺序标记将提示 Excel 2007+ 您正在使用 UTF-8 的事实。 (见this SO post)。
如果有人遇到与我相同的问题,.NET 的 UTF8 编码类不会在 GetBytes()
调用中输出字节顺序标记。您需要 use streams(或使用 a workaround)来获取要输出的 BOM。
UTF-8
转换为 UTF-8 with BOM
忽略 BOM 的错误似乎已在 Excel 2013 中修复。我对西里尔字母有同样的问题,但添加 BOM 字符 \uFEFF
确实有帮助。
$utf8_with_bom = chr(239) . chr(187) . chr(191) . $csvText
;
令人难以置信的是有这么多答案,但没有一个回答这个问题:
“当我问这个问题时,我要求一种在 Excel 中打开 UTF-8 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 中的结果:
https://i.stack.imgur.com/DFbK5.png
一个解决方案是根本不使用 CSV。这种格式被微软实现得太愚蠢了,如果逗号或分号用作分隔符,它取决于控制面板中的区域设置。因此,相同的 CSV 文件可能会在一台计算机上正确打开,但在另一台计算机上则不能。 “CSV”表示“逗号分隔值”,但例如在德语 Windows 上,默认分号必须用作分隔符,而逗号不起作用。 (这里应该命名为 SSV = 分号分隔值) CSV 文件不能在不同语言版本的 Windows 之间互换。这是 UTF-8 问题的另一个问题。
Excel 已经存在了几十年。很遗憾,微软这些年来都无法实现 CSV 导入这样的基本功能。
但是,如果您将相同的值放入 HTML 文件并将该文件保存为 UTF8 文件,带有 BOM 文件扩展名 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 中的结果:
https://i.stack.imgur.com/h0Msk.png
您甚至可以在 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 中的结果:
https://i.stack.imgur.com/z55sV.png
在这种情况下,只有表格本身有黑色边框和线条。如果您希望所有单元格显示网格线,这在 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 中的结果:
https://i.stack.imgur.com/t6o0Q.png
我们使用了这种解决方法:
将 CSV 转换为 UTF-16 LE 在文件开头插入 BOM 使用制表符作为字段分隔符
PHP 生成的 CSV 文件也有同样的问题。当分隔符在内容的开头通过 "sep=,\n"
定义时,Excel 忽略了 BOM(当然在 BOM 之后)。
因此,在内容的开头添加 BOM ("\xEF\xBB\xBF"
) 并通过 fputcsv($fh, $data_array, ";");
将分号设置为分隔符就可以了。
老问题,但见鬼,最简单的解决方案是:
在记事本中打开 CSV 另存为 -> 选择正确的编码 打开新文件
您可以通过 Notepad++ 将 .csv 文件转换为带有 BOM 的 UTF-8:
在记事本++中打开文件。转到菜单编码→转换为 UTF-8。转到菜单文件→保存。关闭记事本++。在 Excel 中打开文件。
在 Windows 8.1 上的 Microsoft Office Professional Plus 2013 中使用 Microsoft Excel 2013 (15.0.5093.1000) MSO (15.0.5101.1000) 64 位,非 Unicode 程序的区域设置为“德语(德国)”。
我过去也遇到过同样的问题(如何生成 Excel 可以读取的文件,其他工具也可以读取)。我使用的是 TSV 而不是 CSV,但出现了同样的编码问题。
我没有找到任何方法让 Excel 自动识别 UTF-8,而且我不愿意/无法对文件的消费者施加复杂的如何打开它们的说明。所以我将它们编码为 UTF-16le(带有 BOM)而不是 UTF-8。两倍大小,但 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 中打开它。
在 php 中,您只需在 $csv_string 前添加 $bom:
$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 测试
用于打开 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
来源:=65001 是 UTF-8。逗号:适用于以列形式分布的 .csv 文件
将其保存在 Personal.xlsb 中以使其始终可用。个性化 Excel 工具栏,添加宏调用按钮并从那里打开文件。您可以为宏添加更多格式,例如列自动调整、对齐等。
只是为了帮助有兴趣在 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
这是我的工作解决方案:
vbFILEOPEN = "your_utf8_file.csv"
Workbooks.OpenText Filename:=vbFILEOPEN, DataType:=xlDelimited, Semicolon:=True, Local:=True, Origin:=65001
关键是 Origin:=65001
对的,这是可能的。在编写创建 csv 的流时,首先要做的是:
myStream.Write(Encoding.UTF8.GetPreamble(), 0, Encoding.UTF8.GetPreamble().Length)
是的,这是可能的。正如多个用户之前所指出的,当文件以 UTF-8 编码时,excel 读取正确的字节顺序标记似乎存在问题。使用 UTF-16 似乎没有问题,因此它是 UTF-8 特有的。我为此使用的解决方案是添加 BOM,TWICE。为此,我两次执行以下 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 sheets 打开 csv 文件并将其作为 excel 文件保存回您的本地计算机。
与 Microsoft 相比,Google 已设法支持 UTF-8 csv 文件,因此只需在此处打开文件即可。并且导出为 excel 格式也可以。因此,尽管这可能不是所有人的首选解决方案,但它非常安全,并且点击次数并不像听起来那么高,尤其是当您已经登录谷歌时。
这并不能准确地解决问题,但是由于我偶然发现了这一点,并且上述解决方案对我不起作用或有我无法满足的要求,因此当您可以访问 vim 时,这是添加 BOM 的另一种方法:
vim -e -s +"set bomb|set encoding=utf-8|wq" filename.csv
嗨,我正在使用 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.write bom
f.write(csv_file)
Windows 和 Mac
文件可以直接双击打开。
Linux (ubuntu)
https://i.stack.imgur.com/KC1Zz.png
下载并安装 LibreOffice Calc 在 LibreOffice Calc 中打开您选择的 csv 文件 感谢上帝出现了导入文本向导... ...选择您的分隔符和字符编码选项 在 Calc 中选择生成的数据并复制粘贴到 Excel
几天前我遇到了同样的问题,但找不到任何解决方案,因为我无法使用 import from csv
功能,因为它将所有内容都设置为字符串。
我的解决方案是先用 notpad++ 和 change the encode to ASCII
打开文件。然后只需在 excel 中打开文件,它就可以按预期工作。
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);
这是一个老问题,但我刚刚遇到了类似的问题,解决方案可能对其他人有所帮助:
有同样的问题,将 CSV 文本数据写入文件,然后在 Excel 中打开生成的 .csv 将所有文本转移到单个列中。在阅读了上述答案后,我尝试了以下方法,这似乎解决了问题。
创建 StreamWriter 时应用 UTF-8 编码。而已。
例子:
using (StreamWriter output = new StreamWriter(outputFileName, false, Encoding.UTF8, 2 << 22)) {
/* ... do stuff .... */
output.Close();
}
Dispose
堆栈中看到了对 Close()
的调用,但我们开始了。您关于 CSV 导入是原始的说法也是不正确的,因为它不需要您建议的低效 HTML 方法。事实上,创建额外的编程步骤来获取纯文本数据、转换为 HTML 然后 拉入 Excel 似乎违反直觉
如果您想使其完全自动化、单击或从网页自动加载到 Excel 中,但无法生成正确的 Excel 文件,那么我建议您将 SYLK 格式作为替代方案。好的,它不像 CSV 那样简单,但它是基于文本的并且非常容易实现,并且它支持 UTF-8 没有任何问题。
我编写了一个 PHP 类,它接收数据并输出一个 SYLK 文件,只需单击该文件即可直接在 Excel 中打开(或者如果您将文件写入具有正确 mime 类型的网页,则会自动启动 Excel。您甚至可以添加格式(如粗体,以特定方式格式化数字等)并更改列大小或自动调整列大小到列中的文本,总而言之,代码可能不超过 100 行。
通过创建一个简单的电子表格并保存为 SYLK,然后使用文本编辑器读取它,对 SYLK 进行逆向工程非常容易。第一个块是您将识别的标题和标准数字格式(您只是在您创建的每个文件中反刍),然后数据只是一个 X/Y 坐标和一个值。
我正在从一个简单的 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。
我尝试了在此线程上可以找到的所有内容以及类似的内容,但没有任何效果。然而,导入谷歌表格并简单地下载为 csv 就像一个魅力。如果您遇到我的挫败感,请尝试一下。
现在是 2022 年 3 月,我们似乎不能同时使用 BOM 和 sep=... 行。添加 sep=\t 或类似的,使 Excel 忽略 BOM。
使用分号似乎是 Excel 理解的默认设置,在这种情况下,我们可以跳过 sep=... 行,它可以工作。
这是带有 Excel 版本 2110 内部版本 14527.20276 的 Microsoft 365。
首先将 Excel 电子表格保存为 Unicode 文本。使用 Internet Explorer 打开 TXT 文件并单击“另存为”TXT 编码 - 选择适当的编码,即 Win Cyrillic 1251
不定期副业成功案例分享