2017-05-29 47 views
0

我試圖優化我前段時間編寫的應用程序的輸出,儘管我在許多方面取得了很大成績,但我仍在努力加快導出結果的功能一個.xlsx文件的列表視圖。將ListView導出到Excel - 苦苦掙扎

I'm使用互操作做到這一點,如下圖所示:

Imports Excel = Microsoft.Office.Interop.Excel 
Imports System 
Imports System.IO 
Imports System.Data.OleDb 
Imports System.Threading 
Imports System.Linq 
Imports System.Data.SqlClient 

這是出口在列表視圖中的數據的功能:

Private Function ExportListViewTab5ToXLSxFile(ByRef FileNameWithoutExtension As String, ByRef OutputDir As String) As Boolean 

     Try 
      Dim objExcel As Excel.Application = New Excel.Application 
      Dim bkWorkBook As Excel.Workbook 
      Dim shWorkSheet As Excel.Worksheet 
      Dim i As Integer 
      Dim j As Integer 

      objExcel = New Excel.Application 
      bkWorkBook = objExcel.Workbooks.Add 
      shWorkSheet = CType(bkWorkBook.ActiveSheet, Excel.Worksheet) 

      For i = 0 To lvObjectsTab5.Columns.Count - 1 
       shWorkSheet.Cells(1, i + 1) = lvObjectsTab5.Columns(i).Text 
      Next 
      For i = 0 To lvObjectsTab5.Items.Count - 1 
       For j = 0 To lvObjectsTab5.Items(i).SubItems.Count - 1 
        shWorkSheet.Cells(i + 2, j + 1) = lvObjectsTab5.Items(i).SubItems(j).Text 
       Next 
      Next 

      shWorkSheet.Columns.AutoFit() 

      Try 

       '///////////////// 
       '// Save report // 
       '///////////////// 
       Try 
        shWorkSheet.SaveAs(OutputDir & "\" & FileNameWithoutExtension & ".xlsx") 
       Catch ex As Exception 
        MessageBox.Show("A exportação do relatório foi cancelada pelo usuário!", "Exportação cancelada!", MessageBoxButtons.OK, MessageBoxIcon.Error) 
        Return False 
       End Try 

       '/////////////////////////////////// 
       '// Close EXCEL.EXE COM processes // 
       '/////////////////////////////////// 

       bkWorkBook.Close() 
       objExcel.Workbooks.Close() 
       NAR(bkWorkBook) 
       objExcel.Quit() 
       NAR(objExcel) 

       '////////////////////////// 
       '// Open report in Excel // 
       '////////////////////////// 

       Process.Start(OutputDir & "\" & FileNameWithoutExtension & ".xlsx") 
       Return True 

      Catch ex As Exception 
       MessageBox.Show("Falha ao exportar o arquivo '" & FileNameWithoutExtension & ".xlsx' para '" & OutputDir & "'", "Falha ao exportar relatório!" & vbCrLf & vbCrLf & _ 
           "Detalhes do erro:" & vbCrLf & vbCrLf & _ 
           ex.ToString, MessageBoxButtons.OK, MessageBoxIcon.Error) 
       Return False 
      End Try 
     Catch ex As Exception 
      MessageBox.Show("Falha ao exportar o arquivo '" & FileNameWithoutExtension & ".xlsx' para '" & OutputDir & "'", "Falha ao exportar relatório!" & vbCrLf & vbCrLf & _ 
          "Detalhes do erro:" & vbCrLf & vbCrLf & _ 
          ex.ToString, MessageBoxButtons.OK, MessageBoxIcon.Error) 
      Return False 
     End Try 

    End Function 

ListView控件包含10列,需要4分鐘才能輸出2000行。太多了。我搜索了幾個小時並搜索了幾個性能問題的例子,但我發現的所有例子都與我的類似。

有沒有人可以指導我如何使用.NET代碼提高我的函數性能?在典型的情況下,這個列表視圖列出了15000行。我限制到2000年,所以對用戶來說不那麼痛苦。

有什麼建議嗎?

由於提前, 丹尼爾

+0

一個常見問題。在你的雙循環中,將所有來自listview的文本寫入一個2d數組中。然後將數組一次寫入工作表!不帶循環。像'shWorkSheet.Cells(2,1).Resize(numberOfRows,numberOfColumns).Value = arrayFilledByDoubleLoop'這將寫入A2作爲輸出數據的左上角。 – MacroMarc

+1

您也可以嘗試'ClosedXml'NuGet包的互操作性。在我的應用程序中,我在15秒內創建了85k行,18列的電子表格。 – Phil

回答

1

嘗試一次全部適用所有的值作爲一個範圍。像這樣的東西可能會做到這一點。

dim Values(lvObjectsTab5.Items.Count, lvObjectsTab5.Items(i).SubItems.Count) as object 
dim Range as Excel.Range = shWorkSheet.Range("A1","J" & (lvObjectsTab5.Items.Count+ 1)) 

For i = 0 To lvObjectsTab5.Columns.Count - 1 
    Values(0, i) = lvObjectsTab5.Columns(i).Text 
Next 

For i = 0 To lvObjectsTab5.Items.Count - 1 
     For j = 0 To lvObjectsTab5.Items(i).SubItems.Count - 1 
      Values(i+1,j) = lvObjectsTab5.Items(i).SubItems(j).Text 
     Next 
Next 
Range.value = Values 

編輯:插入上的值矩陣中的列標題。

+1

耶穌......來自@AugustoQ的答案將它從12分鐘縮短到了30秒......我認爲這個線程將幫助一羣擁有同樣問題的人......謝謝! –

+0

此解決方案的唯一副作用是不再導出列表視圖中具有列名稱的標題。 –

+0

你也可以導出頭文件,我忘了把它放在我的代碼上,但是如果你把'Values(,)'矩陣的第一行作爲頭文件名,它也會有頭文件名 – AugustoQ

相關問題