如何阻止Excel吃掉我美味的CSV文件并排除无用的数据?


128

我有一个数据库,该数据库按序列号跟踪小部件的销售。用户输入购买者数据和数量,然后将每个小部件扫描到自定义客户端程序中。然后,他们确定订单。所有这些都完美无缺。

一些客户想要购买的小部件的Excel兼容电子表格。我们使用PHP脚本生成此文件,该脚本查询数据库并以CSV格式输出结果以及商店名称和相关数据。这也很好。

在记事本或vi等文本编辑器中打开文件时,该文件如下所示:

"Account Number","Store Name","S1","S2","S3","Widget Type","Date"
"4173","SpeedyCorp","268435459705526269","","268435459705526269","848 Model Widget","2011-01-17"

如您所见,序列号存在(在这种情况下为两次,并非所有辅助序列号都相同),并且是一长串数字。在Excel中打开此文件时,结果变为:

Account Number  Store Name  S1  S2  S3  Widget Type Date 
4173    SpeedyCorp  2.68435E+17     2.68435E+17 848 Model Widget    2011-01-17

如您所见,序列号用双引号引起来。Excel似乎不尊重.csv文件中的文本限定符。将这些文件导入Access时,难度为零。以文本形式打开它们时,一点也​​不麻烦。但是Excel一定会将这些文件转换成无用的垃圾。可以说,试图指导最终用户使用非默认应用程序打开CSV文件的技术已经变得很烦人。有希望吗?是否有我找不到的设置?Excel 2003、2007和2010似乎就是这种情况。


46
我可以给名字加+1吗?
tombull89 '01

11
Excel does not seem to respect text qualifiers in .csv files-双引号不是文本限定符,它们只是在数据中使用逗号,如果您在数据中不使用逗号,则它们是没有意义的。CSV文件中的所有数据都是无类型的,因此Excel只能猜测您的大序列号是一个数字,也就是说,当您以Excel的15位数字的最大精度运行时,这就是将数字截断的原因。
DMA57361 2011年

1
Excel似乎不尊重双引号中的所有逗号。考虑“ 2012年8月12日”,Excel也将其转换为垃圾。
zundarz 2012年

5
我想提一下这个SU问题。它说明了在Excel中处理CSV时具有哪些选项。
nixda

1
@nixda谢谢!这些都是有用的建议,尤其对于经验丰富的用户。我的问题几乎更多是人为问题,因为Excel将自身与.csv文件相关联,人们看到了该图标,然后双击(因为这是打开方式),然后通常单击Save(因为我们一直在告诉他们保存!),一切都丢失了。但是,我会尽可能使用您的方法。
13年

Answers:


58

但是Excel一定会将这些文件转换成无用的垃圾。

Excel是无用的垃圾。

如果任何希望您使用Excel格式的数据的客户端都无法将这三列的可见格式更改为小数点后零位的“数字”或“文本”,我会感到有些惊讶。但是,让我们假设没有简短的操作文档。

您的选择是:

  1. 将非数字字符而不是空格字符插入序列号。
  2. 用某种默认格式写出xls文件或xlsx文件。
  3. 作弊并将这些数字作为公式输出="268435459705526269","",="268435459705526269"(您也可以="268435459705526269",,="268435459705526269"节省2个字符)。这样的优点是可以正确显示,并且可能通常有用,但会被巧妙地破坏(因为它们是公式)。

选项3请小心,因为某些程序(包括Excel和Open Office Calc)将不再将=""字段内的逗号视为转义符。这意味着="abc,xyz"将跨越两列并中断导入。

使用"=""abc,xy"""解决方案的格式可以解决此问题,但是由于Excel的公式长度限制,此方法仍将您限制为255个字符。


1
实际上,这并不苛刻。将上述数字之一复制并粘贴到Excel中,然后根据建议更改数字格式。Excel更改该值,导致垃圾。
Joe Internet,

1
@Joe,我对最初的概述太粗心了。Excel确实在产生垃圾,并且本身就是垃圾。我已经更新了答案以反映这一点。一个选择可能是拥有“ Excel csv”,也可能具有“可用的,有价值的csv”
Tyler

2
@Tyler-我不认为Excel是垃圾,只是说OP在这种情况下会产生垃圾是正确的。这实际上是一个很好的问题,没有看似优雅的解决方案。
Joe Internet,

1
建议使用“单元格格式...”选项,而我尝试使用它。在这种情况下,打开文件的那一刻,Excel似乎会将序列转换为科学计数法(同意的,不是意外的)并丢掉了精度。当您将它们更改为数字或文本时,字符串不会返回。 确实是问题的实质。输出为公式可以做到这一点……我没想到。
2011年

9
@ DMA57361该行为是无法预期的,可以确定。数值精度已得到很好的证明,但excel如何读取CSV却没有。缺乏警告和默默丢弃数据是荒谬的。您甚至不能告诉Excel如何导入数据的事实同样荒谬。需要否定性吗?不,但是诚实是最好的政策,这就是我的感受。
泰勒

42

我们有一个类似的问题,即我们的CSV文件的列包含诸如3-5的范围,而Excel总是将其转换为日期,例如3-5将是3月3日,此后切换回数字会给我们一个无用的日期整数。我们绕过它

  1. 将CSV重命名为TXT扩展名
  2. 然后,当我们在Excel中打开它时,它将在文本导入向导中启动
  3. 在向导的第3步(共3步)中,我们告诉它所涉及的列是文本,并且已正确导入。

我想您可以在这里做同样的事情。

文字汇入精灵

