【问题标题】:Excel comparing two csv files and showing the differenceExcel比较两个csv文件并显示差异
【发布时间】:2011-05-31 18:14:55
【问题描述】:

我希望比较两组 csv 文件和/或一个 csv 文件和一个 .txt 文件。为了简单起见,我“认为” .txt 文件可能需要转换为 csv 文件,但这可能需要也可能不需要。我要么想使用 excel、c++ 或 python。我需要将一个“已接受”值列表与一个已测量的列表进行比较,并找出它们之间的差异(如果有的话)。 Excel 可能是最简单的方法,但 python 或 c++ 也可以。这不是家庭作业,所以不要担心那种事情。非常感谢代码建议和/或模板。或网站链接

编辑 1

我读过 Python 的 difflib 或不同的类,但不熟悉如何使用它,可能比我想要的要多。

编辑 2

文件都有一系列列(它们之间没有画线或任何东西),在这些“命名”列下方会有数字。我需要将文件一中第 1 列中的数字与文件 2 中第 1 列中的数字进行比较,如果有差异,请显示另一个 csv 文件中的差异

【问题讨论】:

  • 我想我会将所有内容都转换为 CSV 文件(类似pypi.python.org/pypi/xlrd/0.5.2 会有所帮助)并比较 CSV。使用 CSV 作为与应用程序和平台无关的公分母
  • 在没有更多信息的情况下回答有点棘手 - 您能解释一下文件中数据的布局方式吗?
  • 每列下 5 列中的每一列的标题都有数字,我需要将 5 列下的每个数字与不同文件中同一位置的数字进行比较,如果存在差异是一个
  • "我想使用 excel、c++ 或 python" 哎呀,这确实缩小了范围。选择一个。
  • @ildjarn 如果您对我的问题的回答没有什么要补充的,请远离我,我这样做是为了吸引来自其他编程背景的人。你忘了抱怨我也标记了 python、c++ 和 excel

标签: c++ python excel compare


【解决方案1】:

您可以使用 ADO(ODBC/JET/OLEDB 文本驱动程序)将“体面”的 .txt/.csv/.tab/.flr 文件视为 SQL 数据库中每种支持 COM 语言的表。然后可以使用 SQL 的强大功能进行比较(DISTINCT、GROUP、(LEFT) JOINS、...)。

添加了关于您的评论:

这是你的问题,我不想把你推到你不想去的地方。但是如果您需要比较表格数据,SQL 是一个很好的(最好的?)工具。作为发现两个 .txt 文件中差异的脚本输出的证据:

======= The .txt files to play with
------- file1.txt
"AC";"AM"
40000;-19083,00
40100;20000,00
40200;350004,00
40300;3498,99

------- file2.txt
"AC";"AM"
40000;-19083,00
40300;3498,99
40105;-234567,00
40200;350,00

======= Some diagnostic SQL
------- <NULL> indicates: In F1 but not in F2 (LEFT JOIN)
SELECT T1.AC, T1.AM, T2.AM FROM [file1.txt] AS T1 LEFT JOIN [file2.txt] AS T2 ON (T1.AC =
T2.AC)
------- Result
AC      File1   File2
40000   -19083  -19083
40100   20000   <NULL>
40200   350004  350
40300   3498,99 3498,99

------- <NULL> indicates: Not in the other file (LEFT JOIN, UNION)
SELECT T1.AC, T1.AM, T2.AM FROM [file1.txt] AS T1 LEFT JOIN [file2.txt] AS T2 ON (T1.AC =
T2.AC) UNION SELECT T2.AC, T1.AM, T2.AM FROM [file2.txt] AS T2 LEFT JOIN [file1.txt] AS T1
 ON (T1.AC = T2.AC)
------- Result
AC      File1   File2
40000   -19083  -19083
40100   20000   <NULL>
40105   <NULL>  -234567
40200   350004  350
40300   3498,99 3498,99

