生成Excel的CSV文件,如何在值内部添加换行符

176

我需要生成一个Excel文件,其中一些值包含多行文本。

其中还有非英文文本,所以该文件必须是Unicode格式。

我现在生成的文件如下所示:(使用UTF8编码,包含非英文文本并且有许多行)

Header1,Header2,Header3
Value1,Value2,"Value3 Line1
Value3 Line2"

请注意,多行值用双引号括起来,并包含一个普通的日常换行符。

根据我在网上找到的信息,这应该有效,但实际上并不是这样,至少在Excel 2007和UTF8文件中不是这样。Excel将第三行视为数据的第二行,而不是第一行数据的第二行。

这必须在我的客户机上运行,我无法控制他们使用的Excel版本,因此我需要一种适用于Excel 2000及更高版本的解决方案。

谢谢。

编辑:我通过拥有两个CSV选项(一个用于Excel(Unicode、制表符分隔、字段中没有换行符),另一个用于其他地方(UTF8、标准CSV))“解决”了我的问题。

虽然不是我想要的,但至少它可以工作(到目前为止)。


1
FYI:这在LibreOffice中完美运行,在一开始导入CSV就容易得多。 - user2061057
11
现在您编辑了问题并去除了额外的空格,有关额外空格的被接受答案变得非常混乱... - Matti Virkkunen
19个回答

75

仅在空格字符是数据的一部分时,应将空格字符放在字段开头。Excel 不会去掉前导空格。这样会在标题和数据字段中产生不必要的空格。更糟糕的是,第三列中应该“保护”换行符的双引号将被忽略,因为它不在字段开头。

如果文件中有非 ASCII 字符(以 UTF-8 编码),则文件开头应该有一个 UTF-8 BOM(3 字节,hex EF BB BF)。否则,Excel 将按照您所在区域设置的默认编码(例如 cp1252)来解释数据,而不是 utf-8,您的非 ASCII 字符将被破坏。

以下评论适用于 Excel 2003、2007 和 2013;未在 Excel 2000 上测试过

如果您在 Windows Explorer 中双击文件名打开文件,则一切正常。

如果您在 Excel 中打开它,结果会有所不同:

  1. 文件中只有 ASCII 字符(没有 BOM):可以正常工作。
  2. 文件中有非 ASCII 字符(以 UTF-8 编码),并且在开头有一个 UTF-8 BOM:它识别出您的数据是以 UTF-8 编码的,但它会忽略 csv 扩展名,并把您带到“文本导入向导”,不幸的是,您会遇到换行符问题。

