Utilizzando LightCells API

Architettura guidata dagli eventi

Aspose.Cells fornisce le LightCells API, progettate principalmente per manipolare i dati delle celle uno per uno senza creare un blocco completo del modello di dati (utilizzando la raccolta Cell ecc.) in memoria. Funziona in una modalità guidata dagli eventi.

Per salvare le cartelle di lavoro, fornisci il contenuto della cella cella per cella durante il salvataggio e il componente lo salva direttamente nel file di output.

Durante la lettura dei file modello, il componente analizza ogni cella e ne fornisce il valore uno per uno.

In entrambe le procedure, un oggetto Cell viene elaborato e quindi eliminato, l’oggetto Workbook non contiene la raccolta. In questa modalità, quindi, la memoria viene salvata durante l’importazione e l’esportazione del file Excel Microsoft che ha un set di dati di grandi dimensioni che altrimenti utilizzerebbe molta memoria.

Anche se LightCells API elabora le celle allo stesso modo per i file XLSX e XLS (in realtà non carica tutte le celle in memoria ma elabora una cella e poi la scarta), risparmia memoria in modo più efficace per i file XLSX rispetto ai file XLS a causa di i diversi modelli di dati e le strutture dei due formati.

Tuttavia,per file XLS , per risparmiare più memoria, gli sviluppatori possono specificare una posizione temporanea per il salvataggio dei dati temporanei generati durante il processo di salvataggio. Comunemente,l’utilizzo di LightCells API per salvare il file XLSX può far risparmiare il 50% o più di memoria piuttosto che usare il modo comune,salvare XLS può far risparmiare circa il 20-40% di memoria.

Scrittura di file Excel di grandi dimensioni

Aspose.Cells fornisce un’interfaccia, LightCellsDataProvider, che deve essere implementata nel programma. L’interfaccia rappresenta il fornitore di dati per il salvataggio di file di fogli di calcolo di grandi dimensioni in modalità leggera.

Quando si salva una cartella di lavoro in questa modalità, startSheet(int) viene controllato quando si salva ogni foglio di lavoro nella cartella di lavoro. Per un foglio, se startSheet(int) è vero, tutti i dati e le proprietà delle righe e delle celle di questo foglio da salvare vengono forniti da questa implementazione. In primo luogo, nextRow() viene chiamato per ottenere l’indice della riga successiva da salvare. Se viene restituito un indice di riga valido (l’indice di riga deve essere in ordine crescente affinché le righe vengano salvate), viene fornito un oggetto Row che rappresenta questa riga per l’implementazione per impostarne le proprietà tramite startRow(Row).

Per una riga, nextCell() viene controllato per primo. Se viene restituito un indice di colonna valido (l’indice di colonna deve essere in ordine crescente per salvare tutte le celle di una riga), viene fornito un oggetto Cell che rappresenta questa cella per impostare i dati e le proprietà tramite startCell(Cell). Dopo aver impostato i dati di questa cella, questa cella viene salvata direttamente nel file del foglio di calcolo generato e la cella successiva verrà controllata ed elaborata.

L’esempio seguente mostra come funziona LightCells API.

Il seguente programma crea un file enorme con 100.000 record in un foglio di lavoro, pieno di dati. Abbiamo aggiunto alcuni collegamenti ipertestuali, valori stringa, valori numerici e anche formule a determinate celle nel foglio di lavoro. Inoltre, abbiamo anche formattato un intervallo di celle.

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

Lettura di file Excel di grandi dimensioni

Aspose.Cells fornisce un’interfaccia, LightCellsDataHandler, che deve essere implementata nel programma. L’interfaccia rappresenta il fornitore di dati per la lettura di file di fogli di calcolo di grandi dimensioni in modalità leggera.

Quando si legge una cartella di lavoro in questa modalità, startSheet() viene controllato durante la lettura di ogni foglio di lavoro nella cartella di lavoro. Per un foglio, se startSheet() restituisce true, tutti i dati e le proprietà delle celle nelle righe e nelle colonne del foglio vengono controllati ed elaborati. Per ogni riga, startRow() viene chiamato per verificare se deve essere elaborato. Se una riga deve essere elaborata, le proprietà della riga vengono lette per prime e gli sviluppatori possono accedere alle sue proprietà con processRow().

Se anche le celle della riga devono essere elaborate, processRow() restituisce true e startCell() viene richiamato per ogni cella esistente nella riga per verificare se deve essere elaborata. In caso affermativo, viene chiamato processCell().

Il seguente codice di esempio illustra questo processo. Il programma legge un file di grandi dimensioni con milioni di record. Ci vuole un po' di tempo per leggere ogni foglio della cartella di lavoro. Il codice di esempio legge il file e recupera il numero totale di celle, il conteggio delle stringhe e il conteggio delle formule per ogni foglio di lavoro.

// 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 classe che implementa l’interfaccia 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;
}
}