2009-09-28 29 views
16

Estoy buscando escribir en un archivo excel (formato .xls MS Excel 2003) programáticamente usando Java. Los archivos de salida de Excel pueden contener ~ 200,000 filas que planeo dividir en una cantidad de hojas (64k filas por hoja, debido al límite de Excel).API para escribir enormes archivos de Excel usando java

He intentado utilizar las API POI de apache, pero parece ser un problema de memoria debido al modelo de objetos API. Me veo obligado a agregar celdas/hojas al objeto libro de trabajo en la memoria y solo una vez que se agregan todos los datos, puedo escribir el libro en un archivo. Este es un ejemplo de cómo recomienda el apache i escribir archivos Excel utilizando su API:

Workbook wb = new HSSFWorkbook(); 
Sheet sheet = wb.createSheet("new sheet"); 

//Create a row and put some cells in it 
Row row = sheet.createRow((short)0); 

// Create a cell and put a value in it. 
Cell cell = row.createCell(0); 
cell.setCellValue(1); 

// Write the output to a file 
FileOutputStream fileOut = new FileOutputStream("workbook.xls"); 
wb.write(fileOut); 
fileOut.close(); 

Claramente, la escritura ~ filas 20k (con unos 10-20 columnas en cada fila) me da la "java.lang temida. OutOfMemoryError: espacio de pila Java ".

He intentado aumentar el volumen inicial JVM y el tamaño máximo de almacenamiento dinámico utilizando los parámetros Xms y Xmx como Xms512m y Xmx1024. Todavía no puedo escribir más de 150k filas en el archivo.

Estoy buscando una manera de transmitir a un archivo de Excel en lugar de construir todo el archivo en la memoria antes de escribirlo en el disco, lo que con suerte ahorrará mucho uso de memoria. Cualquier API o solución alternativa sería apreciada, pero estoy restringido al uso de Java. ¡Gracias! :)

+0

Puedes echar un vistazo a: http://stackoverflow.com/questions/6004379/java-write-excel-files-with-poi-event-model – ParagJ

+0

¿Solo 1024m? Prueba 4086 (4 gigas). Ejecutamos 8 gig vms en el trabajo a veces). Las hojas de cálculo están diseñadas de esa manera, ¿pueden incluso funcionar solo en una parte de una hoja de cálculo a la vez? –

Respuesta

6

Todas las API Java existentes intentan compilar todo el documento en la RAM de una vez. Intente escribir un archivo XML que se ajuste al nuevo formato de archivo xslx. Para comenzar, sugiero construir un archivo pequeño en el formato deseado en Excel y guardarlo. Luego ábralo y examine la estructura y reemplace las partes que desea.

Wikipedia tiene un good article about the overall format.

+0

¡Gracias! Pensé en xslx, pero los clientes usan office 2003 y xslx se vuelve problemático. Tampoco pueden instalar ese complemento MS para convertir xslx a xls. Dos palabras: "Enterprise IT": | – Jaskirat

+0

Crea el archivo, ábrelo en Excel y guárdalo con el formato anterior –

+0

Los informes se generarían diariamente/semanalmente, abrir en Excel y guardar con el formato antiguo no es realmente posible. – Jaskirat

0

¿Se produce este problema de memoria cuando inserta datos en la celda, o cuando realiza cálculos/generación de datos?

Si va a cargar archivos en un Excel que consisten en un formato predefinido de plantilla estática, entonces es mejor guardar una plantilla y volver a utilizarla varias veces. Normalmente, los casos de plantilla suceden cuando va a generar un informe de ventas diario, etc.

De lo contrario, cada vez que necesite crear una nueva fila, borde, columna, etc. desde cero.

Hasta ahora, Apache POI es la única opción que encontré.

"Claramente, escribir ~ 20k filas (con unas 10-20 columnas en cada fila) me da el temido" java.lang.OutOfMemoryError: espacio de pila Java "."

"TI de las empresas"

lo que puede hacer es- realizar la inserción de datos por lotes. Cree una tabla quequierak, cada vez que genere 1 página, descanse durante unos segundos, luego continúe con la segunda porción. Si le preocupan los cambios de datos dinámicos durante su tarea de cola, primero puede obtener la clave principal en Excel (ocultando y bloqueando la columna de la vista del usuario). La primera ejecución será insertar la clave principal, luego la segunda fila que se ejecuta en adelante leerá desde el bloc de notas y hará la parte de la tarea por porción.

+0

¿Por qué estamos hablando de colas de tareas? : -S Realmente no entiendo lo que intentas decir. Cuando dices usar plantillas, ¿quieres que use la aplicación jxls o algo por el estilo? – Jaskirat

2

También existe JExcelApi, pero usa más memoria. Creo que deberías crear un archivo .csv y abrirlo en Excel. le permite pasar una gran cantidad de datos, pero no podrá hacer ninguna "magia excel".

