POI——動態修改Excel模板下拉框
阿新 • • 發佈:2019-02-11
需求:
在匯入頁面放置了的Excel模板,最開始內容是寫死的。現在需要將資料庫的資料動態的載入到excel模板的下拉框中。使用的為poi.xssf
相關jar包
poi-3.10-FINAL-20140208.jar
poi-ooxml-3.10-FINAL-20140208.jar
poi-ooxml-schemas-3.10-FINAL-20140208.jar
方法思路:
讀取Excel模板檔案——從資料庫讀取下拉框所需資料——將讀取出的資料先寫入另一張sheet(資料來源sheet)——為展示資料的sheet設定資料驗證規則,增加資料驗證——將更新後的workbook儲存到新的path
該方法返回path到controller,之後經過檔案流處理即可實現模板的下載
/** * update poi select * @param realPath * @author cloudHeart * @throws FileNotFoundException */ public String setPOISelect(String realPath) throws FileNotFoundException { InputStream is = null; XSSFWorkbook wb = null; //讀取檔案 try { is = new FileInputStream(new File(realPath)); wb = new XSSFWorkbook(is); XSSFSheet sheet = wb.getSheetAt(0); int rows = sheet.getLastRowNum() + 1; //行數 System.out.println("rows = " + rows); //設定部門下拉框 ArrayList<String> orgNameList = new ArrayList<>(30); List<Org> orgList = dao.findAll(); for (Org one : orgList) { String name = one.getOrgName(); orgNameList.add(name); } String[] orgArray = orgNameList.toArray(new String[orgNameList.size()]); wb = selectUpda're(wb, sheet, orgArray, 2, 9, 1, 1, 2, 'B');
//由於POI開啟讀取檔案後再儲存時bug問題, 只能重新定義一個新的Excel寫入資料 String subPath = realPath.substring(0, realPath.lastIndexOf("\\")); String path = subPath.concat("\\模板"); createExcel(wb, path); return path; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return realPath; }
因為可能更新多個不同型別下拉框資料,所以設定了selectNum和selectAlpha
/**
* @param wb XSSFWorkbook物件
* @param realSheet 需要操作的sheet物件
* @param datas 下拉的列表資料
* @param startRow 開始行
* @param endRow 結束行
* @param startCol 開始列
* @param endCol 結束列
* @param selectMum 資料來源sheet的下拉資料來源對應列
* @param selectAlpha 資料來源sheet的下拉資料對應字母
* @return
* @throws Exception
*/
public XSSFWorkbook dropDownList2003(XSSFWorkbook wb, XSSFSheet realSheet, String[] datas, int startRow, int endRow,
int startCol, int endCol, int selectNum ,char seletAlpha)
throws Exception {
String hiddenSheetName = "字典項";
// XSSFWorkbook workbook = (XSSFWorkbook) wb;
// 資料來源sheet 原模板已有專門的資料來源sheet,沒有的話用 wb.createSheet("名稱")建立一個即可
XSSFSheet hidden = (XSSFSheet) wb.getSheetAt(1);
// 資料來源sheet頁不顯示
wb.setSheetHidden(1, true);
// 將下拉列表的資料放在資料來源sheet上
XSSFRow row = null;
XSSFCell cell = null;
for (int i = 0, length = datas.length; i < length; i++) {
//row = hidden.createRow(i);
row = hidden.getRow(i);
if(row == null || ("").equals(row)){
row = hidden.createRow(i);
}
cell = row.getCell(selectNum-1);
if(cell == null || ("").equals(cell)){
cell = row.createCell(selectNum -1);
}
cell.setCellValue(datas[i]);
}
//建立規則
XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper(realSheet);
XSSFDataValidationConstraint dvConstraint = (XSSFDataValidationConstraint) dvHelper
.createFormulaListConstraint(hiddenSheetName + "!$"+seletAlpha+"$1:$"+seletAlpha+"" + datas.length);
//DataValidationConstraint constraint = DVConstraint.createFormulaListConstraint(hiddenSheetName + "!$"+seletAlpha+"$1:$"+seletAlpha+"" + datas.length);
CellRangeAddressList addressList = null; // 設定在哪個單元格生效
DataValidation validation = null; // 建立規則物件
row = null;
cell = null;
// 迴圈指定單元格下拉資料
for (int i = startRow; i <= endRow; i++) {
row = (XSSFRow) realSheet.getRow(i);
cell = row.getCell(startCol);
addressList = new CellRangeAddressList(i, i, startCol, endCol);
validation = dvHelper.createValidation(dvConstraint, addressList);
//validation = new HSSFDataValidation(addressList, constraint);
//HSSF和XSSF的建立資料驗證有區別 realSheet.addValidationData(validation);
realSheet.addValidationData(validation);
}
return wb;
}
根據路徑建立Excel
/**
* 根據路徑建立Excel
* @param workbook
* @param path
*/
public void createExcel(Workbook workbook, String path) {
FileOutputStream fileOut = null;
try {
fileOut = new FileOutputStream(path);
workbook.write(fileOut);
} catch (Exception e) {
logger.error("Error create excel: ", e.getMessage());
} finally {
try {
if(fileOut != null) {
fileOut.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}