Использование LightCells API
Архитектура, управляемая событиями
Aspose.Cells предоставляет LightCells API, в основном предназначенные для манипулирования данными ячеек один за другим без создания в памяти полного блока модели данных (с использованием коллекции Cell и т. д.). Работает в событийно-ориентированном режиме.
Чтобы сохранить рабочие книги, предоставьте содержимое ячейки ячейка за ячейкой при сохранении, и компонент сохранит его непосредственно в выходной файл.
При чтении файлов шаблонов компонент анализирует каждую ячейку и выдает их значения одну за другой.
В обеих процедурах обрабатывается и затем отбрасывается один объект Cell, объект Workbook не содержит коллекции. Таким образом, в этом режиме экономится память при импорте и экспорте Microsoft файла Excel с большим набором данных, который в противном случае потребовал бы много памяти.
Несмотря на то, что LightCells API одинаково обрабатывает ячейки для файлов XLSX и XLS (на самом деле он не загружает все ячейки в память, а обрабатывает одну ячейку, а затем отбрасывает ее), он экономит память более эффективно для файлов XLSX, чем для файлов XLS из-за различные модели данных и структуры двух форматов.
Однако,для файлов XLS , чтобы сэкономить больше памяти, разработчики могут указать временное место для сохранения временных данных, созданных в процессе сохранения. Обычно,использование LightCells API для сохранения файла XLSX может сэкономить 50% или более памяти чем обычным путем,сохранение XLS может сэкономить около 20-40% памяти.
Запись больших файлов Excel
Aspose.Cells предоставляет интерфейс LightCellsDataProvider, который необходимо реализовать в вашей программе. Интерфейс представляет собой поставщика данных для сохранения больших файлов электронных таблиц в облегченном режиме.
При сохранении книги в этом режиме startSheet(int) проверяется при сохранении каждого листа в книге. Для одного листа, если startSheet(int) имеет значение true, то все данные и свойства строк и ячеек этого листа для сохранения предоставляются этой реализацией. Во-первых, nextRow() вызывается для сохранения индекса следующей строки. Если возвращается допустимый индекс строки (индекс строки должен быть в порядке возрастания, чтобы строки были сохранены), то объект Row, представляющий эту строку, предоставляется для реализации, чтобы установить его свойства с помощью startRow(Row).
Для одной строки сначала проверяется nextCell(). Если возвращается допустимый индекс столбца (индекс столбца должен быть в порядке возрастания для сохранения всех ячеек одной строки), то объект Cell, представляющий эту ячейку, предоставляется для установки данных и свойств с помощью startCell(Cell). После того, как данные этой ячейки установлены, эта ячейка сохраняется непосредственно в сгенерированном файле электронной таблицы, а следующая ячейка будет проверена и обработана.
В следующем примере показано, как работает LightCells API.
Следующая программа создает огромный файл со 100 000 записей на листе, заполненном данными. Мы добавили некоторые гиперссылки, строковые значения, числовые значения, а также формулы в определенные ячейки на листе. Кроме того, мы также отформатировали ряд ячеек.
// 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); | |
} | |
} |
Чтение больших файлов Excel
Aspose.Cells предоставляет интерфейс LightCellsDataHandler, который необходимо реализовать в вашей программе. Интерфейс представляет собой поставщик данных для чтения больших файлов электронных таблиц в облегченном режиме.
При чтении рабочей книги в этом режиме startSheet() проверяется при чтении каждого рабочего листа в рабочей книге. Для листа, если startSheet() возвращает true, то все данные и свойства ячеек в строках и столбцах листа проверяются и обрабатываются. Для каждой строки вызывается startRow(), чтобы проверить, нужно ли ее обрабатывать. Если строку необходимо обработать, сначала считываются свойства строки, и разработчики могут получить доступ к ее свойствам с помощью processRow().
Если ячейки строки также необходимо обработать, то processRow() возвращает true, а startCell() вызывается для каждой существующей ячейки в строке, чтобы проверить, нужно ли ее обрабатывать. Если да, то вызывается processCell().
Следующий пример кода иллюстрирует этот процесс. Программа читает большой файл с миллионами записей. На чтение каждого листа рабочей тетради уходит немного времени. Пример кода считывает файл и извлекает общее количество ячеек, количество строк и количество формул для каждого рабочего листа.
// 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); | |
} | |
} |
Класс, реализующий интерфейс 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; | |
} | |
} |