2013-08-22 4 views
0

У меня есть интересная головоломка, как быстро (менее 1 минуты) экспортировать большое количество данных (заполненных из SQL, 35 000 строк) в электронную таблицу Excel для пользователей. У меня есть код, который может обрабатывать экспорт, и, хотя ничто не является «неправильным» с кодом как таковым, он неистово медленно занимает 4 минуты, чтобы экспортировать весь файл (иногда дольше, если у пользователя меньше памяти или больше работает на их системы). К сожалению, это улучшение по сравнению с 10 + минутами, которые он использовал, используя наш старый метод. Проще говоря, можно ли это сделать быстрее, без использования сторонних компонентов? Если да, то как? Мой код выглядит следующим образом, замедление происходит между сообщениями 6 и 7, где записана каждая строка. Спасибо всем за то, что нашли время, чтобы посмотреть на это:Быстрый экспорт крупноформатной таблицы Excel в VB.Net

Private Sub btnTest_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnJeffTest.Click 
      Test(MySPtoExport) 
    End Sub 

Private Sub Test(ByVal SQL As String) 
    'Declare variables used to execute the VUE Export stored procedure 
    MsgBox("start stop watch") 
    Dim ConnectionString As New SqlConnection(CType(ConfigurationManager.AppSettings("ConnString"), String)) 
    Dim cmdSP As New SqlClient.SqlCommand 
    Dim MyParam As New SqlClient.SqlParameter 
    Dim MyDataAdapter As New SqlClient.SqlDataAdapter 
    Dim ExportDataSet As New DataTable 
    Dim FilePath As String 

    MsgBox("stop 1 - end of declare") 

    Try 

     ' open the connection 
     ConnectionString.Open() 

     ' Use the connection for this sql command 
     cmdSP.Connection = ConnectionString 

     'set this command as a stored procedure command 
     cmdSP.CommandType = CommandType.StoredProcedure 

     'get the stored procedure name and plug it in 
     cmdSP.CommandText = SQL 

     'Add the Start Date parameter if required 
     Select Case StDt 
      Case Nothing 
       ' there's no parameter to add 
      Case Is = 0 
       ' there's no parameter to add 
      Case Else 
       'add the parameter name, it's direction and its value 
       MyParam = cmdSP.Parameters.Add("@StartDate", SqlDbType.VarChar) 
       MyParam.Direction = ParameterDirection.Input 
       MyParam.Value = Me.txtStartDate.Text 
     End Select 
     MsgBox("stop 2 - sql ready") 
     'Add the End Date parameter if required 
     Select Case EdDt 
      Case Nothing 
       ' there's no parameter to add 
      Case Is = 0 
       ' there's no parameter to add 
      Case Else 
       'add the parameter name, it's direction and its value 

       MyParam = cmdSP.Parameters.Add("@EndDate", SqlDbType.VarChar) 
       MyParam.Direction = ParameterDirection.Input 
       MyParam.Value = Me.txtEndDate.Text 
     End Select 

     'Add the single parameter 1 parameter if required 
     Select Case SPar1 
      Case Is = Nothing 
       ' there's no parameter to add 
      Case Is = "" 
       ' there's no parameter to add 
      Case Else 
       'add the parameter name, it's direction and its value 
       MyParam = cmdSP.Parameters.Add(SPar1, SqlDbType.VarChar) 
       MyParam.Direction = ParameterDirection.Input 
       MyParam.Value = Me.txtSingleReportCrt1.Text 
     End Select 

     'Add the single parameter 2 parameter if required 
     Select Case Spar2 
      Case Is = Nothing 
       ' there's no parameter to add 
      Case Is = "" 
       ' there's no parameter to add 
      Case Else 
       'add the parameter name, it's direction and its value 
       MyParam = cmdSP.Parameters.Add(Spar2, SqlDbType.VarChar) 
       MyParam.Direction = ParameterDirection.Input 
       MyParam.Value = Me.txtSingleReportCrt2.Text 
     End Select 

     MsgBox("stop 3 - params ready") 

     'Prepare the data adapter with the selected command 
     MyDataAdapter.SelectCommand = cmdSP 

     ' Set the accept changes during fill to false for the NYPDA export 
     MyDataAdapter.AcceptChangesDuringFill = False 

     'Fill the Dataset tables (Table 0 = Exam Eligibilities, Table 1 = Candidates Demographics) 
     MyDataAdapter.Fill(ExportDataSet) 

     'Close the connection 
     ConnectionString.Close() 

     'refresh the destination path in case they changed it 
     SPDestination = txtPDFDestination.Text 

     MsgBox("stop 4 - procedure ran, datatable filled") 

     Select Case ExcelFile 
      Case True 

       FilePath = SPDestination & lblReportName.Text & ".xls" 

       Dim _excel As New Microsoft.Office.Interop.Excel.Application 
       Dim wBook As Microsoft.Office.Interop.Excel.Workbook 
       Dim wSheet As Microsoft.Office.Interop.Excel.Worksheet 

       wBook = _excel.Workbooks.Add() 
       wSheet = wBook.ActiveSheet() 

       Dim dt As System.Data.DataTable = ExportDataSet 
       Dim dc As System.Data.DataColumn 
       Dim dr As System.Data.DataRow 
       Dim colIndex As Integer = 0 
       Dim rowIndex As Integer = 0 

       MsgBox("stop 5 - excel stuff declared") 

       For Each dc In dt.Columns 
        colIndex = colIndex + 1 
        _excel.Cells(1, colIndex) = dc.ColumnName 
       Next 

       MsgBox("stop 6 - Header written") 

       For Each dr In dt.Rows 
        rowIndex = rowIndex + 1 
        colIndex = 0 
        For Each dc In dt.Columns 
         colIndex = colIndex + 1 
         _excel.Cells(rowIndex + 1, colIndex) = dr(dc.ColumnName) 
        Next 
       Next 

       MsgBox("stop 7 - rows written") 

       wSheet.Columns.AutoFit() 

       MsgBox("stop 8 - autofit complete") 

       Dim strFileName = SPDestination & lblReportName.Text & ".xls" 

       If System.IO.File.Exists(strFileName) Then 
        System.IO.File.Delete(strFileName) 
       End If 

       MsgBox("stop 9 - file checked") 

       wBook.SaveAs(strFileName) 
       wBook.Close() 
       _excel.Quit() 
     End Select 

     MsgBox("File " & lblReportName.Text & " Exported Successfully!") 


     'Dispose of unneeded objects 
     MyDataAdapter.Dispose() 
     ExportDataSet.Dispose() 
     StDt = Nothing 
     EdDt = Nothing 
     SPar1 = Nothing 
     Spar2 = Nothing 
     MyParam = Nothing 
     cmdSP.Dispose() 
     cmdSP = Nothing 
     MyDataAdapter = Nothing 
     ExportDataSet = Nothing 

    Catch ex As Exception 
     ' Something went terribly wrong. Warn user. 
     MessageBox.Show("Error: " & ex.Message, "Stored Procedure Running Process ", _ 
     MessageBoxButtons.OK, MessageBoxIcon.Error) 

    Finally 
     'close the connection in case is still open 
     If Not ConnectionString.State = ConnectionState.Closed Then 
      ConnectionString.Close() 
      ConnectionString = Nothing 
     End If 

     ' reset the fields 
     ResetFields() 

    End Try 
