Utilizando la API de LightCells
Arquitectura Orientada a Eventos
Aspose.Cells proporciona la API de LightCells, diseñada principalmente para manipular los datos de las celdas una por una sin construir un modelo completo de datos (usando la colección de Celdas, etc.) en la memoria. Funciona en modo de eventos.
Para guardar libros de trabajo, proporciona el contenido de la celda una por una al guardar, y el componente lo guarda directamente en el archivo de salida.
Al leer archivos de plantilla, el componente analiza cada celda y proporciona su valor uno por uno.
En ambos procedimientos, se procesa un objeto de Celda y luego se descarta, el objeto de Libro de trabajo no retiene la colección. En este modo, por lo tanto, se ahorra memoria al importar y exportar archivos de Microsoft Excel que tienen un gran conjunto de datos que de otra manera usaría mucha memoria.
Aunque la API de LightCells procesa las celdas de la misma manera para archivos XLSX y XLS (no carga todas las celdas en la memoria sino que procesa una celda y luego la descarta), ahorra memoria de manera más efectiva para archivos XLSX que para archivos XLS debido a los diferentes modelos de datos y estructuras de los dos formatos.
Sin embargo, para archivos XLS, para ahorrar más memoria, los desarrolladores pueden especificar una ubicación temporal para guardar los datos temporales generados durante el proceso de Guardar. Comúnmente, utilizando la API de LightCells para guardar archivos XLSX se puede ahorrar un 50% o más de memoria que utilizando el método común, guardando XLS puede ahorrar alrededor del 20-40% de memoria.
Escribiendo Archivos de Excel Grandes
Aspose.Cells proporciona una interfaz, LightCellsDataProvider, que debe ser implementada en tu programa. La interfaz representa un proveedor de datos para guardar archivos de hojas de cálculo grandes en modo ligero.
Al guardar un libro de trabajo en este modo, se comprueba startSheet(int) al guardar cada hoja de cálculo en el libro. Para una hoja, si startSheet(int) es verdadero, entonces todos los datos y propiedades de las filas y celdas de esta hoja que se van a guardar son proporcionados por esta implementación. En primer lugar, se llama a nextRow() para obtener el próximo índice de fila que se guardará. Si se devuelve un índice de fila válido (el índice de fila debe estar en orden ascendente para las filas que se van a guardar), entonces se proporciona un objeto Row que representa esta fila para que la implementación establezca sus propiedades mediante startRow(Row).
Para una fila, se comprueba primero nextCell(). Si se devuelve un índice de columna válido (el índice de columna debe estar en orden ascendente para todas las celdas de una fila que se van a guardar), entonces se proporciona un objeto Cell que representa esta celda para establecer los datos y propiedades mediante startCell(Cell). Después de que se establecen los datos de esta celda, esta se guarda directamente en el archivo de hoja de cálculo generado y se comprueba y procesa la siguiente celda.
El siguiente ejemplo muestra cómo funciona la API LightCells.
El siguiente programa crea un archivo enorme con 100,000 registros en una hoja de cálculo, rellenada con datos. Hemos agregado algunos hipervínculos, valores de cadena, valores numéricos y también fórmulas a ciertas celdas en la hoja de cálculo. Además, hemos formateado un rango de celdas también.
// For complete examples and data files, please go to https://github.com/aspose-cells/Aspose.Cells-for-Java | |
public class LightCellsDataProviderDemo implements LightCellsDataProvider { | |
private final int sheetCount; | |
private final int maxRowIndex; | |
private final int maxColIndex; | |
private int rowIndex; | |
private int colIndex; | |
private final Style style1; | |
private final Style style2; | |
public LightCellsDataProviderDemo(Workbook wb, int sheetCount, int rowCount, int colCount) { | |
// set the variables/objects | |
this.sheetCount = sheetCount; | |
this.maxRowIndex = rowCount - 1; | |
this.maxColIndex = colCount - 1; | |
// add new style object with specific formattings | |
style1 = wb.createStyle(); | |
Font font = style1.getFont(); | |
font.setName("MS Sans Serif"); | |
font.setSize(10); | |
font.setBold(true); | |
font.setItalic(true); | |
font.setUnderline(FontUnderlineType.SINGLE); | |
font.setColor(Color.fromArgb(0xffff0000)); | |
style1.setHorizontalAlignment(TextAlignmentType.CENTER); | |
// create another style | |
style2 = wb.createStyle(); | |
style2.setCustom("#,##0.00"); | |
font = style2.getFont(); | |
font.setName("Copperplate Gothic Bold"); | |
font.setSize(8); | |
style2.setPattern(BackgroundType.SOLID); | |
style2.setForegroundColor(Color.fromArgb(0xff0000ff)); | |
style2.setBorder(BorderType.TOP_BORDER, CellBorderType.THICK, Color.getBlack()); | |
style2.setVerticalAlignment(TextAlignmentType.CENTER); | |
} | |
public boolean isGatherString() { | |
return false; | |
} | |
public int nextCell() { | |
if (colIndex < maxColIndex) { | |
colIndex++; | |
return colIndex; | |
} | |
return -1; | |
} | |
public int nextRow() { | |
if (rowIndex < maxRowIndex) { | |
rowIndex++; | |
colIndex = -1; // reset column index | |
if (rowIndex % 1000 == 0) { | |
System.out.println("Row " + rowIndex); | |
} | |
return rowIndex; | |
} | |
return -1; | |
} | |
public void startCell(Cell cell) { | |
if (rowIndex % 50 == 0 && (colIndex == 0 || colIndex == 3)) { | |
// do not change the content of hyperlink. | |
return; | |
} | |
if (colIndex < 10) { | |
cell.putValue("test_" + rowIndex + "_" + colIndex); | |
cell.setStyle(style1); | |
} else { | |
if (colIndex == 19) { | |
cell.setFormula("=Rand() + test!L1"); | |
} else { | |
cell.putValue(rowIndex * colIndex); | |
} | |
cell.setStyle(style2); | |
} | |
} | |
public void startRow(Row row) { | |
row.setHeight(25); | |
} | |
public boolean startSheet(int sheetIndex) { | |
if (sheetIndex < sheetCount) { | |
// reset row/column index | |
rowIndex = -1; | |
colIndex = -1; | |
return true; | |
} | |
return false; | |
} | |
} |
// For complete examples and data files, please go to https://github.com/aspose-cells/Aspose.Cells-for-Java | |
public class Demo { | |
private static final String OUTPUT_FILE_PATH = Utils.getDataDir(LightCellsDataProviderDemo.class); | |
public static void main(String[] args) throws Exception { | |
// Instantiate a new Workbook | |
Workbook wb = new Workbook(); | |
// set the sheet count | |
int sheetCount = 1; | |
// set the number of rows for the big matrix | |
int rowCount = 100000; | |
// specify the worksheet | |
for (int k = 0; k < sheetCount; k++) { | |
Worksheet sheet = null; | |
if (k == 0) { | |
sheet = wb.getWorksheets().get(k); | |
sheet.setName("test"); | |
} else { | |
int sheetIndex = wb.getWorksheets().add(); | |
sheet = wb.getWorksheets().get(sheetIndex); | |
sheet.setName("test" + sheetIndex); | |
} | |
Cells cells = sheet.getCells(); | |
// set the columns width | |
for (int j = 0; j < 15; j++) { | |
cells.setColumnWidth(j, 15); | |
} | |
// traverse the columns for adding hyperlinks and merging | |
for (int i = 0; i < rowCount; i++) { | |
// The first 10 columns | |
for (int j = 0; j < 10; j++) { | |
if (j % 3 == 0) { | |
cells.merge(i, j, 1, 2, false, false); | |
} | |
if (i % 50 == 0) { | |
if (j == 0) { | |
sheet.getHyperlinks().add(i, j, 1, 1, "test!A1"); | |
} else if (j == 3) { | |
sheet.getHyperlinks().add(i, j, 1, 1, "http://www.google.com"); | |
} | |
} | |
} | |
// The second 10 columns | |
for (int j = 10; j < 20; j++) { | |
if (j == 12) { | |
cells.merge(i, j, 1, 3, false, false); | |
} | |
} | |
} | |
} | |
// Create an object with respect to LightCells data provider | |
LightCellsDataProviderDemo dataProvider = new LightCellsDataProviderDemo(wb, 1, rowCount, 20); | |
// Specify the XLSX file's Save options | |
OoxmlSaveOptions opt = new OoxmlSaveOptions(); | |
// Set the data provider for the file | |
opt.setLightCellsDataProvider(dataProvider); | |
// Save the big file | |
wb.save(OUTPUT_FILE_PATH + "/DemoTest.xlsx", opt); | |
} | |
} |
Lectura de archivos Excel grandes
Aspose.Cells proporciona una interfaz, LightCellsDataHandler, que debe ser implementada en su programa. La interfaz representa el proveedor de datos para la lectura de archivos de hojas de cálculo grandes en modo liviano.
Al leer un libro de trabajo en este modo, se comprueba startSheet() al leer cada hoja de cálculo en el libro. Para una hoja, si startSheet() devuelve verdadero, entonces se comprueban y procesan todos los datos y propiedades de las celdas en las filas y columnas de la hoja. Para cada fila, se llama a startRow() para comprobar si necesita ser procesada. Si una fila necesita ser procesada, primero se leen las propiedades de la fila y los desarrolladores pueden acceder a sus propiedades con processRow().
Si las celdas de la fila también necesitan ser procesadas, entonces processRow() devuelve verdadero y se llama a startCell() para cada celda existente en la fila para comprobar si necesita ser procesada. Si lo hace, se llama a processCell().
El siguiente código de ejemplo ilustra este proceso. El programa lee un archivo grande con millones de registros. Se tarda un poco en leer cada hoja de cálculo en el libro. El código de ejemplo lee el archivo y recupera el número total de celdas, conteo de cadenas y conteo de fórmulas para cada hoja de cálculo.
// For complete examples and data files, please go to https://github.com/aspose-cells/Aspose.Cells-for-Java | |
public class LightCellsTest1 { | |
public static void main(String[] args) throws Exception { | |
String dataDir = Utils.getDataDir(LightCellsTest1.class); | |
LoadOptions opts = new LoadOptions(); | |
LightCellsDataHandlerVisitCells v = new LightCellsDataHandlerVisitCells(); | |
opts.setLightCellsDataHandler((LightCellsDataHandler) v); | |
Workbook wb = new Workbook(dataDir + "LargeBook1.xlsx", opts); | |
int sheetCount = wb.getWorksheets().getCount(); | |
System.out.println("Total sheets: " + sheetCount + ", cells: " + v.cellCount + ", strings: " + v.stringCount | |
+ ", formulas: " + v.formulaCount); | |
} | |
} |
Una clase que implementa la interfaz LightCellsDataHandler
// For complete examples and data files, please go to https://github.com/aspose-cells/Aspose.Cells-for-Java | |
public class LightCellsDataHandlerVisitCells implements LightCellsDataHandler { | |
public int cellCount; | |
public int formulaCount; | |
public int stringCount; | |
public LightCellsDataHandlerVisitCells() { | |
this.cellCount = 0; | |
this.formulaCount = 0; | |
this.stringCount = 0; | |
} | |
public int cellCount() { | |
return cellCount; | |
} | |
public int formulaCount() { | |
return formulaCount; | |
} | |
public int stringCount() { | |
return stringCount; | |
} | |
public boolean startSheet(Worksheet sheet) { | |
System.out.println("Processing sheet[" + sheet.getName() + "]"); | |
return true; | |
} | |
public boolean startRow(int rowIndex) { | |
return true; | |
} | |
public boolean processRow(Row row) { | |
return true; | |
} | |
public boolean startCell(int column) { | |
return true; | |
} | |
public boolean processCell(Cell cell) { | |
this.cellCount = this.cellCount + 1; | |
if (cell.isFormula()) { | |
this.formulaCount = this.formulaCount + 1; | |
} else if (cell.getType() == CellValueType.IS_STRING) { | |
this.stringCount = this.stringCount + 1; | |
} | |
return false; | |
} | |
} |