2010-06-22 30 views
13

Estoy escribiendo una función para exportar datos a Excel usando Office Interop en VB .NET. Actualmente estoy escribiendo las células utilizando directamente las células de la hoja de cálculo Excel() Método:¿La forma más rápida de escribir celdas en Excel con Office Interop?

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

Esto está tomando mucho tiempo para grandes cantidades de datos. ¿Existe una manera más rápida de escribir una gran cantidad de datos en Excel a la vez? ¿Hacer algo con rangos sería más rápido?

+0

Este casi duplicado tiene respuestas extensas: http://stackoverflow.com/questions/3840270/fastest-way-to-interface-between-live-unsaved-excel-data-andc-c-sharp-objects. – Govert

Respuesta

28

Debe evitar leer y escribir celda por celda si puede. Es mucho más rápido trabajar con matrices y leer o escribir bloques completos a la vez. Escribí una publicación hace un tiempo en reading from worksheets using C#; Básicamente, el mismo código funciona al revés (ver a continuación), y se ejecutará mucho más rápido, especialmente con bloques de datos más grandes.

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

No he podido dejar un comentario en tu blog, así que déjame escribir aquí. Puede crear una matriz basada en 1 en C# utilizando el método CreateInstance: var arr = (object [,]) Array.CreateInstance (typeof (object), new int [] {2, 3}, new int [] {1 , 1}) – IMil

10

Si aún no lo ha hecho, asegúrese de configurar Application.ScreenUpdating = false antes de comenzar a generar sus datos. Esto hará que las cosas vayan mucho más rápido. Vuelva a configurarlo en True cuando termine de enviar sus datos. Tener que volver a dibujar la pantalla en cada cambio de celda lleva un buen tiempo, evitando esto.

En cuanto al uso de rangos, igual tendrá que apuntar a 1 (una) celda específica para un valor, por lo que no veo ningún beneficio aquí. No estoy al tanto de hacer esto más rápido que lo que está haciendo con respecto a la salida de los datos.

5

Solo para añadir la respuesta de Tommy.

  • Es posible que también desee establecer el cálculo en manual antes de comenzar a escribir.

Application.Calculation = xlCalculationManual

y configurarlo de nuevo a automático cuando haya terminado con su escritura. (Si hay una posibilidad de que el modo original podría haber sido distinta automática nada, tendrá que almacenar ese valor antes de que el manual)

Application.Calculation = xlCalculationAutomatic

  • También podría usar el método CopyFromRecordset del objeto Range.

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

2

serio, la forma más rápida de escribir es con delimitadores de coma. Es más fácil escribir una línea de campos usando el método Join (",") ToString en lugar de intentar iterar a través de las celdas. A continuación, guarde el archivo como ".csv". Con la interoperabilidad, abra el archivo como un csv que automáticamente hará la actualización de la celda cuando se abra.

+3

Si la velocidad es lo que buscas, entonces este es el camino a seguir, sin embargo hay trampas especialmente alrededor de cadenas y caracteres especiales –

+0

¿Funcionará esto si quieres escribir en fórmulas? –

3

La manera más rápida de escribir y leer valores de los rangos de Excel es Range.get_Value y Range.set_Value.

La forma es la siguiente:

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); 

y sí, no requiere iteración.El rendimiento es solo voila !!

Espero que ayude !!

0

En caso de que alguien más aparezca como yo buscando una solución completa utilizando el método dado por @Mathias (que parece ser el más rápido para cargar en Excel) con la sugerencia de @IMil en la matriz.
Aquí van:

'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 

Entonces

limitaciones sólo incluyen permitir 26 columnas antes de que se necesitaría un mejor código para dar con las letras Intervalo de valores.

Cuestiones relacionadas