una poi leer importar fuera desde datos con como java excel apache-poi poi-hssf

poi - leer excel desde java como si fuera una base de datos



Cómo insertar una fila entre dos filas en un Excel existente con HSSF(Apache POI) (8)

De alguna manera, logro crear nuevas filas entre dos filas en un archivo existente de Excel. El problema es que algunos de los formatos no se incluyeron a lo largo del desplazamiento de las filas.

Una de ellas es que la fila que se esconde no está relativamente lista durante el turno. Lo que quiero decir es (por ejemplo), las filas del 20 al 30 están ocultas, pero cuando se crean nuevas filas, el formateo sigue ahí. Las filas ocultas también deben moverse durante la inserción / creación de nuevas filas, debe ser de 21 a 31.

Otra cosa es, el otro objeto en la hoja que no está en la celda. Al igual que el cuadro de texto no se mueven después de que se crea la nueva fila. Es como si la posición de estos objetos fuera fija. Pero quiero que se mueva, lo mismo que insertar una nueva fila o pegar fila en Excel. Si hay una función de insertar una nueva fila, házmelo saber.

Esto es lo que tengo ahora, solo un fragmento de mi código.

HSSFWorkbook wb = new HSSFWorkbook(template); //template is the source of file HSSFSheet sheet = wb.getSheet("SAMPLE"); HSSFRow newRow; HSSFCell cellData; int createNewRowAt = 9; //Add the new row between row 9 and 10 sheet.shiftRows(createNewRowAt, sheet.getLastRowNum(), 1, true, false); newRow = sheet.createRow(createNewRowAt); newRow = sheet.getRow(createNewRowAt);

Si copiar y pegar filas es posible, sería una gran ayuda. Pero ya lo pregunto aquí y no puedo encontrar una solución. Así que decidí crear una fila como una solución provisional. Terminé con eso pero teniendo un problema como este.

Cualquier ayuda será muy apreciada. ¡Gracias!


Al hacer referencia a la respuesta de Qwerty , puede evitar inflar el tamaño XL al volver a usar cellStyle . Y cuando el tipo es CELL_TYPE_BLANK , getStringCellValue devuelve "" lugar de null .

