生成的 CSV 文件中的换行符让我很烦恼。

14
我试图导出一些数据(存储在一个datatable中)。其中一些值中间有换行符。但是,每当我尝试在Excel(2010)中导入文件时,换行符被识别为新行而不是实际的换行符。 我已经搜索了几个小时,看到了许多解决方案,但似乎都行不通。下面是我输出CSV文件的方式:(变量csvfile是一个stringbuilder)
context.Response.Clear();
context.Response.ContentType = "text/csv";
context.Response.ContentEncoding = System.Text.Encoding.UTF8;
context.Response.AppendHeader("Content-Disposition", "attachment; filename=" + name + ".csv");
context.Response.Write(csvfile.ToString());
context.Response.End();

我手动用Excel打开文件时,它显示正常。但因为Excel 2003不支持该文件格式,我必须导入它。在导入过程中,它将字段中的换行符(\n)视为新行。

很遗憾,我无法提供我正在处理的真实数据示例(这是所有个人数据),但我可以给你一个出错的示例:

Header1,Header2,Header3
"value1","value2","value 3
and this is where its going wrong"

这是一个简单的CSV文件,导入后你会看到出错的地方。我默认使用双引号来封装字段。我也默认删除值中的前导空格。

我已经花费至少两天时间解决这个看似简单的问题,但我真的搞不清楚该如何解决。我看到了多个关于相同问题的主题,但那里提供的解决方案似乎都不能解决这个问题。


你需要保留换行符吗? - Matt Ellen
1
是的,恐怕换行符对于数据非常重要。 - Melle Groenewoud
1
请查看此问题:https://dev59.com/-nM_5IYBdhLWcg3ww2AQ - Matt Ellen
6个回答

5
这对我有效:
a) 设置 Response.ContentEncoding = System.Text.Encoding.UTF8 并不足以使 Excel 正确打开 UTF-8 文件。相反,您必须手动为 Excel 文件编写字节顺序标记 (BOM) 头:
if (UseExcel2003Compatibility)
    {
        // write UTF-16 BOM, even though we export as utf-8. Wrong but *I think* the only thing Excel 2003 understands
        response.Write('\uFEFF');
    }
    else
    {
        // use the correct UTF-8 bom. Works in Excel 2008 and should be compatible to all other editors
        // capable of reading UTF-8 files
        byte[] bom = new byte[3];
        bom[0] = 0xEF;
        bom[1] = 0xBB;
        bom[2] = 0xBF;
        response.BinaryWrite(bom);
    }
b) 将文件作为八位字节流发送,使用带有 .csv 扩展名的文件名,并按照 HTTP 规范要求引用文件名:
response.ContentType = "application/octet-stream";
response.AppendHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");

c) 使用双引号包含所有字段

我刚刚检查了一下,对于我来说,Excel 可以正确地打开下载的文件,包括带有换行符的字段。

但请注意,Excel 在所有默认分隔符不是“,”的系统上仍无法正确打开此类 CSV 文件。例如,如果用户在设置为德国区域设置的 Windows 系统上运行 Excel,则 Excel 将无法正确打开该文件,因为它期望使用分号而不是逗号作为分隔符。我认为这方面无法做任何事情。


7
实际上是有这个功能的,但它非常难以发现。您可以在CSV文件的第一行写入以下内容: sep=, 这将使Excel使用相同的分隔符,而不考虑本地设置。 - Michael Böckling
1
@MichaelBöckling 先生,您真是救星!我一直在全球寻找一个简单的解决方案来解决这个问题。 - stormfield
谢谢,一旦我将内容类型从"text/csv"更改为"application/octet-stream",它就起作用了。 - Mat70x7

4

步骤1: 在需要换行的文本值处使用“\n”符号,如下所示。

字符串值 = "我不害怕那些练过1万种踢法的人,但我害怕那些练过1种踢法1万次的人。 \n";

步骤2: 使用扩展方法,它将检查文本索引以打破文本值。

public static class ExtensionMethods
{
    static char[] SpecialCharacters = new char[] { ',', '"', '\r', '\n' };
    public static string ToWrap(this string val)
    {
        StringBuilder builder = new StringBuilder();
        bool firstColumn = true;

        // Add separator if this isn't the first value
        if (!firstColumn)
            builder.Append(',');
        // Implement special handling for values that contain comma or quote
        // Enclose in quotes and double up any double quotes
        if (val.IndexOfAny(SpecialCharacters) != -1)
            builder.AppendFormat("\"{0}\"", val.Replace("\"", "\"\""));
        else
            builder.Append(val);
        firstColumn = false;

        return builder.ToString();
    }
}

第三步: 创建扩展方法后,将其用于字符串变量中,以包装文本值。
Value.ToWrap();

2
只要字段被正确地双引号引用,CSV文件中允许有换行符。问题似乎在于如何使Excel正确导入记录。此前在该网站上已经提出过这个问题,有几种可能的解决方案:
1. 将输出文件的编码设置为ASCII或UTF-8。由于您在问题中将其设置为UTF-8,请尝试使用ASCII。(链接) 2. 将文件名更改为.csv,这可能会欺骗Excel以正确导入文件。(链接)

很抱歉,我也尝试了ASCII编码,但没有结果。我知道这个问题之前已经被问过,甚至多次。我已经阅读并尝试了每一个解决方案,但由于某种原因它就是无法正确导入。 - Melle Groenewoud

0

我认为在CSV字段中不能有换行符,因为换行符表示新记录。您可以在将字段值添加到字符串之前替换所有换行符吗?或者您可以构建一个Excel文件,它们应该允许字段中的换行符。


8
CSV文件中允许在字段中有换行符。 - Factor Mystic

0

包含BOM的UTF文件会导致Excel即使在该字段被引号包围时也会将新行视为字面意义。 (已测试Excel 2008 Mac)

解决方案是将任何新行变成回车(CHR 13),而不是换行符。


0

我曾经遇到过同样的问题。在浏览这篇博客中的“使用适当格式导出到Excel”一节时,我找到了解决方案。

我按照以下方式修改了我的代码:

string brstyle = @"<style>br { mso-data-placement:same-cell; }</style>";

Response.Write(brstyle);

Response.Write(stringWriter.ToString());

它对我有效。现在,换行符文本显示为单个单元格,而不是每个换行符(行)都有一个新单元格。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接