+0

¡Los archivos delimitados son, por supuesto, increíblemente livianos! Pero lamentablemente esta no es una opción. No hay magia de Excel ni formato de datos, etc. Necesito escribir archivos .xls. :( – Jaskirat

+1

Creo que deberías tratar de convencer a tu jefe para que use .csv, porque más adelante tendrás un gran problema con el trabajo lento de Excel y toda la aplicación web no podría funcionar, porque 10 personas están generando informes de Excel. – IAdapter

0

Hicimos algo muy similar, la misma cantidad de datos, y tuvimos que cambiar a JExcelapi porque POI es muy pesado en recursos.Prueba JexcelApi, ¡no te arrepentirás cuando tengas que manipular grandes archivos de Excel!

+0

Gracias, haré una prueba de concepto con JExcelAPI y veré cómo se compara con los puntos de interés. Pero la estructura parece similar, así que realmente no veo la diferencia que hará. ¿Me puede dar algunas proporciones, números si es posible? – Jaskirat

+0

Cuando abandonamos el código basado en POI hace bastante tiempo por exactamente los mismos problemas que el suyo, lo siento, no puedo. Sin embargo, acabo de echar un vistazo al servidor de Glassfish que, entre otras aplicaciones, aloja la aplicación que genera los archivos .xls. Tiene -Xmx768m, y nunca tuvimos generaciones de Excel que causaron un error grave. Acabo de generar 10 xls de 45000 líneas * 8 cols y hay 574,423,040 bytes en el montón. Espero que esto ayude – fvu

+0

Múltiples xls no sería un problema, porque una vez que se vacían al archivo, el objeto podría enviarse para la recolección de basura. Entonces, sí, un archivo excel de 45k filas x 8 cols correría bajo 768Mb pero 150,000 x 20 Cols requerirían más de 1GB y no puedo seguir asignando memoria exponencialmente, eso deletrearía mal diseño. : D De todos modos, ¡gracias por todo eso! :) – Jaskirat

3

Eche un vistazo a HSSF serializer del proyecto Cocoon.

The HSSF serializer catches SAX events and creates a spreadsheet in the XLS format used by Microsoft Excel

1

Considere el uso del formato CSV. De esta forma ya no estará limitado por la memoria, sino solo durante la prepoblación de los datos para CSV, pero esto también se puede hacer de manera eficiente, por ejemplo, consultar subconjuntos de filas de DB utilizando, por ejemplo, LIMIT/OFFSET y escribirlo inmediatamente en un archivo en lugar de arrastrar todo el contenido de la tabla DB a la memoria de Java antes de escribir cualquier línea. La limitación de Excel de las filas de cantidad en una "hoja" aumentará a aproximadamente un millón.

Dicho esto, si los datos realmente provienen de un DB, entonces lo reconsideraría mucho si Java es la herramienta adecuada para esto. La mayoría de los DB decentes tienen una función de exportación a CSV que puede hacer esta tarea, sin duda, mucho más eficiente. En el caso de, por ejemplo, MySQL, puede usar el comando LOAD DATA INFILE para esto.

4

Tuve que dividir mis archivos en varios archivos de Excel para superar la excepción de espacio de montón. Me di cuenta de que alrededor de 5k filas con 22 columnas se trataba, así que hice mi lógica para que cada 5k fila terminara el archivo, comenzara una nueva y simplemente numeara los archivos en consecuencia.

En los casos en los que tenía que escribir más de 20k filas, tendría 4+ archivos diferentes que representaran los datos.

+0

Sí, también tuve esa idea, varios archivos de Excel y luego tal vez comprimirlo en un solo archivo. Pero no es lo suficientemente bueno. De todos modos gracias por la sugerencia. – Jaskirat

+0

Si alguna vez se le ocurre una solución, le pregunto si actualiza su pregunta =) Este es un problema muy molesto. –

+0

Estoy enfrentando el mismo problema ahora. Estoy planeando dividir los datos. ¿Pero puedo saber cómo lo estás haciendo? –

9

Intente utilizar SXSSF libro, eso es gran cosa para los enormes documentos xls, su documento de acumulación y no comen RAM en absoluto, becase usando nio

+0

SXSSF no admite el trabajo con XLS https://stackoverflow.com/questions/20678164/saving-sxssf-as-xls-file –

1

Hemos desarrollado una biblioteca de java para este fin y en la actualidad está disponible como proyecto de código abierto https://github.com/jbaliuka/x4j-analytic. Lo usamos para informes operativos. Generamos enormes archivos de Excel, ~ 200,000 deberían funcionar sin problemas, Excel logra abrir esos archivos también. Nuestro código usa POI para cargar la plantilla, pero el contenido generado se transmite directamente al archivo sin XML o la capa del modelo de objetos en la memoria.

Cuestiones relacionadas