【发布时间】:2018-06-05 11:12:02
【问题描述】:
我只是有一个好奇的问题。我正在开发一个从列表视图导出到 csv 的 wpf 应用程序。我编写的代码(有效)如下:
private void Launch(object sender, RoutedEventArgs e)
{
Microsoft.Office.Interop.Excel.Application oExcel = new Microsoft.Office.Interop.Excel.Application();
oExcel.Visible = true;
Microsoft.Office.Interop.Excel.Workbook oWorkBook = oExcel.Workbooks.Add(Microsoft.Office.Interop.Excel.XlSheetType.xlWorksheet);
Microsoft.Office.Interop.Excel.Worksheet oSheet = (Microsoft.Office.Interop.Excel.Worksheet)oExcel.ActiveSheet;
int row = 2; //allow for header row
int column = 1;
oSheet.Cells[1, 1] = "Name";
oSheet.Cells[1, 2] = "CPU";
oSheet.Cells[1, 3] = "RAM";
oSheet.Cells[1, 4] = "IP Address";
oSheet.Cells[1, 5] = "Subnet Mask";
oSheet.Cells[1, 6] = "Port Group";
oSheet.Cells[1, 7] = "Default Gateway";
oSheet.Cells[1, 8] = "DNS";
oSheet.Cells[1, 9] = "Description";
oSheet.Cells[1, 10] = "Template";
oSheet.Cells[1, 11] = "Host";
oSheet.Cells[1, 12] = "Site";
oSheet.Cells[1, 13] = "Folder";
oSheet.Cells[1, 14] = "DataStore";
oSheet.Cells[1, 15] = "Patch Method";
oSheet.Cells[1, 16] = "HDD1Size";
oSheet.Cells[1, 17] = "HDD1Format";
oSheet.Cells[1, 18] = "HDD2Size";
oSheet.Cells[1, 19] = "HDD2Format";
oSheet.Cells[1, 20] = "HDD3Size";
oSheet.Cells[1, 21] = "HDD3Format";
oSheet.Cells[1, 22] = "HDD4Size";
oSheet.Cells[1, 23] = "HDD4Format";
oSheet.Cells[1, 24] = "HDD5Size";
oSheet.Cells[1, 25] = "HDD5Format";
foreach (var oVM in MyItems)
{
oSheet.Cells[row, column] = oVM.Name;
oSheet.Cells[row, (column + 1)] = oVM.CPU;
oSheet.Cells[row, (column + 2)] = oVM.RAM;
oSheet.Cells[row, (column + 3)] = oVM.IP;
oSheet.Cells[row, (column + 4)] = oVM.Subnet;
oSheet.Cells[row, (column + 5)] = oVM.PortGroup;
oSheet.Cells[row, (column + 6)] = oVM.Gateway;
oSheet.Cells[row, (column + 7)] = oVM.DNS;
oSheet.Cells[row, (column + 8)] = oVM.Description;
oSheet.Cells[row, (column + 9)] = oVM.Template;
oSheet.Cells[row, (column + 10)] = oVM.Host;
oSheet.Cells[row, (column + 11)] = oVM.Site;
oSheet.Cells[row, (column + 12)] = oVM.Folder;
oSheet.Cells[row, (column + 13)] = oVM.Datastore;
oSheet.Cells[row, (column + 14)] = oVM.Patch;
oSheet.Cells[row, (column + 15)] = oVM.HDD1Size;
oSheet.Cells[row, (column + 16)] = oVM.HDD1Format;
oSheet.Cells[row, (column + 17)] = oVM.HDD2Size;
oSheet.Cells[row, (column + 18)] = oVM.HDD2Format;
oSheet.Cells[row, (column + 19)] = oVM.HDD3Size;
oSheet.Cells[row, (column + 20)] = oVM.HDD3Format;
oSheet.Cells[row, (column + 21)] = oVM.HDD4Size;
oSheet.Cells[row, (column + 22)] = oVM.HDD4Format;
oSheet.Cells[row, (column + 23)] = oVM.HDD5Size;
oSheet.Cells[row, (column + 24)] = oVM.HDD5Format;
row++;
}
oExcel.Application.ActiveWorkbook.SaveAs(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\example", 6);
}
如前所述,这可行,但速度很慢。我在测试阶段将 Excel 设置为可见,并注意到打开它大约需要 7 秒。然后再用 2 个填充 10 行。
我也在编写代码来做相反的事情,从 excel 导入到列表视图中。为此,我使用了 StreamReader 对象,结果几乎是立竿见影的。所以我认为更改导出代码可以让我获得相同的速度。我试过这段代码:
FileStream srcFS;
srcFS = new FileStream(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\testingout.csv", FileMode.CreateNew, FileAccess.Write);
StreamWriter srcWrt = new StreamWriter(srcFS, System.Text.Encoding.Default);
StringBuilder header = new StringBuilder();
header.Append("Name").Append(',')
.Append("CPU").Append(',')
.Append("RAM").Append(',')
.Append("IP Address").Append(',')
.Append("Port Group").Append(',')
.Append("Default Gateway").Append(',')
.Append("DNS").Append(',')
.Append("Description").Append(',')
.Append("Template").Append(',')
.Append("Host").Append(',')
.Append("Site").Append(',')
.Append("Folder").Append(',')
.Append("Datastore").Append(',')
.Append("Patch").Append(',')
.Append("HDD1Size").Append(',')
.Append("HDD1Format").Append(',')
.Append("HDD2Size").Append(',')
.Append("HDD2Format").Append(',')
.Append("HDD3Size").Append(',')
.Append("HDD3Format").Append(',')
.Append("HDD4Size").Append(',')
.Append("HDD4Format").Append(',')
.Append("HDD5Size").Append(',')
.Append("HDDFormat").Append(',');
srcWrt.WriteLine(header);
foreach (MyItem item in MyItems)
{
StringBuilder builder = new StringBuilder();
builder.Append(item.Name).Append(',')
.Append(item.CPU).Append(',')
.Append(item.RAM).Append(',')
.Append(item.IP).Append(',')
.Append(item.Subnet).Append(',')
.Append(item.PortGroup).Append(',')
.Append(item.Gateway).Append(',')
.Append(item.DNS).Append(',')
.Append(item.Description).Append(',')
.Append(item.Template).Append(',')
.Append(item.Host).Append(',')
.Append(item.Site).Append(',')
.Append(item.Folder).Append(',')
.Append(item.Datastore).Append(',')
.Append(item.Patch).Append(',')
.Append(item.HDD1Size).Append(',')
.Append(item.HDD1Format).Append(',')
.Append(item.HDD2Size).Append(',')
.Append(item.HDD2Format).Append(',')
.Append(item.HDD3Size).Append(',')
.Append(item.HDD3Format).Append(',')
.Append(item.HDD4Size).Append(',')
.Append(item.HDD4Format).Append(',')
.Append(item.HDD5Size).Append(',')
.Append(item.HDD5Format);
srcWrt.WriteLine(builder);
}
MessageBox.Show("Task Complete");
但它似乎成倍地慢,比如返回消息框需要 40 秒。另外,我注意到即使循环完成并显示消息,流似乎仍在写入。如果我打开文件太快表明它正在被“另一个用户”使用。因此,当文件可供我使用时,实际上已经接近一分钟了。
我只是想知道为什么使用 FileStream 读取与写入的速度不同。是我在实施过程中遇到的问题,还是这是一个已知问题?如果与 Excel 交互是要走的路(我宁愿不是所有的机器都可能安装了 Excel),有没有办法缩短最初的 6 或 7 秒延迟?
【问题讨论】:
-
当你分析它时,哪一点慢?
StringBuilder或WriteLine的人口?MyItems.Count()是什么? -
试试这样的:ctrlv.it/id/71935/2944207925,这是我学生的项目,我认为它很快。
-
我认为,你可以输入
File.WriteAllText( <path> , builder.ToString()),而不是srcWrt.WriteLine(builder)builder.AppendLine(""); -
另外,从 Net 1.1 开始,我们不使用 StringBuilder 来知道 concats 的计数,所以不要使用 Append Append Append 等,只需编写 AppendLine(string1 + string2 + .. + string_last),应该是更快。
-
@sTrenat -- 我认为这不对。我认为
StringBuilder应该比使用+运算符的连接要快得多,除非您处理的迭代次数很少。 support.microsoft.com/en-us/help/306822/…