干杯


2
+1是正确的做法。(编辑:抱歉,您必须进行一点点编辑才能阐明解决方案)
jay 2012年

2
您不必重命名文件。只需使用导入向导Shift-选择所有列,然后选择作为文本即可。
nixda

1
文本导入向导就是答案。所有其他解决方案都是不必要的黑客,因为他们不了解如何使用Excel查看和编辑CSV。
Excellll 2014年

1
@Excellll,确保一次执行一个文件。在自动执行此过程时,“不必要的黑客”通常可以节省时间。
Parrish Husband'Mar

1
当标准用户使用excel显示CSV文件时,这是完全没有用的。在尝试向约15个初学技能的办公室用户解释如何使用text-import-wizard之前,我宁愿自己输入excel文档源代码。
northkildonan

8

更好的解决方案是生成XML工作簿。像这样:

<?xml version="1.0" encoding="UTF-8"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet" xmlns:c="urn:schemas-microsoft-com:office:component:spreadsheet" xmlns:html="http://www.w3.org/TR/REC-html40" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet" xmlns:x2="http://schemas.microsoft.com/office/excel/2003/xml" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">
  </OfficeDocumentSettings>

  <ss:Worksheet ss:Name="Sheet 1">
    <Table>
    <Column ss:Width="100"/>
    <Column ss:Width="100"/>
    <Column ss:Width="150"/>
    <Column ss:Width="150"/>
    <Column ss:Width="150"/>
    <Column ss:Width="150"/>
    <Column ss:Width="80"/>
    <Column/>

    <Row>
      <Cell><Data ss:Type="String">Account Number</Data></Cell>
      <Cell><Data ss:Type="String">Store Name</Data></Cell>
      <Cell><Data ss:Type="String">S1</Data></Cell>
      <Cell><Data ss:Type="String">S2</Data></Cell>
      <Cell><Data ss:Type="String">S3</Data></Cell>
      <Cell><Data ss:Type="String">Widget Type</Data></Cell>
      <Cell><Data ss:Type="String">Date</Data></Cell>
    </Row>

    <Row>
      <Cell><Data ss:Type="String">4173</Data></Cell>
      <Cell><Data ss:Type="String">SpeedyCorp</Data></Cell>
      <Cell><Data ss:Type="String">268435459705526269</Data></Cell>
      <Cell><Data ss:Type="String">x</Data></Cell>
      <Cell><Data ss:Type="String">268435459705526269</Data></Cell>
      <Cell><Data ss:Type="String">848 Model Widget</Data></Cell>
      <Cell><Data ss:Type="String">2011-01-17</Data></Cell>
    </Row>


    </Table>
    <x:WorksheetOptions/>
  </ss:Worksheet>
</Workbook>

该文件必须具有.xml扩展名。Excel和OpenOffice可以正确打开它。


您是说OP应该使用PHP脚本将数据库转换为XML格式吗?
Prasanna

2
比让用户在Excel中打开.csv或弄乱您的CSV更加干净,这样只有Excel才能理解您的CSV。它甚至没有架构那么复杂。
宾基

该标准在哪里记录?我想进一步了解可用的数据类型。
John Doherty

1

我的解决方案:导入序列号时遇到相同的问题。它们不必视为数字,即没有对其执行任何数学函数,但我们需要其中的整个数字。我最简单的事情是在序列号中插入一个空格。例如“ 12345678 90123456 1234”。Excel导入时,它将被视为文本而不是数字。


0

我的帐号长了乱码。

这是我解决的方法:

在Libre Office / Open Office中打开file.csv(可能需要指定定界符等),然后将文件另存为Excel XML文件。

然后在Excel中打开此文件,然后您将看到列不再更改为科学格式或其他格式。为了安全起见,右键单击该列,然后将格式明确设置为“文本”,然后另存为Excel文件格式。

打开Excel格式文件,该列仍然应该可以!


1
虽然这工作,试图解释给别人谁讲只有蹩脚的英语,为什么他会需要使用不同的办公套件创建,因为它只是解决了许多问题。我个人认为,M $ Office的替代软件非常不错,但我意识到我无法转换所有人。
13年

0

对于临时用户和一次性情况,导入向导是最佳解决方案。如果需要编程解决方案,则可以使用QueryTables.Add方法(这是导入向导在后台使用的方法)。

Workbooks.Add
With ActiveSheet.QueryTables.Add(Connection:="TEXT;" & "C:\myfile.csv", Destination:=Range("$A$1"))
    .FieldNames = True
    .RowNumbers = False
    .FillAdjacentFormulas = False
    .PreserveFormatting = True
    .RefreshOnFileOpen = False
    .RefreshStyle = xlInsertDeleteCells
    .SavePassword = False
    .SaveData = True
    .AdjustColumnWidth = True
    .RefreshPeriod = 0
    .TextFilePromptOnRefresh = False
    .TextFilePlatform = 437
    .TextFileStartRow = 1
    .TextFileParseType = xlDelimited
    .TextFileTextQualifier = xlTextQualifierDoubleQuote
    .TextFileConsecutiveDelimiter = False
    .TextFileTabDelimiter = False
    .TextFileSemicolonDelimiter = False
    .TextFileCommaDelimiter = True
    .TextFileSpaceDelimiter = False
    .TextFileColumnDataTypes = Array(1, 2, 2) 'Edit this line. Add a number for each column, 1 is general, 2 is text. Search the internet for other formats.
    .TextFileTrailingMinusNumbers = True
    .Refresh BackgroundQuery:=False
End With
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.