解决方案包括:

  1. 培训用户不要从 Excel 中打开文件 :-(
  2. 考虑直接编写 XLS 文件…有可用于 Python/Perl/PHP/.NET 等编程语言的包/库。

1
谢谢,我已经解决了问题中的前导空格,CSV示例是我手动输入的,而不是从真实文件复制粘贴的,真实文件不包含那些空格,你发现得很好。 - Nir
如果我想使用竖线作为字段分隔符,换行符作为记录分隔符,使用双引号保护文本字段的内容,并且文本字段可能包含 |," 和换行符。这种情况可行吗? - Giorgio
1
FYI:我有Excel2007和从Redmine系统导出的CSV文件。在开头添加UTF-8 BOM(EFBBBF)后,Excel完美地打开了该文件。嵌入“问题描述”列中的新行被正确处理,行结构未受损,并且所有国家字符都被正确读取(在没有UTF8 BOM的情况下读取时它们被破坏了)。 Excel甚至没有显示文本导入向导。目前,该CSV现在具有EFBBBF标题,使用0A作为行分隔符,以及0D0A作为文本单元格内部字符串的换行符。 - quetzalcoatl
1
如果您正在尝试让OS X上的Excel正确读取CSV文件,以及Windows上的Excel,这是一个很好的资源:https://dev59.com/H2855IYBdhLWcg3wbjvO - Alexandre R. Janini
在 macOS 上,在 UTF-8 编码的文件开头添加 BOM 标记就可以解决这个问题。现在 Excel 正确显示所有字符,换行也不再有问题了。非常感谢! - Lukas Petr
显示剩余2条评论

33

经过大量调试,以下是一个可行的配置方案,可以在Linux上生成文件,在Windows+Excel上读取,尽管嵌入式换行格式并不符合标准

  • 字段内部的换行符应该使用 \n (并且必须用双引号引起来)
  • 记录结束:\r\n
  • 确保不要以等号开头,否则它会被视为公式并被截断

在Perl中,我使用Text::CSV来实现这个功能,代码如下:

use Text::CSV;

open my $FO, ">:encoding(utf8)", $filename or die "Cannot create $filename: $!";
my $csv = Text::CSV->new({ binary => 1, eol => "\r\n" });

#for each row...:
$csv -> print ($FO, \@row);

5
是的,没错。我可以确认这适用于Windows+Excel、OSX+Numbers和Google Docs。 - Yorick Sijsling
3
在使用双引号包含的字段中使用“\n”(也尝试过“\r\n”)并使用“\r\n”分隔行,在Excel 2010中仍未解决我的问题。我已尝试使用ANSI和UTF8-with-BOM编码,但没有成功。 - nl-x
1
但这是因为我使用 | 作为字段分隔符。如果我使用 ; 作为字段分隔符,在导入 CSV 数据时问题仍然存在,但是在文件资源管理器中双击打开 CSV 文件时问题消失了。 - nl-x
3
Ian的答案在Windows 7上的Excel 2003/2010对我不起作用。我尝试使用十六进制编辑器编辑我的UTF-8 BOM文件,并从“0D0A”位(\r\n)中删除了0D(\r)以便在字段内换行。但它并没有起作用。 - Dan W
1
在Windows 8.1上的Excel 2013中对我无效。像@DanW一样使用十六进制编辑器将单元格中的换行符更改为0D,同时保留0D0A作为行分隔符。当我通过双击打开CSV文件或使用文本向导导入时,无论如何都会处理回车符不正确,并且文本会换到另一行。当然,整个字段都用双引号包装了。 - CodeManX
显示剩余3条评论

21

最近我也遇到了类似的问题,我通过导入一个HTML文件来解决它,基本示例如下:

<html xmlns:v="urn:schemas-microsoft-com:vml"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns="http://www.w3.org/TR/REC-html40">
  <head>
    <style>
      <!--
      br {mso-data-placement:same-cell;}
      -->
    </style>
  </head>
  <body>
    <table>
      <tr>
        <td>first line<br/>second line</td>
        <td style="white-space:normal">first line<br/>second line</td>
      </tr>
    </table>
  </body>
</html>

我知道它不是一个CSV文件,并且在各种版本的Excel中可能会有所不同,但我认为值得一试。

希望这能帮到你;-)


35
@GusDeCooL在第一句话中的措辞“我需要生成一个用于Excel的文件,该文件中的某些值包含多行。”表明它可能不需要是CSV文件。另外,问答格式也适用于其他读者,并且对于其中一些人来说可能是可行的选择(即使OP必须使用CSV)。我认为你的投票反对不合理(不过还是谢谢你解释原因)。 - dtldarek
1
这对我来说是最好的选择,谢谢你建议! - Jordan Gray

14
在 Excel 365 中导入文件时:
数据 -> 从文本/CSV: From Text/CSV -> 选择文件 -> 转换数据:

Select File -> Transform Data

在Power Query编辑器中,在“查询设置”下的右侧,在“已应用步骤”下,在“Source”行上,单击“设置图标”。

Source settings icon

-> 在换行符下拉菜单中选择“忽略引号内的换行符”。

Ignore quoted line breaks

然后按确定 -> 文件 -> 关闭并加载。

1
我很高兴我向下滚动找到了这个!我还添加了步骤的截图,并添加了英文Excel版本中的术语。 - Niko Pasanen
好的回答。很奇怪Excel默认没有使用这个。 - golimar

