我正在开发一个应用程序的一部分,负责将一些数据导出到CSV文件中。该应用程序始终使用UTF-8,因为它在各个层面都具有多语言特性。但是在Excel中打开此类CSV文件(包含例如变音符号,西里尔字母,希腊字母)并未达到Г„/Г¤, Г–/Г¶
之类的预期结果。而且我不知道如何强制Excel理解打开的CSV文件是用UTF-8编码的。我也尝试过指定UTF-8 BOM EF BB BF
,但Excel会忽略它。
有解决方法吗?
P.S。哪些工具可能像Excel一样?
更新
我不得不说我把社区与问题的表述混为一谈。当我提出这个问题的时候,我想要一种在Excel中打开UTF-8 CSV文件的方法,而不会给用户带来任何问题,而且流畅透明。但是,我使用了一个错误的公式,要求自动执行 。这非常令人困惑,它与VBA宏自动化发生冲突。这个问题有两个答案我最欣赏:Alex https://stackoverflow.com/a/6002338/166589的第一个答案,我接受了这个答案;马克https://stackoverflow.com/a/6488070/166589的第二个出现了一会儿。从可用性的角度来看,Excel似乎缺乏一个良好的用户友好型UTF-8 CSV支持,所以我认为两个答案都是正确的,我已经接受了Alex的答案,因为它真的说明了Excel无法透明地执行此操作。这就是我在这里与自动混淆的原因。 Mark的答案为更高级的用户提供了一种更复杂的方式来实现预期的结果。这两个答案都很棒,但亚历克斯的答案更符合我未明确指出的问题。
更新2
在最后一次编辑五个月后,我注意到Alex的答案因某种原因消失了。我真的希望这不是一个技术问题,我希望现在不再讨论哪个答案更大。所以我接受马克的答案是最好的答案。
答案 0 :(得分:354)
Alex是正确的,但是当您必须导出到csv时,您可以在打开csv文件时向用户提供此建议:
这样特殊字符应该正确显示。
答案 1 :(得分:130)
UTF-8字节顺序标记将提示Excel 2007+使用UTF-8。 (见this SO post)。
如果有人遇到同样的问题,.NET的UTF8编码类不会在GetBytes()
调用中输出字节顺序标记。您需要use streams(或使用a workaround)来输出BOM。
答案 2 :(得分:65)
对于Excel 2013,似乎修复了忽略BOM的错误。我对西里尔字母有同样的问题,但添加BOM字符\uFEFF
确实有帮助。
答案 3 :(得分:40)
令人难以置信的是,有很多答案,但没有人回答这个问题:
"当我问这个问题时,我问了一种打开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存在数十年。遗憾的是,这些年来微软无法实现CSV导入这样的基本功能。
但是,如果您将相同的值放入HTML文件并将该文件保存为带文件扩展名为 XLS 的BOM的UTF8文件,您将获得正确的结果。
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>
此代码甚至允许指定工作表的名称(此处为&#34; MySuperSheet&#34;)
Excel 2007中的结果:
答案 4 :(得分:36)
我们已经使用了这种解决方法:
答案 5 :(得分:17)
PHP生成的CSV文件存在同样的问题。
当在内容开头通过"sep=,\n"
定义分隔符时,Excel忽略了BOM(但当然是在BOM之后)。
因此,在内容的开头添加BOM("\xEF\xBB\xBF"
)并通过fputcsv($fh, $data_array, ";");
将分号设置为分隔符就可以了。
答案 6 :(得分:11)
老问题但是,最简单的解决方案是:
答案 7 :(得分:10)
我过去遇到过同样的问题(如何生成Excel可以阅读的文件,其他工具也可以阅读)。我使用的是TSV而不是CSV,但编码的问题也出现了。
我没有找到任何方法让Excel自动识别UTF-8,而且我不愿意/能够对文件的消费者造成如何打开它们的复杂指令。所以我将它们编码为UTF-16le(带有BOM)而不是UTF-8。两倍大小,但Excel可以识别编码。而且它们压缩得很好,所以尺寸很少(但遗憾的是从来没有)很重要。
答案 8 :(得分:6)
我发布在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中打开它。
答案 9 :(得分:4)
您可以通过记事本++使用BOM将.csv文件转换为UTF-8:
Encoding
→Convert to UTF-8
。File
→Save
。在Windows 8.1上的Microsoft Office 2013 Plus的Microsoft Excel 2013(15.0.5093.1000)MSO(15.0.5101.1000)中工作,并且将非Unicode程序的区域设置设置为“德语(德国)”。
答案 10 :(得分:3)
这是一个老问题,但在搜索顶部出现。经过多次努力,我发现在csv文件开头添加BOM字符会有所帮助。
我在这里简要介绍了一下:https://sites.google.com/site/ritechtips/home/the-multi-line-fields-csv-file-and-excel-import---ha
答案 11 :(得分:2)
仅仅是为了帮助那些有兴趣在Excel上打开文件的用户,就像我一样。
我使用了下面的向导,它对我来说很好,导入了一个UTF-8文件。 不透明,但如果您已有文件,则非常有用。
来源:https://www.itg.ias.edu/content/how-import-csv-file-uses-utf-8-character-encoding-0
答案 12 :(得分:2)
用于打开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。 逗号:对于以colums分发的.csv文件为真
将其保存在Personal.xlsb中以使其始终可用。 个性化Excel工具栏添加宏调用按钮并从那里打开文件。 您可以为宏添加更多格式,例如列自动调整,对齐等。
答案 13 :(得分:1)
这是我的工作解决方案:
vbFILEOPEN = "your_utf8_file.csv"
Workbooks.OpenText Filename:=vbFILEOPEN, DataType:=xlDelimited, Semicolon:=True, Local:=True, Origin:=65001
关键是Origin:= 65001
答案 14 :(得分:1)
是的,这是可能的。在编写创建csv的流时,首先要做的是:
myStream.Write(Encoding.UTF8.GetPreamble(), 0, Encoding.UTF8.GetPreamble().Length)
答案 15 :(得分:1)
是的,这是可能的。正如之前多个用户所指出的,当文件以UTF-8编码时,excel读取正确的字节顺序标记似乎存在问题。使用UTF-16似乎没有问题,因此它是UTF-8的特有种。我用于此的解决方案是添加BOM,TWICE。为此,我执行以下sed命令两次:
sed -I '1s/^/\xef\xbb\xbf/' *.csv
,其中通配符可以替换为任何文件名。但是,这会导致.csv文件开头的sep =突变。然后.csv文件将在excel中正常打开,但是带有一个额外的行&#34; sep =&#34;在第一个细胞中。 &#34; sep =&#34;也可以在源.csv本身中删除,但在使用VBA打开文件时,应指定分隔符:
Workbooks.Open(name, Format:=6, Delimiter:=";", Local:=True)
格式6是.csv格式。如果文件中有日期,则将Local设置为true。如果Local未设置为true,则日期将为美国化,这在某些情况下会破坏.csv格式。
答案 16 :(得分:1)
一个真正令人惊叹的答案列表,但由于一个相当不错的答案仍然缺失,我在这里提到它:用google sheets打开csv文件并将其作为excel保存回本地计算机文件。
与微软相比,Google已成功支持UTF-8 csv文件,因此只需在那里打开文件即可。导出到excel格式也是有效的。因此,即使这可能不是所有人的首选解决方案,但它非常安全,并且点击次数不会听起来那么高,尤其是当您已经登录谷歌时。
答案 17 :(得分:1)
这不能准确地解决这个问题,但由于我偶然发现了上述解决方案并没有为我工作或者有我无法满足的要求,这里有另一种方法来添加BOM。访问vim:
vim -e -s +"set bomb|set encoding=utf-8|wq" filename.csv
答案 18 :(得分:1)
嗨,我在使用Ruby进行csv生成。在我们的应用程序中,我们计划使用多语言(I18n),并且在Windows Excel的CSV文件中查看I18n内容时遇到一个问题。
在Linux(Ubuntu)和Mac上都可以。
我们确定Windows excel需要再次导入数据以查看实际数据。导入时,我们将获得更多选择字符集的选项。
但这并不是每个用户都可以接受的,所以我们寻找的解决方案是双击打开。
然后,在aghuddleston gist的帮助下,我们确定了在Windows excel中通过打开模式和Bom显示数据的方式。在引用处添加。
示例I18n内容
在Mac和Linux中
瑞典语:弗南姆 英语:名字
在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)
答案 19 :(得分:0)
在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
答案 20 :(得分:0)
几天前,我遇到了同样的问题,但是找不到任何解决方案,因为我无法使用import from csv
功能,因为它使所有内容都被设置为字符串样式。
我的解决方案是首先使用notpad ++和change the encode to ASCII
打开文件。
然后只需在excel中打开该文件,即可按预期工作。
答案 21 :(得分:0)
Office 365的工作解决方案
UTF-16
(比利时,不设LE)\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);
答案 22 :(得分:0)
我尝试了在此线程上可以找到的所有东西,类似的东西,没有完全起作用。但是,导入到Google表格中并简单地以csv格式下载就像一个魅力。如果您遇到我的挫败点,请尝试一下。
答案 23 :(得分:0)
如果你想让它完全自动化,只需点击一下,或者从网页自动加载到Excel中,但无法生成正确的Excel文件,那么我建议将SYLK格式作为替代方案。好吧,它不像CSV那么简单,但它是基于文本的,非常容易实现,它支持UTF-8没有问题。
我编写了一个PHP类,它接收数据并输出一个SYLK文件,只需单击该文件即可直接在Excel中打开(如果将文件写入具有正确mime类型的网页,则会自动启动Excel。您甚至可以添加格式(如粗体,格式数字以特定方式等)并更改列大小或自动调整列到列中的文本,并且所有代码中的所有代码都可能不超过大约100行。
通过创建一个简单的电子表格并保存为SYLK然后使用文本编辑器读取它,可以轻松地对SYLK进行逆向工程。第一个块是您将识别的标题和标准数字格式(您只是在您创建的每个文件中反刍),然后数据只是一个X / Y坐标和一个值。
答案 24 :(得分:0)
我正在从一个简单的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。
答案 25 :(得分:0)
答案 26 :(得分:0)
这是一个老问题,但我刚刚遇到类似的问题,解决方案可能会帮助其他人:
将CSV文本数据写入文件时出现同样的问题,然后在Excel中打开生成的.csv会将所有文本转换为单个列。在阅读了上述答案后,我尝试了以下内容,这似乎可以解决问题。
创建StreamWriter时应用UTF-8编码。就是这样。
示例:
using (StreamWriter output = new StreamWriter(outputFileName, false, Encoding.UTF8, 2 << 22)) {
/* ... do stuff .... */
output.Close();
}
答案 27 :(得分:-1)
首先将Excel电子表格另存为Unicode文本。使用Internet Explorer打开TXT文件,然后单击“另存为”TXT编码 - 选择适当的编码,即Win Cyrillic 1251