VB2005 Esportazione rapida in Excel di dataset grandi

sabato 20 giugno 2009 - 16.49

niclo Profilo | Newbie

ciao a tutti, questo è il mio secondo thread e spero che sia più interessante del primo che ho posto.

Vorrei esportare un dataset di circa 10.000 record (circa 30 colonne) in Excel. Al momento utilizzo questo codice ma prima di ultimare l'esportazione impiego un 3-4 minuti

Dim excel As New Microsoft.Office.Interop.Excel.ApplicationClass
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 = dsExcel.Tables(0)
Dim dc As System.Data.DataColumn
Dim dr As System.Data.DataRow
Dim colIndex As Integer = 0
Dim rowIndex As Long = 0

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

Dim nrow As Long = dt.Rows.Count
While rowIndex <= (nrow - 1)
dr = dt.Rows(rowIndex)
rowIndex = rowIndex + 1
colIndex = 0
For Each dc In dt.Columns
colIndex = colIndex + 1
excel.Cells(rowIndex + 1, colIndex) = dr(dc.ColumnName)
Next
End While

wSheet.Columns.AutoFit()

Dim strPathFile As String = "C:\prova.xls"

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

wBook.SaveAs(strPathFile)
excel.Workbooks.Open(strPathFile)
excel.Visible = False
excel.Workbooks.Close()

Qualcuno mi consiglia un metodo più efficiente per eseguire l'esportazione in tempi contenuti?

grazie

Jeremy Profilo | Guru

Ciao Stefano.
Il tempo che ci impiega la procedura, penso sia fisiologico ..... visto la quantità di dati.
Quello che potremmo aiutarti a fare ... se è ciò che ti interessa .... è evitare che l'applicazione si blocchi in attesa della fine della procedura, eseguendola in un thread separato da quello principale, magari mostrando un messagebox alla fine del processo ed, eventualmente, mostrando una progressbar di avanzamento.

Facci sapere...
Ciao

niclo Profilo | Newbie

in effetti ho fatto cosi: thread separato e barra di caricamento che notifica lo stato di avanzamento

sto guardando un pò in giro e ho trovato questo articolo

http://support.microsoft.com/kb/316934/it

non ho ancora provato ma pensavo di fare una cosa del genere, valutando poi i tempi e la fattibilità:
preparo un template excel pulito (solo intestazioni di colonna con formattazione dati corrette) poi con un Datadapter estraggo il dataset vuoto e in un ciclo creo l'aggiunta di Datarow nel Dataset, per poi eseguire l'update..

Dici che potrebbe funzionare?

Jeremy Profilo | Guru

Se lo dice Microsoft ..... .
Scherzo .... ovviamente, mi sembra la via più corretta.

Facci sapere...
Ciao

niclo Profilo | Newbie

ciao Jeremy e a tutti coloro a cui possa interessare questo risultato che sono riuscito ad ottenere..

Con il codice che avevo indicato inizialmente, riuscivo ad esportare un dataset di 12851 record (33 colonne) in Excel in un tempo di parecchi minuti.
Diciamo che il foglio Excel veniva creato correttamente ma le performance di creazione non mi soddisfacevano. Inoltre durante la fase di generazione, se aprivo un altro file Excel di lavoro, mi compariva anche il file in fase di generazione, non riuscendo a gestire le diverse istanze di Excel.

Con la nuova soluzione che ho costruito, secondo l'articolo da me indicato, sono riuscito ad ottenere risultati migliori, infatti ho estratto lo stesso dataset in un tempo pari a circa 30 secondi. I passi che ho seguito sono i seguenti:
- costruzione struttura del foglio Excel, identica alla struttura del datase (che nel mio caso è sempre la stessa)
- inserimento righe mediante DataAdapter e successivo Update, secondo questo codice:


Dim i As Integer
Dim Path = "C:\prova.xls"
Dim conString As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Path & ";Extended Properties=""Excel 8.0;HDR=Yes"""
Dim conn1 As New System.Data.OleDb.OleDbConnection(conString)
Dim da As New OleDb.OleDbDataAdapter("SELECT * FROM [Foglio1$]", conn1)
Dim ds As New DataSet
da.Fill(ds, "Foglio1")

da.InsertCommand = New OleDb.OleDbCommand("INSERT INTO [Foglio1$] (ID, Nome, ...) VALUES (?, ?, ...)", conn1)
da.InsertCommand.Parameters.Add("@ID", OleDb.OleDbType.Double).SourceColumn = "ID"
da.InsertCommand.Parameters.Add("@Nome", OleDb.OleDbType.VarChar, 10, "Nome")
....

Dim dr As DataRow
Dim dsGrid As DataSet = Me.DataGridView1.DataSource
Dim nRec As Integer = dsGrid.Tables(0).Columns.Count
For Each drGrid As DataRow In dsGrid.Tables(0).Rows
dr = ds.Tables("Foglio1").NewRow
For i = 0 To (nRec - 1)
dr.Item(i) = drGrid.Item(i)
Next
ds.Tables("Foglio1").Rows.Add(dr)
Next
da.Update(ds, "Foglio1")
conn1.Close()


Jeremy, fammi sapere cosa ne pensi...
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5