使用 poi 保存 excel 内容时,出现类似的错误信息:
Exception in thread "main" org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException: Fail to save: an error occurs while saving the package : The part /docProps/app.xml fail to be saved in the stream with marshaller org.apache.poi.openxml4j.opc.internal.marshallers.DefaultMarshaller@4fbf1942
网上很多都说是 输出流 在关闭的情况下继续使用的结果,目前我还没有找到合适的解决这个 错误的办法。
下面提供一个思路,可以绕过这个 bug 。
我的业务逻辑 读取 模板excel,编写新的 excel ,不可修改 模板 excel 的内容。
思路:
1,拷贝 模板 excel 到一个临时文件(a.excel)
2,根据临时文件填充内容,生成新的 excel (b.excel,确保 和 临时文件的名称不一样!这里很重要)
3,保存 新的 excel
4,关闭 poi 对象
5,删除临时文件 (a.excel)
核心代码如下:
1,拷贝 模板 excel 到一个临时文件(a.excel)
private void copyExcel(String fromexcel, String newexcel) {
XSSFWorkbook wb = null;
FileInputStream fis =null;
FileOutputStream fos = null;
try {
fis = new FileInputStream(fromexcel);
fos = new FileOutputStream(newexcel);
wb = new XSSFWorkbook(fis);
wb.write(fos);
fis.close();
fos.close();
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
wb.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
2,根据临时文件填充内容,生成新的 excel (b.excel,确保 和 临时文件的名称不一样!这里很重要)
String filePath = "D:\\template.xlsx";
String destPath = "D:\\" + System.currentTimeMillis() + ".xlsx";
this.copyExcel(filePath, destPath);//复制一份临时文件,避免修改原模板
XSSFWorkbook wb = new XSSFWorkbook(destPath);
XSSFSheet sheet = wb.getSheetAt(5);//从 0 开始,这里是获取第6个 sheet
//如果 sheet 是 null 需要新建
XSSFRow row = sheet.createRow(14);//根据 rownum 创建 行,这里是第 15 行
XSSFCell firstC = row.createCell(0, CellType.NUMERIC);
firstC.setCellValue("100.00");
XSSFCell nC = row.createCell(5, CellType.NUMERIC);
nC.setCellValue("100.00");
3,保存 新的 excel
FileOutputStream outputStream = new FileOutputStream("D:template2.xlsx");
wb.write(outputStream);
outputStream.close();
4,关闭 poi 对象
wb.close();
5,删除临时文件 (a.excel)
new File(destPath).delete();//删除临时文件
6,import 的所有包(是不是很多朋友在看别人文档的时候找不到这个部分,感到很烦恼,哈哈哈)
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFDataFormat;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
最后,给几个建议,关于所有的 close 操作和删除临时文件操作,最好放到 finally 块中,这样保证它必然会操作;
另外,return 语句、break 语句、continue 语句,如果掌握不好代码流程最好不要用,会给自己刨坑!!!
希望给位越来越好!