C#从listview导出到csv - Excel应用程序与FileStream

时间:2017-12-22 21:27:12

标签: c# wpf excel csv

我的好奇心问题比什么都重要。我正在开发一个从listview导出到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导入listview。为此,我使用了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秒返回消息框。此外,我注意到即使循环完成,并显示消息,似乎流仍在写。如果我过快地打开文件,则说明#34;另一个用户"正在使用它。所以当文件可供我使用时,它实际上更接近一分钟。

我只是想知道为什么速度读取与使用FileStream写入的差异。这是我在实施时遇到的问题,还是这个已知的问题?如果要与Excel交互是可行的方法(我不是因为并非所有机器都安装了Excel)是否有办法缩短最初的6或7秒延迟?

1 个答案:

答案 0 :(得分: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.);
    } 
} 

我猜你写的每个循环都会减慢你的代码速度。如果你改为在一个批处理中写入文件,那么当字符串完成时。这通常是一个更好的选择