我收到了一张非常大的Excel工作簿,其中包含500多张。每个工作表代表一个商店,行包含该商店的交易。每个工作表布局都相同。我被要求编写一个循环遍历每个工作表的程序,提取特定的事务数据,并将所有内容写入一个巨大的CSV文件。
我知道这种功能更适合关系数据库,但我被要求按原样处理。
我编写了一个成功解析数据并编写数据的程序。问题是,在同步读取和写入数据时,完成文件写入需要将近半个小时。
我想通过异步读取和写入每张表中的数据来完成此任务。在C#中,我更喜欢使用任务并行库,但我可以使用其他选项。
我正在考虑从foreach循环中分离工作线程,如下所示:
foreach( Worksheet ws in _excelApp.Worksheets)
{
Parallel.Invoke(()=>ExportWorksheet(ws));
}
然后在方法中(为简洁起见缩短):
private void ExportWorksheet(Worksheet ws)
{
using(FileStream fs = new new FileStream(fi.FullName, FileMode.Append, FileAccess.Write, FileShare.Write, 1, true))
{
for(int row = 1; row < 300; row++)
{
for(int column = 1; column < 20)
{
byte[] bytes = Encoding.ASCII.GetBytes(ws.Cells[row, column].Value.ToString() + ",");
fs.Write(bytes, 0, bytes.count());
}
fs.Write(Encoding.ASCII.GetBytes("\n"), 0, 2);
}
}
}
当然,这给了我奇怪的结果。
我是否在正确的轨道上?我应该使用不同的编码吗?是否有更简洁的方法来完成异步写入?这里是否有任何线程规则被破坏?
欢迎所有建议。谢谢你的帮助。
答案 0 :(得分:2)
不是循环遍历行和列,而是最好使用范围的Value属性(例如WorkSheet的ActiveRange)。它包含一个包含所有数据的二维数组。这会使读数性能提高1000倍。
另一部分。我将它重写为两部分,删除Excel引用:
DateTime start = DateTime.Now;
//using (FileStream fs = new FileStream(@"C:\temp\x.x", FileMode.Append, FileAccess.Write, FileShare.Write, 1, true))
//{
// for (int row = 1; row < 3 * 1000; row++)
// {
// for (int column = 1; column < 3 * 1000; column++)
// {
// byte[] bytes = Encoding.ASCII.GetBytes(1.ToString() + ",");
// fs.Write(bytes, 0, bytes.Length);
// }
// byte[] bytes2 = Encoding.ASCII.GetBytes("\n");
// fs.Write(bytes2, 0, bytes2.Length);
// }
//}
using (TextWriter tw = new StreamWriter(new FileStream(@"C:\temp\x.x", FileMode.Append, FileAccess.Write, FileShare.Write, 1, true)))
{
for (int row = 1; row < 3 * 1000; row++)
{
for (int column = 1; column < 3 * 1000; column++)
{
tw.Write(1.ToString());
tw.Write(',');
}
tw.WriteLine();
}
}
DateTime end = DateTime.Now;
MessageBox.Show(string.Format("Time spent: {0:N0} ms.", (end - start).TotalMilliseconds));
第一部分(几乎与您的代码完全相同,现已注释掉)需要3.670(是的,超过三千)秒。 第二部分(未注释掉)需要12秒。
答案 1 :(得分:0)
我从C#阅读Excel的经验通常是令人讨厌的。所有计算时间都花在使用Excel进行广告投放上 - 写出CSV文件根本不需要时间。用单独的线程来打扰是不值得的。
在某些情况下,我只是将电子表格保存为.csv,然后从那里解析它。如何使用我不知道的多个工作表,但您可以通过工作表翻页将它们逐个保存到.CSV。然后,将.CSV作为长字符串读取并清理它们。