2010-06-22 9 views
13

Sto scrivendo una funzione per esportare i dati in Excel utilizzando Office Interop in VB .NET. Attualmente sto scrivendo le cellule utilizzando direttamente le cellule del foglio di lavoro Excel() il metodo:Il modo più veloce per scrivere celle su Excel con Office Interop?

worksheet.Cells(rowIndex, colIndex) = data(rowIndex)(colIndex) 

Questo sta prendendo molto tempo per grandi quantità di dati. C'è un modo più rapido per scrivere molti dati in Excel contemporaneamente? Fare qualcosa con intervalli sarebbe più veloce?

+0

Questo quasi duplicato ha risposte ampie: http://stackoverflow.com/questions/3840270/fastest-way-to-interface-between-live-unsaved-excel-data-and-c-sharp-objects. – Govert

risposta

28

Se possibile, evitare di leggere e scrivere cella per cella. È molto più veloce lavorare con gli array e leggere o scrivere interi blocchi contemporaneamente. Ho scritto un post poco fa su reading from worksheets using C#; in pratica, lo stesso codice funziona in senso inverso (vedi sotto), e funzionerà molto più velocemente, specialmente con blocchi di dati più grandi.

var sheet = (Worksheet)Application.ActiveSheet; 
    var range = sheet.get_Range("A1", "B2"); 
    var data = new string[3,3]; 
    data[0, 0] = "A1"; 
    data[0, 1] = "B1"; 
    data[1, 0] = "A2"; 
    data[1, 1] = "B2"; 
    range.Value2 = data; 
+1

Non sono riuscito a lasciare un commento sul tuo blog, quindi lascia che lo scriva qui. È possibile creare un array basato su 1 in C# utilizzando il metodo CreateInstance: var arr = (oggetto [,]) Array.CreateInstance (typeof (oggetto), new int [] {2, 3}, new int [] {1 , 1}) – IMil

10

Se non lo hai già fatto, assicurati di impostare Application.ScreenUpdating = false prima di iniziare a stampare i tuoi dati. Questo renderà le cose andare molto più veloci. Ritorna su True quando hai finito di stampare i tuoi dati. Dovendo ridisegnare lo schermo su ogni cella, il cambiamento richiede un bel po 'di tempo, evitando di salvarlo.

Per quanto riguarda l'utilizzo degli intervalli, sarà comunque necessario scegliere come target 1 (una) cella specifica per un valore, quindi non vedo alcun vantaggio qui. Non sono consapevole di farlo più velocemente di quello che stai facendo per quanto riguarda l'effettiva emissione dei dati.

5

solo per aggiungere alla risposta di Tommy.

  • Si potrebbe anche voler impostare il calcolo su manuale prima di iniziare a scrivere.

Application.Calculation = xlCalculationManual

e impostarlo su automatico quando hai finito con la vostra scrittura. (Se c'è una possibilità che la modalità originale avrebbe potuto essere qualcosa di diverso da automatico, si dovrà memorizzare tale valore prima di impostare l'avvio manuale)

Application.Calculation = xlCalculationAutomatic

  • È anche possibile utilizzare il metodo CopyFromRecordset dell'oggetto Range.

http://msdn.microsoft.com/de-de/library/microsoft.office.interop.excel.range.copyfromrecordset(office.11).aspx

2

Onestamente, il modo più veloce per scrivere è con la virgola come delimitatore. È più semplice scrivere una riga di campi usando il metodo Join (","). ToString invece di provare a scorrere le celle. Quindi salva il file come ".csv". Usando l'interoperabilità, apri il file come un csv che eseguirà automaticamente l'aggiornamento della cella per te all'apertura.

+3

Se la velocità è ciò che stai cercando, questa è la strada da percorrere, tuttavia ci sono trucchi specialmente attorno a stringhe e caratteri speciali –

+0

Funzionerà se vuoi scrivere in formule? –

3

Il modo più veloce per scrivere e leggere valori da intervalli excel è Range.get_Value e Range.set_Value.

Il modo in cui è la seguente:

Range filledRange = Worksheet.get_Range("A1:Z678",Missing); 
object[,] rngval = (object[,]) filledRange.get_Value (XlRangeValueDataType.xlRangeValueDefault); 

Range Destination = Worksheet2.get_Range("A1:Z678",Missing); 
destination.set_Value(Missing,rngval); 

e sì, non l'iterazione richiesto.Le prestazioni sono solo voilà !!

Spero che aiuti !!

0

Nel caso in cui qualcun altro si presenti come me cercando una soluzione completa utilizzando il metodo fornito da @Mathias (che sembra essere il più veloce per il caricamento in Excel) con il suggerimento di @ IMil sull'array.
Qui si va:

'dt (DataTable) is the already populated DataTable 
'myExcelWorksheet (Worksheet) is the worksheet we are populating 
'rowNum (Integer) is the row we want to start from (usually 1) 
Dim misValue As Object = System.Reflection.Missing.Value 
Dim arr As Object = DataTableToArray(dt) 
'Char 65 is the letter "A" 
Dim RangeTopLeft As String = Convert.ToChar(65 + 0).ToString() + rowNum.ToString() 
Dim RangeBottomRight As String = Convert.ToChar(65 + dt.Columns.Count - 1).ToString() + (rowNum + dt.Rows.Count - 1).ToString() 
Dim Range As String = RangeTopLeft + ":" + RangeBottomRight 
myExcelWorksheet.Range(Range, misValue).NumberFormat = "@" 'Include this line to format all cells as type "Text" (optional step) 
'Assign to the worksheet 
myExcelWorksheet.Range(Range, misValue).Value2 = arr 

Poi

limitazioni includono consentendo solo 26 colonne prima che avrebbe bisogno di un codice migliore per venire con le lettere di valore gamma.