8
值得注意的是,当一个CSV文件中有用双引号包含的字段包含换行符时,在UTF-8格式下编写这个CSV文件时Excel无法正确地导入。Excel将回车换行视为新的一行,导致电子表格变得混乱不堪。即使使用分号作为字段分隔符也是如此。
可以通过使用Windows记事本编辑CSV文件并在保存文件之前将文件编码从UTF-8更改为ANSI来解决这个问题。一旦以ANSI格式保存文件,则我发现在运行Windows 7 Professional上的Microsoft Excel 2013中可以正确导入该文件。

7

如果您使用分号作为分隔符而不是逗号或制表符,并使用引号,那么在值内部添加换行符似乎有效。

这对我在Excel 2010和Excel 2000中都有效。但令人惊讶的是,只有当您将文件作为新电子表格打开时,而不是使用数据导入功能将其导入现有电子表格时,它才起作用。


是的,但我没有找到在Excel中使行末以分号结束的选项。 - GusDeCooL
1
如果一些实际文本数据包含分号怎么办?这样是行不通的。 - htm11h

4
在PC上,ASCII字符#10是您想要在值中放置换行符的字符。但是,在将其放入Excel中之后,您需要确保为多行单元格打开自动换行功能,否则换行符将显示为方框。

3

如果您尝试将文件导入EXCEL,则无法正常工作。

将csv文件扩展名与EXCEL.EXE相关联,这样您就可以通过双击csv文件来调用EXCEL。

在此,我插入一些文本,后跟换行符,然后再跟一些文本,并用双引号括起整个字符串。

不要使用CR,因为EXCEL会将字符串的一部分放在下一个单元格中。

""text" + NL + "text""

当您调用EXCEL时,您将看到如下内容。您可能需要自动调整高度才能看到所有内容,换行的位置将取决于单元格的宽度。
2
日期
以下是Basic代码。
CHR$(34,"2", 10,"DATE", 34)

2

测试一下: 这对我来说完全有效: 将以下内容放入xxxx.csv文件中

hola_x,="este es mi text1"&CHAR(10)&"I sigo escribiendo",hola_a

hola_y,="este es mi text2"&CHAR(10)&"I sigo escribiendo",hola_b

hola_z,="este es mi text3"&CHAR(10)&"I sigo escribiendo",hola_c

使用Excel打开。

在某些情况下,可能会直接打开,否则需要使用列到数据转换。扩展列宽并点击“自动换行”按钮,或格式化单元格并激活“自动换行”。

感谢其他的建议,但对我没有用。我在一个纯Windows环境中,不想玩Unicode或其他有趣的东西。

这样可以将CSV中的公式放入Excel中。这种工作方法可能有很多用途。(请注意引号前的等号)

附注:在您的建议中,请提供一些数据示例而不仅仅是代码。


这是唯一在 Excel 网页版上有效的解决方案。 - smörkex

2

我发现这个方法对我很有效

$delimiter = ',';
$enc1 = '"';
$enc2 = '""';

那么,在你需要将东西包裹起来的地方

$myfile = ('/path/to/myfile.csv');
//erase any previous contents
$fp = fopen($myfile, 'w+');
fwrite($fp, $enc1 .  'Column Heading 1' . $enc1 . $delimiter );
//append to new file
$fp2 = fopen($myfile, 'a');
fwrite($fp2, $enc1 .  'Column Heading 2' . $enc1 . $delimiter );

.....

fwrite($fp2, $enc1 .  'Last Column Heading' . $enc1 . $delimiter. PHP_EOL );

当您需要编写一些内容时 - 比如包含“”的HTML代码,您可以这样做

fwrite($fp2, $enc2 .  $myhtmlstring . $enc2 . $delimiter);

新行以. PHP_EOL结束。

脚本的结尾会打印一个链接,以便用户下载文件。

echo 'Click <a href="myfile.csv">here</a> to download file';

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