用例:我有一个用excel实现的成本计算器。我必须在工作表的输入单元格中插入大量输入,并从同一工作表获取输出。我有3张excel表格,大小约为3MB。 Excel工作表为.xlsm格式。
使用的技术:Java 1.8和Apache POI 4.0.1
问题:将输入值写入大于3MB的excel文件的速度很快(大约12个输入大约需要10秒)。但是对excel文件执行的相同操作是<3MB太慢(仅一次输入就需要10秒)。
我似乎这里有人说要使用SXSSFWorkbook。我用它替换了XSSFWorkbook,但是它给了我Null Pointer Exception。另外,它用于大于100MB的大型Excel工作表,对吧?
用于编写值的代码:
public void setData1(String filePath, String sheetName, int rowNum, int colNum, Object data) throws IOException {
File file = new File(filePath);
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
} catch (FileNotFoundException e) {
Messages.terminate(file.getName() + " file is missing.");
}
Workbook workbook = new XSSFWorkbook(fis);
Sheet sheet = workbook.getSheet(sheetName);
Row row = sheet.getRow(rowNum);
Cell cell = row.getCell(colNum);
if(data instanceof Integer) {
cell.setCellValue((int)data);
}
else if (data instanceof String) {
cell.setCellValue(String.valueOf((String) data));
}
else if(data instanceof Double) {
if((double)data == Math.floor((double)data)) {
cell.setCellValue((int)Math.floor((double)data));
}
else {
cell.setCellValue((double)data);
}
}
FileOutputStream fos = new FileOutputStream(new File(filePath));
BaseFormulaEvaluator.evaluateAllFormulaCells(workbook);
workbook.write(fos);
workbook.close();
fos.close();
fis.close();
}
答案 0 :(得分:0)
以下代码仅打开工作簿一次,而不是针对输入的每个值重复打开和关闭工作簿:
public void setData1(Workbook workbook, FileOutputStream fos, String filePath, String sheetName, int rowNum, int colNum, Object data) throws IOException {
Sheet sheet = workbook.getSheet(sheetName);
Row row = sheet.getRow(rowNum);
Cell cell = row.getCell(colNum);
if(data instanceof Integer) {
cell.setCellValue((int)data);
}
else if (data instanceof String) {
cell.setCellValue(String.valueOf((String) data));
}
else if(data instanceof Double) {
if((double)data == Math.floor((double)data)) {
cell.setCellValue((int)Math.floor((double)data));
}
else {
cell.setCellValue((double)data);
}
}
BaseFormulaEvaluator.evaluateAllFormulaCells(workbook); //I don't have enough context here, but if it does not cause any logical problems, move this line to *
workbook.write(fos);
}
public void callsSetData1() {
object Data = new Object()
File file = new File(filePath);
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
} catch (FileNotFoundException e) {
Messages.terminate(file.getName() + " file is missing.");
}
Workbook workbook = new XSSFWorkbook(fis);
FileOutputStream fos = new FileOutputStream(new File(filePath));
//*
for(i = 0; i < 10; i++) {
setData1(workbook, fos, "R:\andom\File\Path", "randomSheetName",0,0, data); //I'm assuming you are calling setData1() multiple times, as I do not have the code of the method that calls it, I've just used a for-loop for now
}
workbook.close();
fos.close();
fis.close();
}
我建议您还提供调用setData1
的方法的代码。由于我没有这个,callsSetData1
可能包含一些逻辑错误。
重点是,在调用setData1
并将其作为参数传递的方法中,只应打开和关闭工作簿一次。这应该有助于延迟。
唯一的次要缺点是,如果您使用多种不同的方法调用setData1
,则会有几行代码。