The part /docProps/app.xml fail to be saved in the stream with marshaller org.apache.poi.openxml4j

使用 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 语句,如果掌握不好代码流程最好不要用,会给自己刨坑!!!

希望给位越来越好!

猜你喜欢

转载自blog.csdn.net/u013276512/article/details/103043796
今日推荐