【问题标题】:Transform and load a large CSV to multiple worksheets in one Excel file将大型 CSV 转换并加载到一个 Excel 文件中的多个工作表中
【发布时间】:2013-07-26 07:06:29
【问题描述】:

背景故事:

来自管理层的新项目:我的老板给了我一个软项目来评估我们当前的 ETL 计划之一,以寻找流程中的改进空间,我正在寻求指导。

动机:目前正在使用 Excel,由于文件大小,在此过程中经常崩溃。

任务:分析师每个月都会收到来自调查供应商的大型 csv 文件,其中包含多达 750 列(并非所有唯一名称)和 15,000 多行,只需将大型 csv 文件转换为包含七个工作表的 excel 文件。在 csv 的列标题上。下面是如何分解的详细信息。

我的问题是使用 VB.NET 和 VS2010 或 VBA 将一个大型 csv 转换为具有多个工作表的编辑过的 excel 文件,或者使用 Excel 是继续此过程的最简单方法吗?我是 Excel 专家用户,但我仍然是 VBA、VB.NET 或任何其他语言编码的初学者到中级。


详细问题:

我愿意使用免费或开源软件,但我最熟悉 VB.NET 和 Excel 以及 Excel-VBA。我已经使用类似的TextFieldParser code found here 对一个简单的 Windows 窗体应用程序进行了一些编码,以将 csv 加载到数据表中。我曾考虑将其加载到数组甚至二维数组中,以便更轻松地编辑列标题并找到重复的列标题。数据表选项仍然给我留下了比答案更多的问题,因为我需要唯一的列标题,并且如果我要立即编写一个 Excel 文件,我不确定是否应该使用数据表。我试过 CSVreader from CodeProject 不会处理具有重复标题名称的文件。我觉得好像我被作家阻止了,因为我不确定我应该采取哪个方向来处理这样的过程。非常感谢您提供的任何意见,如果这个问题没有一个明确的最佳答案,我深表歉意,谢谢。


当前使用 excel 的分析师任务

当前的分析计划已表示分析师在 excel 中打开 csv,在第 1 行上方插入一行并使用 vlookup 将“新”列名称替换为“旧”列名称,基于一个简单的两列查找表在单独的工作表上。例如

New becomes Old
"org-name" becomes "org_name" or 
"item_1_Vendor" becomes "item_1" or
"date-created_Survey" becomes "date_created"
etc...checking all sent "New" columns against the list of all possible 750 columns.

然后他们粘贴第一行的值,然后删除包含我们要更改的新标题的第二行。

然后分析师必须修复名为“sid”的文件的主键。 调查 ID 字段 (sid) 应为数据文件的每一行提供一个编号。有时 sid 显示在 sid_HCAHPS 或 sid_CGCAHPS 字段下。 分析师将在“sid”字段旁边插入一列,并在其中输入一个公式,例如: =IF(BE2<>"",BE2,IF(RD2<>"",RD2,IF(UH2<>"",UH2,""))) 实际的单元格引用会发生变化,但在示例 excel 公式中,

"sid"=Range("BE2")
"sid_HCAHPS"=Range("RD2")
"sid_CGCAHPS"=Range("UH2")

新创建的主键列制作完成后不留空,我们就可以删除原来的“sid”列了。

下一步是检查列,因为可能存在冗余的 HCAHPS 列部分(由于发送第二次调查,然后返回 - 编码为 Wave 2),删除第二组列“sid_HCAHPS”到“语言"

接下来是最大的改动,因为我们已经设置了一个系统,我们将这些信息以七个工作表 excel 文件的形式发送给我们的数据库管理员,由 MS Access Query 加载,该查询从每个加载的工作表中创建一个表进入我们专有的商业智能软件。全部完成!


【问题讨论】:

  • 在我看来,这个 CSV 文件确实应该首先加载到 Access 表中(因为这是处理此类大量数据的更好工具),然后运行各种查询(可能还有 Access VBA如果需要)在那里将其分成七个表。如果由于某种原因无法做到这一点,那么 Excel VBA 肯定能够完成这项工作。我不会说 VB.NET,我从来没有在 Excel 工作中使用过。
  • 使用访问的问题是每个表的256列的限制。所以文件在被剪切之前不能加载到表中。
  • 我明白了,我不知道 Access 有这个限制。好吧,我认为 VBA 可以自动执行您上面描述的步骤,并且可能比 VB.NET 更易于使用,因为 VBA 可以直接在 Excel 中工作,而这似乎是所有工作都发生的地方。
  • 实际上,15000 * 750 = 1130 万个单元格。 Excel 可以毫无问题地处理这么多。如果任何代码运行非常缓慢或崩溃,那是因为它可能写得不太好。每个 Range 操作都有开销,所以不要循环通过单元格等。有了这么多的行和列,尽量不要在工作表上工作(插入列等),而是在内存中的数组或集合中工作,输出通过 RangeOfCells.Value/Formula = 等,在单个操作中将最终产品添加到工作表中,或者至少一次处理列,而不是单元格。
  • @Scheballs,我感受到了你的痛苦——当我不得不处理愚蠢的 200MB excel 文件时,我的头有时会撞到我的桌子上。尝试使用 .xlsb 格式,因为它的打开/保存速度要快得多。您在上面概述的过程听起来非常适合自动化(使用 VBA 或 .NET 语言(我喜欢 C#))。由于每一行都被独立且统一地有效处理(在标题之后),您可以处理文件流,处理数据并立即将其泵送到输出文件。这适用于任意大的文件:-)

标签: vb.net visual-studio-2010 excel excel-2007 vba


【解决方案1】:

您的问题是“VB.net 可以自动化我们当前的分析任务吗?” - 如果是,那么是的。

您可以使用 streamreader 类从您的 csv 中获取数据 (http://msdn.microsoft.com/en-us/library/system.io.streamreader.aspx)

然后将它存储在您提到的数组中或使用 *list 类 (http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx)

存储完所有数据后,您需要自动执行 excel,这非常简单,但您也可以通过以下链接开始使用它:http://support.microsoft.com/kb/301982/en-gb

  • 使用列表类,您可以使用类或结构创建自定义对象列表。例如。

我们定义一个结构:

Structure rowOfData
    Public intPrimaryKey as Integer
    Public strIceCreamName as String
    Public decPrice as Decimal
End Structure

然后我们可以创建一个 rowOfData 并向其添加属性:

Dim iceCream1 as rowOfData
iceCream1.intPrimaryKey = 1
iceCream1.strIceCreamName = "Mr Whippy"
iceCream1.decPrice = 0.99

我们创建一个列表:

Dim listOfIceCreams as New List(of rowOfData)

然后像这样添加:

listOfIceCreams.Add(iceCream1)
listOfIceCreams.Add(iceCream2)
etc.

并像这样访问列表的成员:

listOfIceCreams(0).decPrice 'gives us the price of the ice Cream that was added to the list first.

还有很多其他有用的方法,列表有哪些数组没有。您可以查看该 msdn 列表类链接,看看是否有任何您可能需要的东西

【讨论】:

  • 感谢有关自动化 excel 的链接,我已经完成了尽可能多的搜索,我不敢相信我还没有看到这个。 List 类很有趣,但与使用数组相比,它的主要好处是什么?
  • 我已经更新了我的答案。列表更具可定制性,这就是您可能希望它们保存和处理您的数据的原因
  • 刚刚看到您有 256 列,您可能最好使用数组而不是列表:P
猜你喜欢
  • 2020-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-14
  • 1970-01-01
  • 2013-09-15
  • 1970-01-01
  • 2013-07-13
相关资源
最近更新 更多