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 語句,如果掌握不好代碼流程最好不要用,會給自己刨坑!!!

 

希望給位越來越好!

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章