Pergunta

Estou procurando escrever um arquivo do Excel (.xls MS Excel 2003) usando o Java. Os arquivos de saída do Excel podem conter ~ 200.000 linhas que planejo dividir o número de folhas (64k linhas por folha, devido ao limite do Excel).

Eu tentei usar as APIs Apache POI, mas parece ser um porco de memória devido ao modelo de objeto API. Sou forçado a adicionar células/folhas ao objeto da pasta de trabalho na memória e somente quando todos os dados forem adicionados, posso escrever a pasta de trabalho em um arquivo! Aqui está uma amostra de como o Apache recomenda que eu escreva arquivos do Excel usando sua 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, escrever ~ 20k linhas (com cerca de 10 a 20 colunas em cada linha) me dá o temido "java.lang.outofmemoryerror: Java Heap Space".

Tentei aumentar o tamanho do HEAPSIGE EMAPTION EM MAX JVM usando os parâmetros XMS e XMX como XMS512M e XMX1024. Ainda não consigo escrever mais de 150k linhas no arquivo.

Estou procurando uma maneira de transmitir para um arquivo do Excel, em vez de criar o arquivo inteiro na memória antes de gravá -lo para o disco, que esperamos economizar muito uso de memória. Qualquer API ou soluções alternativas seriam apreciadas, mas estou restrito ao uso do Java. Obrigado! :)

Foi útil?

Solução

Todas as APIs Java existentes tentam construir o documento inteiro na RAM de uma só vez. Tente escrever um arquivo XML que esteja em conformidade com o novo formato de arquivo XSLX. Para começar, sugiro criar um pequeno arquivo na forma desejada no Excel e salvá -lo. Em seguida, abra -o e examine a estrutura e substitua as peças desejadas.

A Wikipedia tem um Bom artigo sobre o formato geral.

Outras dicas

Tente usar SXSSF pasta de trabalho, isso é uma coisa ótima para documentos XLS enormes, seu documento de construção e não coma Ram, Becase usando o NIO

Eu tive que dividir meus arquivos em vários arquivos do Excel para superar a exceção do espaço da pilha. Imaginei que cerca de 5k linhas com 22 colunas era sobre isso, então eu apenas fiz minha lógica para que a cada linha de 5k eu encerrasse o arquivo, inicie uma nova e apenas numerasse os arquivos de acordo.

Nos casos em que eu tinha 20k + linhas a serem escritas, eu teria mais de 4 arquivos diferentes representando os dados.

Dê uma olhada no Serializador HSSF do projeto Cocoon.

O serializador HSSF captura eventos sax e cria uma planilha no formato XLS usado pelo Microsoft Excel

Lá também há Jexcelapi, mas usa mais memória. Eu acho que você deve criar um arquivo .csv e abri -lo no Excel. Ele permite que você passe muitos dados, mas você não poderá fazer nenhum "Excel Magic".

Considere usar o formato CSV. Dessa forma, você não é mais limitado pela memória -bem, talvez apenas durante a preparação dos dados para o CSV, mas isso também pode ser feito com eficiência, por exemplo, consultas de consultas de linhas de dB usando, por exemplo, LIMIT/OFFSET e escreva imediatamente para arquivar em vez de transportar todo o conteúdo da tabela DB na memória de Java antes de escrever qualquer linha. A limitação do Excel da quantidade de linhas em uma "folha" aumentará para cerca de um milhão.

Dito isto, se os dados forem realmente de um banco de dados, eu reconsideraria se o Java for a ferramenta certa para isso. A maioria dos DBs decentes possui uma função de exportação para CSV que pode fazer essa tarefa, sem dúvida, muito mais eficiente. No caso de, por exemplo, MySQL, você pode usar o LOAD DATA INFILE comando para isso.

We developed a java library for this purpose and currently it is available as open source project https://github.com/jbaliuka/x4j-analytic . We use it for operational reporting. We generate huge Excel files, ~200,000 should work without problems, Excel manages to open such files too. Our code uses POI to load template but generated content is streamed directly to file without XML or Object model layer in memory.

Is this memory issue happen when you insert data into cell, or when you perform data computation/generation?

If you are going to load files into an excel that consist of predefined static template format, then better to save a template and reuse multiple time. Normally template cases happen when you are going to generate daily sales report or etc...

Else, every time you need to create new row, border, column etc from scratch.

So far, Apache POI is the only choice I found.

"Clearly, writing ~20k rows(with some 10-20 columns in each row) gives me the dreaded "java.lang.OutOfMemoryError: Java heap space"."

"Enterprise IT"

What YOU CAN DO is- perform batch data insertion. Create a queuetask table, everytime after generate 1 page, rest for seconds, then continue second portion. If you are worry about the dynamic data changes during your queue task, you can first get the primary key into the excel (by hiding and lock the column from user view). First run will be insert primary key, then second queue run onwards will read out from notepad and do the task portion by portion.

We did something quite similar, same amount of data, and we had to switch to JExcelapi because POI is so heavy on resources. Try JexcelApi, you won't regret it when you have to manipulate big Excel-files!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top