------- the problems: missing, different values
SELECT T1.AC, T1.AM, T2.AM FROM [file1.txt] AS T1 LEFT JOIN [file2.txt] AS T2 ON (T1.AC =
T2.AC) WHERE T2.AM IS NULL OR T1.AM <> T2.AM UNION SELECT T2.AC, T1.AM, T2.AM FROM [file2.
txt] AS T2 LEFT JOIN [file1.txt] AS T1 ON (T1.AC = T2.AC) WHERE T1.AM IS NULL OR T1.AM <>
T2.AM
------- Result
AC      File1   File2
40100   20000   <NULL>
40105   <NULL>  -234567
40200   350004  350

进一步补充:

这个article 处理ADO 和文本文件;查找文件 adoNNN.chm (NNN=版本号,例如 210)在您的计算机上;这是good book 关于 ADO。

您可以使用 Access 或 OpenOffice Base 来试验 SQL 语句 应用于链接/引用(未导入!)文本数据库。

在您掌握了最初的障碍后,脚本/程序将变得很容易:连接 到数据库,即到包含文件和 schema.ini 的文件夹 文件来定义 files=tables 的结构。

上面的输出是由以下生成的:

  Const adClipString = 2

  Dim oFS  : Set oFS = CreateObject( "Scripting.FileSystemObject" )
  Dim sDir : sDir    = oFS.GetAbsolutePathName( ".\txt" )
  Dim oDB  : Set oDb = CreateObject( "ADODB.Connection" )
  oDB.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & sDir & ";Extended Properties=""text"""
  Dim sSQL
  Dim sFiNa
  WScript.Echo "=======", "The .txt files to play with"
  For Each sFiNa In Array( "file1.txt", "file2.txt"  )
      WScript.Echo "-------", sFiNa
      WScript.Echo oFS.OpenTextFile( "txt\" & sFiNa ).ReadAll()
  Next

  WScript.Echo "=======", "Some diagnostic SQL"
  Dim aSQL
  For Each aSQL In Array( _
       Array(   "<NULL> indicates: In F1 but not in F2 (LEFT JOIN)" _
              , Join( Array( _
                     "SELECT T1.AC, T1.AM, T2.AM FROM" _
                   , "[file1.txt] AS T1" _
                   , "LEFT JOIN [file2.txt] AS T2 ON (T1.AC = T2.AC)" _
                ), " " ) ) _
     , Array(   "<NULL> indicates: Not in the other file (LEFT JOIN, UNION)" _
              , Join( Array( _
                     "SELECT T1.AC, T1.AM, T2.AM FROM" _
                   , "[file1.txt] AS T1" _
                   , "LEFT JOIN [file2.txt] AS T2 ON (T1.AC = T2.AC)" _
                   , "UNION" _
                   , "SELECT T2.AC, T1.AM, T2.AM FROM" _
                   , "[file2.txt] AS T2" _
                   , "LEFT JOIN [file1.txt] AS T1 ON (T1.AC = T2.AC)" _
                ), " " ) ) _
     , Array(   "the problems: missing, different value" _
              , Join( Array( _
                     "SELECT T1.AC, T1.AM, T2.AM FROM" _
                   , "[file1.txt] AS T1" _
                   , "LEFT JOIN [file2.txt] AS T2 ON (T1.AC = T2.AC)" _
                   , "WHERE T2.AM IS NULL OR T1.AM <> T2.AM" _
                   , "UNION" _
                   , "SELECT T2.AC, T1.AM, T2.AM FROM" _
                   , "[file2.txt] AS T2" _
                   , "LEFT JOIN [file1.txt] AS T1 ON (T1.AC = T2.AC)" _
                   , "WHERE T1.AM IS NULL OR T1.AM <> T2.AM" _
                ), " " ) ) _
     )
     sSQL = aSQL( 1 )
     WScript.Echo "-------", aSQL( 0 )
     WScript.Echo sSQL
     Dim oRS : Set oRS = oDB.Execute( sSQL )
     WScript.Echo "------- Result"
     WScript.Echo Join( Array( "AC", "File1", "File2" ), vbTab )
     WScript.Echo oRS.GetString( adClipString, , vbTab, vbCrLf, "<NULL>" )
  Next
  oDB.Close

如果你删除/忽略胖子(创建 SQL 语句、诊断输出),它就会沸腾 最多 6 行

  Dim oDB  : Set oDb = CreateObject( "ADODB.Connection" )
  oDB.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & sDir & ";Extended Properties=""text"""
  sSQL = "..."
  Dim oRS : Set oRS = oDB.Execute( sSQL )
  WScript.Echo oRS.GetString( adClipString, , vbTab, vbCrLf, "<NULL>" )
  oDB.Close

它可以很容易地“移植”到每一种支持 COM 的语言,因为 ADO 物体完成所有繁重的工作。 .GetString 方法很方便,当你 想要保存结果集:只需旋转分隔符/分隔符/Null 参数 并将其转储到文件中

  oFS.CreateTextFile( ... ).WriteLine oRS.GetString( _
    adClipString, , ",", vbCrLf, ""
  )

(不要忘记将该表的定义添加到您的 schema.ini)。的 当然你也可以使用“SELECT/INSERT INTO”,但这样的语句可能不会 易于正确/通过 ADO 文本驱动程序的解析器。

加法 wrt 计算:

从一个 5 x 2 主/批准文件开始,其中包含:

Num0    Num1    Num2    Num3    Num4
7,6     6,1     3,8     0,9     8,9
0,9     9,4     4,7     8,8     9,9

将其转换为expected.txt

Num0    Num1    Num2    Num3    Num4    Spot
7,6     6,1     3,8     0,9     8,9     1
0,9     9,4     4,7     8,8     9,9     2

通过附加 Spot 列使其符合

[expected.txt]
ColNameHeader=True
CharacterSet=1252
Format=Delimited(;)
Col1=Num0 Float
Col2=Num1 Float
Col3=Num2 Float
Col4=Num3 Float
Col5=Num4 Float
Col6=Spot Integer

在您的 schema.ini 文件中。同样,转换一个测量文件,如:

Num0    Num1    Num2    Num3    Num4
7,1     1,1     3,8     0,9     8,9
0,9     9,4     4,7     8,8     9,9

到measured.txt

Num0    Num1    Num2    Num3    Num4    Spot
7,1     1,1     3,8     0,9     8,9     1
0,9     9,4     4,7     8,8     9,9     2

申请

  sSQL = Join( Array( _
         "SELECT E.Num0 - M.Num0 AS Dif0" _
      ,       ", E.Num1 - M.Num1 AS Dif1" _
      ,       ", E.Num2 - M.Num2 AS Dif2" _
      ,       ", E.Num3 - M.Num3 AS Dif3" _
      ,       ", E.Num4 - M.Num4 AS Dif4" _
      ,       ", E.Spot          AS Spot" _
      ,  "FROM [expected.txt] AS E" _
      ,  "INNER JOIN [measured.txt] AS M" _
      ,  "ON E.Spot = M.Spot" _
  ), " " )

将结果集写入differences.txt

aFNames = Array("Num0", ... "Spot" ) oFS.CreateTextFile(sFSpec).Write _ Join( aFNames, sFSep ) & sRSep & oRS.GetString( adClipString, , sFSep, sRSep, "" )

你会得到:

Num0    Num1    Num2    Num3    Num4    Spot
0,5     5       0       0       0       1
0       0       0       0       0       2

【讨论】:

  • 我没有问 SQL 对不起:s
  • 酷,这是一个巧妙的技巧!您使用什么作为诊断 SQL 控制台?
  • 这很有趣......所以你认为我可以这样做并将差异输出到另一个文件中?有什么网站建议吗?或您可以发送给我的文件,其中包含有关如何执行此操作的说明?感谢您的信息(抱歉之前的声明):p
  • 我通过显示文件中存在“一些”差异来了解您在这里所做的事情,但我真正想要的是我正在测量一个值,它与给定的“真实”不同" 值,我想导入一个测量值的文件和一个真值的文件,并让它吐出“余数”,以便对另一个文件或我可以导出或保存为 csv 文件的东西说话
【解决方案2】:

您不需要编码,您可以使用文本编辑器中的替换功能使两个文件(空格或逗号)中的分隔符相同,并使用 TortoiseSVN 的图形差异工具进行比较:http://tortoisesvn.net/

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2021-12-11
  • 2014-06-08
  • 2015-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-17
相关资源
最近更新 更多