private static void copyRow(Sheet worksheet, int sourceRowNum, int destinationRowNum) { // Get the source / new row Row newRow = worksheet.getRow(destinationRowNum); Row sourceRow = worksheet.getRow(sourceRowNum); // If the row exist in destination, push down all rows by 1 else create a new row if (newRow != null) { worksheet.shiftRows(destinationRowNum, worksheet.getLastRowNum(), 1); } else { newRow = worksheet.createRow(destinationRowNum); } // Loop through source columns to add to new row for (int i = 0; i < sourceRow.getLastCellNum(); i++) { // Grab a copy of the old/new cell Cell oldCell = sourceRow.getCell(i); Cell newCell = newRow.createCell(i); // If the old cell is null jump to next cell if (oldCell == null) { newCell = null; continue; } // Use old cell style newCell.setCellStyle(oldCell.getCellStyle()); // If there is a cell comment, copy if (newCell.getCellComment() != null) { newCell.setCellComment(oldCell.getCellComment()); } // If there is a cell hyperlink, copy if (oldCell.getHyperlink() != null) { newCell.setHyperlink(oldCell.getHyperlink()); } // Set the cell data type newCell.setCellType(oldCell.getCellType()); // Set the cell data value switch (oldCell.getCellType()) { case Cell.CELL_TYPE_BLANK: break; case Cell.CELL_TYPE_BOOLEAN: newCell.setCellValue(oldCell.getBooleanCellValue()); break; case Cell.CELL_TYPE_ERROR: newCell.setCellErrorValue(oldCell.getErrorCellValue()); break; case Cell.CELL_TYPE_FORMULA: newCell.setCellFormula(oldCell.getCellFormula()); break; case Cell.CELL_TYPE_NUMERIC: newCell.setCellValue(oldCell.getNumericCellValue()); break; case Cell.CELL_TYPE_STRING: newCell.setCellValue(oldCell.getRichStringCellValue()); break; } } }


Al hacer referencia a la respuesta de Qwerty , si el destRow no es nulo, sheet.shiftRows () cambiará la referencia de destRow a la siguiente fila; así que siempre debemos crear una nueva fila:

if (destRow != null) { sheet.shiftRows(destination, sheet.getLastRowNum(), 1); } destRow = sheet.createRow(destination);


Combiné algunas de las otras respuestas y comentarios en la siguiente implementación, probada con Apache POI v3.9.

Solo tengo un parámetro de rownum porque desplazo la fila de destino y la copio en la nueva fila vacía. Las fórmulas se manejan como se espera, no se copian al pie de la letra, con una excepción: las referencias a las celdas que están sobre la línea copiada no se actualizan; La solución alternativa es reemplazar estas referencias explícitas (si las hay) con referencias calculadas usando INDIRECT() como lo sugiere esta publicación .

protected void copyRow(Sheet worksheet, int rowNum) { Row sourceRow = worksheet.getRow(rowNum); //Save the text of any formula before they are altered by row shifting String[] formulasArray = new String[sourceRow.getLastCellNum()]; for (int i = 0; i < sourceRow.getLastCellNum(); i++) { if (sourceRow.getCell(i) != null && sourceRow.getCell(i).getCellType() == Cell.CELL_TYPE_FORMULA) formulasArray[i] = sourceRow.getCell(i).getCellFormula(); } worksheet.shiftRows(rowNum, worksheet.getLastRowNum(), 1); Row newRow = sourceRow; //Now sourceRow is the empty line, so let''s rename it sourceRow = worksheet.getRow(rowNum + 1); //Now the source row is at rowNum+1 // Loop through source columns to add to new row for (int i = 0; i < sourceRow.getLastCellNum(); i++) { // Grab a copy of the old/new cell Cell oldCell = sourceRow.getCell(i); Cell newCell; // If the old cell is null jump to next cell if (oldCell == null) { continue; } else { newCell = newRow.createCell(i); } // Copy style from old cell and apply to new cell CellStyle newCellStyle = worksheet.getWorkbook().createCellStyle(); newCellStyle.cloneStyleFrom(oldCell.getCellStyle()); newCell.setCellStyle(newCellStyle); // If there is a cell comment, copy if (oldCell.getCellComment() != null) { newCell.setCellComment(oldCell.getCellComment()); } // If there is a cell hyperlink, copy if (oldCell.getHyperlink() != null) { newCell.setHyperlink(oldCell.getHyperlink()); } // Set the cell data type newCell.setCellType(oldCell.getCellType()); // Set the cell data value switch (oldCell.getCellType()) { case Cell.CELL_TYPE_BLANK: break; case Cell.CELL_TYPE_BOOLEAN: newCell.setCellValue(oldCell.getBooleanCellValue()); break; case Cell.CELL_TYPE_ERROR: newCell.setCellErrorValue(oldCell.getErrorCellValue()); break; case Cell.CELL_TYPE_FORMULA: newCell.setCellFormula(formulasArray[i]); break; case Cell.CELL_TYPE_NUMERIC: newCell.setCellValue(oldCell.getNumericCellValue()); break; case Cell.CELL_TYPE_STRING: newCell.setCellValue(oldCell.getRichStringCellValue()); break; default: break; } } // If there are any merged regions in the source row, copy to new row for (int i = 0; i < worksheet.getNumMergedRegions(); i++) { CellRangeAddress cellRangeAddress = worksheet.getMergedRegion(i); if (cellRangeAddress.getFirstRow() == sourceRow.getRowNum()) { CellRangeAddress newCellRangeAddress = new CellRangeAddress(newRow.getRowNum(), (newRow.getRowNum() + (cellRangeAddress.getLastRow() - cellRangeAddress.getFirstRow() )), cellRangeAddress.getFirstColumn(), cellRangeAddress.getLastColumn()); worksheet.addMergedRegion(newCellRangeAddress); } } }

Estoy usando esta implementación en el código de producción.


En cuanto a las fórmulas que se "actualizan" en la nueva fila, dado que toda la copia se produce después del cambio, la fila anterior (ahora un índice arriba de la nueva fila) ya ha cambiado su fórmula, por lo que copiarla a la nueva fila hará la nueva fila hace referencia a las celdas de filas antiguas. Una solución sería analizar las fórmulas ANTES del cambio, luego aplicarlas (una simple matriz de cadenas haría el trabajo. Estoy seguro de que puedes codificar eso en unas pocas líneas).

Al inicio de la función:

ArrayList<String> fArray = new ArrayList<String>(); Row origRow = sheet.getRow(sourceRow); for (int i = 0; i < origRow.getLastCellNum(); i++) { if (origRow.getCell(i) != null && origRow.getCell(i).getCellType() == Cell.CELL_TYPE_FORMULA) fArray.add(origRow.getCell(i).getCellFormula()); else fArray.add(null); }

Luego, al aplicar la fórmula a una celda:

newCell.setCellFormula(fArray.get(i));


Función de ayudante para copiar las filas sin vergüenza adaptadas desde here

import org.apache.poi.hssf.usermodel.*; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.util.CellRangeAddress; import java.io.FileInputStream; import java.io.FileOutputStream; public class RowCopy { public static void main(String[] args) throws Exception{ HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream("c:/input.xls")); HSSFSheet sheet = workbook.getSheet("Sheet1"); copyRow(workbook, sheet, 0, 1); FileOutputStream out = new FileOutputStream("c:/output.xls"); workbook.write(out); out.close(); } private static void copyRow(HSSFWorkbook workbook, HSSFSheet worksheet, int sourceRowNum, int destinationRowNum) { // Get the source / new row HSSFRow newRow = worksheet.getRow(destinationRowNum); HSSFRow sourceRow = worksheet.getRow(sourceRowNum); // If the row exist in destination, push down all rows by 1 else create a new row if (newRow != null) { worksheet.shiftRows(destinationRowNum, worksheet.getLastRowNum(), 1); } else { newRow = worksheet.createRow(destinationRowNum); } // Loop through source columns to add to new row for (int i = 0; i < sourceRow.getLastCellNum(); i++) { // Grab a copy of the old/new cell HSSFCell oldCell = sourceRow.getCell(i); HSSFCell newCell = newRow.createCell(i); // If the old cell is null jump to next cell if (oldCell == null) { newCell = null; continue; } // Copy style from old cell and apply to new cell HSSFCellStyle newCellStyle = workbook.createCellStyle(); newCellStyle.cloneStyleFrom(oldCell.getCellStyle()); ; newCell.setCellStyle(newCellStyle); // If there is a cell comment, copy if (oldCell.getCellComment() != null) { newCell.setCellComment(oldCell.getCellComment()); } // If there is a cell hyperlink, copy if (oldCell.getHyperlink() != null) { newCell.setHyperlink(oldCell.getHyperlink()); } // Set the cell data type newCell.setCellType(oldCell.getCellType()); // Set the cell data value switch (oldCell.getCellType()) { case Cell.CELL_TYPE_BLANK: newCell.setCellValue(oldCell.getStringCellValue()); break; case Cell.CELL_TYPE_BOOLEAN: newCell.setCellValue(oldCell.getBooleanCellValue()); break; case Cell.CELL_TYPE_ERROR: newCell.setCellErrorValue(oldCell.getErrorCellValue()); break; case Cell.CELL_TYPE_FORMULA: newCell.setCellFormula(oldCell.getCellFormula()); break; case Cell.CELL_TYPE_NUMERIC: newCell.setCellValue(oldCell.getNumericCellValue()); break; case Cell.CELL_TYPE_STRING: newCell.setCellValue(oldCell.getRichStringCellValue()); break; } } // If there are are any merged regions in the source row, copy to new row for (int i = 0; i < worksheet.getNumMergedRegions(); i++) { CellRangeAddress cellRangeAddress = worksheet.getMergedRegion(i); if (cellRangeAddress.getFirstRow() == sourceRow.getRowNum()) { CellRangeAddress newCellRangeAddress = new CellRangeAddress(newRow.getRowNum(), (newRow.getRowNum() + (cellRangeAddress.getLastRow() - cellRangeAddress.getFirstRow() )), cellRangeAddress.getFirstColumn(), cellRangeAddress.getLastColumn()); worksheet.addMergedRegion(newCellRangeAddress); } } } }


Lo he implementado en Kotlin así:

fun Sheet.buildRow ( rowNum:Int ) : Row { val templateRow = this.getRow( rowNum ) this.shiftRows( rowNum+1, sheet.lastRowNum, 1 ) val newRow = this.createRow( rowNum+1 ) templateRow.cellIterator().forEach { newRow.createCell( it.columnIndex ).cellStyle = it.cellStyle } return templateRow }

No copia los valores de celda, solo el formato. Debería ser aplicable a Java también.


Me encontré con el mismo problema recientemente. Tuve que insertar nuevas filas en un documento con filas ocultas y tuve que enfrentar los mismos problemas. Después de algunas búsquedas y algunos correos electrónicos en apache poi list, parece un error en shiftrows () cuando un documento tiene filas ocultas.


Para las personas que buscan insertar una fila entre dos filas en un Excel existente con XSSF (Apache POI), ya existe un método "copyRows" implementado en XSSFSheet.

import org.apache.poi.ss.usermodel.CellCopyPolicy; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.FileInputStream; import java.io.FileOutputStream; public class App2 throws Exception{ public static void main(String[] args){ XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream("input.xlsx")); XSSFSheet sheet = workbook.getSheet("Sheet1"); sheet.copyRows(0, 2, 3, new CellCopyPolicy()); FileOutputStream out = new FileOutputStream("output.xlsx"); workbook.write(out); out.close(); } }