【问题标题】:C# exporting from listview to csv - Excel application vs. FileStreamC# 从 listview 导出到 csv - Excel 应用程序与 FileStream
【发布时间】: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 秒延迟?

【问题讨论】:

  • 当你分析它时,哪一点慢? StringBuilderWriteLine 的人口? 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/…

标签: c# wpf excel csv


【解决方案1】:

尝试将您的函数重写为:

StringBuilder builder = new StringBuilder();
    builder.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(',');
        .Append(Environment.NewLine);

foreach (MyItem item in MyItems) 
{  
    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)
        .Append(Environment.NewLine);
} 

using(FileStream srcFS = new FileStream(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\testingout.csv", FileMode.CreateNew, FileAccess.Write))
{
    using(StreamWriter srcWrt = new StreamWriter(srcFS, System.Text.Encoding.Default)) 
    {
        srcWrt.WriteText(builder);
    } 
} 

我猜是您写入文件的每个循环都会减慢您的代码速度。如果您改为批量写入文件,则当字符串完成时。这通常是更好的选择

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-19
    • 2014-11-09
    • 1970-01-01
    • 2023-03-17
    • 2020-11-10
    • 2012-05-16
    • 2015-09-20
    相关资源
    最近更新 更多