End Sub 
+2

Вы можете заполнить полный диапазон в excel из 2-мерного массива - это будет намного быстрее, чем ваш подход по ячейкам. См. Например: http://stackoverflow.com/questions/536636/write-array-to-excel-range –

+0

Привет, Тим, большое спасибо за ваш ответ. С некоторыми ручными пустяками (как мне пришлось конвертировать из C# в статью, которую вы предоставили VB.Net), я смог заставить это работать менее чем за 5 секунд. Просьба представить ваш комментарий в качестве решения, чтобы я мог отметить его как таковой. Еще раз спасибо. –

ответ

2

Как при использовании VBA для автоматизации Excel, вы можете присвоить массив непосредственно к значению объекта Range: это сделано как одна операция , поэтому вы удаляете служебные данные, связанные с выполнением нескольких вызовов через границы процесса между вашим. Net кодом и экземпляром Excel.

Например, см принятый ответ здесь: Write Array to Excel Range

0

Мы имели приложение VB.NET, что сделал именно это, и потребовалось еще больше времени для наших пользователей, которые были на медленный ПК ... иногда 15 минут.

Приложение представляет собой приложение ASP/VB.NET, которое просто создает таблицу HTML и выводит результат как расширение .xls ... excel может читать таблицу HTML и анализировать ее в виде сетки. Вы можете по-прежнему передавать XML для форматирования и опций, блокировки горизонтальной панели и т. Д.

Если у вас нет возможности использовать ASP.NET ... попробуйте изучить способ построения строки таблицы HTML и excel parse & населяют вас ... намного быстрее! Я уверен, что excel может анализировать и другие типы ... XML, массивы, HTML и т. Д. ... все будет быстрее, чем вручную создавать каждую строку через объекты VB.NET.

1

Вот часть моего кода, который выполняет очень быстро экспорт данных из DataTable в лист Excel (используйте «Секундомер» объект для сравнения скорости и дайте мне комментарий):

Dim _excel As New Excel.Application 
Dim wBook As Excel.Workbook 
Dim wSheet As Excel.Worksheet 

wBook = _excel.Workbooks.Add() 
wSheet = wBook.ActiveSheet() 


Dim dc As System.Data.DataColumn 
Dim colIndex As Integer = 0 
Dim rowIndex As Integer = 0 
'Nombre de mesures 
Dim Nbligne As Integer = DtMesures.Rows.Count 

'Ecriture des entêtes de colonne et des mesures 
'(Write column headers and data) 

For Each dc In DtMesures.Columns 
    colIndex = colIndex + 1 
    'Entête de colonnes (column headers) 
    wSheet.Cells(1, colIndex) = dc.ColumnName 
    'Données(data) 
    'You can use CDbl instead of Cobj If your data is of type Double 
    wSheet.Cells(2, colIndex).Resize(Nbligne,).Value = _excel.Application.transpose(DtMesures.Rows.OfType(Of DataRow)().[Select](Function(k) CObj(k(dc.ColumnName))).ToArray()) 
Next 
+0

Спасибо за ваш ответ, к сожалению, с тех пор я перешел от компании, с которой я был в то время, и не могу проверить. Тем не менее, я буду помнить об этом, если мне когда-нибудь понадобится сделать что-то подобное. –

+0

Это работало для меня после того, как я установил значения по умолчанию в моей таблице данных как нечто отличное от . Я получил несоответствие типа, иначе, поскольку ячейки Excel не могут обрабатывать нулевые значения. – phrebh

Смежные вопросы