poi功能很強大,這裏用來實現一個excel級聯的下拉框
package poiExcel;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.junit.Test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author : haojiangtao
* @Description :
* @Date : 14:20 2019/11/14
* @Modify :
**/
public class MyExcel {
private static final String PRICE_SHEET_NAME = "PRICE_SHEET_NAME";
private static final String MODEL_TYPE_SHEET_NAME = "MODEL_TYPE_SHEET_NAME";
private static final int XLS_MAX_ROW = 65535; //0開始
@Test
public void cascadeExcel() {
List<String> headers = Arrays.asList("耗材類型", "品牌型號", "數量", "價格");
List<Integer> priceList = Arrays.asList(50, 100, 1000, 1200);
List<String> typeList = Arrays.asList("鼠標", "鍵盤", "電腦");
Map<String, List<String>> typeModelMap = new HashMap<>();
typeModelMap.put("鼠標", Arrays.asList("雷蛇鼠標", "賽睿鼠標", "櫻桃鼠標"));
typeModelMap.put("鍵盤", Arrays.asList("87鍵盤", "104鍵盤"));
typeModelMap.put("電腦", Arrays.asList("惠普", "戴爾"));
MyExcel.createStoreInExcelTemplate("f:/類型型號.xls", headers,
priceList, typeList, typeModelMap);
}
private static void createStoreInExcelTemplate(String filePath, List<String> headers, List<Integer> priceList,
List<String> typeList, Map<String, List<String>> typeModelMap) {
FileOutputStream out = null;
File file;
try {
//指定文件
file = new File(filePath);
//文件流
out = new FileOutputStream(file);
//工作簿
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet mainSheet = wb.createSheet("sheet1");
//將存儲下拉框數據的sheet隱藏
//wb.setSheetHidden(2, true);
HSSFSheet typeModelSheet = wb.createSheet("sheet2");
HSSFSheet priceSheet = wb.createSheet("sheet3");
//初始化表頭數據
initHeaders(wb, mainSheet, headers);
//價格下拉框,類型型號下拉框
initPrice(wb, priceSheet, priceList);
initTypeAndModel(wb, typeModelSheet, typeList, typeModelMap);
//在主sheet裏面設置下拉框校驗
initSheetNameMapping(mainSheet);
//在主sheet裏面設置數量校驗
initCount(mainSheet);
out.flush();
wb.write(out);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out != null) {
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 初始化表頭
*
* @param wb
* @param mainSheet
* @param headers
*/
private static void initHeaders(HSSFWorkbook wb, HSSFSheet mainSheet, List<String> headers) {
//表頭樣式,居中加粗
HSSFCellStyle style = wb.createCellStyle();
boldStyle(wb, centerStyle(style));
//生成sheet1內容,第一個sheet的第一行爲標題
HSSFRow rowFirst = mainSheet.createRow(0);
//凍結第一行
mainSheet.createFreezePane(0, 1, 0, 1);
//寫標題
for (int i = 0; i < headers.size(); i++) {
HSSFCell cell = rowFirst.createCell(i); //獲取第一行的每個單元格
mainSheet.setColumnWidth(i, 4000); //設置每列的列寬
cell.setCellStyle(style); //加樣式
cell.setCellValue(headers.get(i)); //往單元格里寫數據
}
}
/**
* 居中
*
* @param cellStyle
* @return
*/
public static CellStyle centerStyle(CellStyle cellStyle) {
// 創建一個居中格式
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
return cellStyle;
}
/**
* 加粗
*
* @param workbook
* @param cellStyle
* @return
*/
public static CellStyle boldStyle(Workbook workbook, CellStyle cellStyle) {
Font fontStyle = workbook.createFont();
fontStyle.setFontName("微軟雅黑");
fontStyle.setFontHeightInPoints((short) 12);
fontStyle.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
cellStyle.setFont(fontStyle);
return cellStyle;
}
/**
* 設置價格下拉框1.設置值 2.設置下拉框
*
* @param wb
* @param priceSheet
* @param priceList
*/
private static void initPrice(HSSFWorkbook wb, HSSFSheet priceSheet, List<Integer> priceList) {
writePrice(wb, priceSheet, priceList);
initPriceNameMapping(wb, priceSheet.getSheetName(), priceList.size());
}
/**
* 設置價格下拉框1.設置值
*
* @param wb
* @param priceSheet
* @param priceList
*/
private static void writePrice(HSSFWorkbook wb, HSSFSheet priceSheet, List<Integer> priceList) {
for (int i = 0; i < priceList.size(); i++) {
HSSFRow row = priceSheet.createRow(i);
HSSFCell cell = row.createCell(0);
cell.setCellValue(priceList.get(i));
}
}
/**
* 設置價格下拉框2.設置下拉框
*
* @param workbook
* @param sheetName
* @param priceCount
*/
private static void initPriceNameMapping(HSSFWorkbook workbook, String sheetName, int priceCount) {
Name name = workbook.createName();
name.setNameName(PRICE_SHEET_NAME);
name.setRefersToFormula(sheetName + "!$A$1:$A$" + priceCount);
}
/**
* 設置類型型號級聯下拉框 1.設置類型值 2.設置型號下拉框 3.設置類型級聯下拉框
*
* @param workbook
* @param tmSheet
* @param typeList
* @param typeModelMap
*/
private static void initTypeAndModel(HSSFWorkbook workbook, HSSFSheet tmSheet,
List<String> typeList, Map<String, List<String>> typeModelMap) {
writeTypes(workbook, tmSheet, typeList);
writeModels(workbook, tmSheet, typeList, typeModelMap);
initTypeNameMapping(workbook, tmSheet.getSheetName(), typeList.size());
}
/**
* 設置類型型號級聯下拉框 1.設置類型值
*
* @param workbook
* @param modelTypeSheet
* @param typeList
*/
private static void writeTypes(HSSFWorkbook workbook, HSSFSheet modelTypeSheet, List<String> typeList) {
HSSFRow row = modelTypeSheet.getRow(0) == null ? modelTypeSheet.createRow(0)
: modelTypeSheet.createRow(0);
HSSFCellStyle cellStyle = workbook.createCellStyle();
boldStyle(workbook, cellStyle);
//if (CollectionUtils.isNotEmpty(modelList)) {
if (null != typeList) {
for (int i = 0; i < typeList.size(); i++) {
HSSFCell cell = row.getCell(i) == null ? row.createCell(i) : row.getCell(i);
cell.setCellValue(typeList.get(i));
cell.setCellStyle(cellStyle);
}
}
}
/**
* 設置類型型號級聯下拉框 2.設置型號下拉框
*
* @param workbook
* @param tmSheet
* @param typeList
* @param typeModelMap
*/
private static void writeModels(HSSFWorkbook workbook, HSSFSheet tmSheet,
List<String> typeList, Map<String, List<String>> typeModelMap) {
for (int i = 0; i < typeList.size(); i++) {
String typeName = typeList.get(i);
List<String> modelList = typeModelMap.get(typeName);
//if (CollectionUtils.isNotEmpty(modelList)) {
if (null != modelList) {
for (int j = 0; j < modelList.size(); j++) {
HSSFRow row = tmSheet.getRow(j + 1) == null ? tmSheet.createRow(j + 1)
: tmSheet.getRow(j + 1);
HSSFCell cell = row.getCell(i) == null ? row.createCell(i) : row.getCell(i);
cell.setCellValue(modelList.get(j));
}
}
initModelNameMapping(workbook, tmSheet.getSheetName(), typeName, i, modelList.size());
}
}
private static void initModelNameMapping(HSSFWorkbook workbook, String tmSheetName,
String typeName, int referCol, int modelCount) {
Name name = workbook.createName();
name.setNameName(typeName);
//modelCount + 1 = modelCount + 2 -1
name.setRefersToFormula(tmSheetName + "!$" + getColumnName(referCol) +
"$2:$" + getColumnName(referCol) + "$" + (modelCount + 1));
}
/**
* 3.設置類型級聯下拉框
*
* @param workbook
* @param tmSheetName
* @param typeCount
*/
private static void initTypeNameMapping(HSSFWorkbook workbook, String tmSheetName, int typeCount) {
Name name = workbook.createName();
name.setNameName(MODEL_TYPE_SHEET_NAME);
name.setRefersToFormula(tmSheetName + "!$A$1:$" + getColumnName(typeCount - 1) + "$1");
}
/**
* 轉換爲A,B,C,D的列
* @param index
* @return
*/
public static String getColumnName(int index) {
StringBuilder s = new StringBuilder();
while (index >= 26) {
s.insert(0, (char) ('A' + index % 26));
index = index / 26 - 1;
}
s.insert(0, (char) ('A' + index));
return s.toString();
}
/**
* 在主sheet裏面設置
*
* @param sheet
*/
private static void initSheetNameMapping(HSSFSheet sheet) {
DataValidation typeValidation = getDataValidationByFormula(MODEL_TYPE_SHEET_NAME, 0);
DataValidation shelfValidation = getDataValidationByFormula("INDIRECT($A1)", 1);
DataValidation priceValidation = getDataValidationByFormula(PRICE_SHEET_NAME, 3);
// 主sheet添加驗證數據
sheet.addValidationData(typeValidation);
sheet.addValidationData(shelfValidation);
sheet.addValidationData(priceValidation);
}
public static DataValidation getDataValidationByFormula(String formulaString, int columnIndex) {
// 加載下拉列表內容
DVConstraint constraint = DVConstraint.createFormulaListConstraint(formulaString);
// 設置數據有效性加載在哪個單元格上。
// 四個參數分別是:起始行、終止行、起始列、終止列
CellRangeAddressList regions = new CellRangeAddressList(1, XLS_MAX_ROW, columnIndex, columnIndex);
// 數據有效性對象
DataValidation dataValidationList = new HSSFDataValidation(regions, constraint);
dataValidationList.createErrorBox("Error", "請選擇或輸入有效的選項,或下載最新模版重試!");
String promptText = initPromptText(columnIndex);
dataValidationList.createPromptBox("", promptText);
return dataValidationList;
}
private static DataValidation getDecimalValidation(int firstRow, int lastRow, int columnIndex) {
// 創建一個規則:>0的整數
DVConstraint constraint = DVConstraint.createNumericConstraint(DVConstraint.ValidationType.INTEGER, DVConstraint.OperatorType.GREATER_OR_EQUAL, "0", "0");
// 設定在哪個單元格生效
CellRangeAddressList regions = new CellRangeAddressList(firstRow, lastRow, columnIndex, columnIndex);
// 創建規則對象
HSSFDataValidation decimalVal = new HSSFDataValidation(regions, constraint);
decimalVal.createPromptBox("", initPromptText(columnIndex));
decimalVal.createErrorBox("輸入值類型或大小有誤!", "數值型,請輸入大於0 的整數。");
return decimalVal;
}
private static String initPromptText(int columnIndex) {
String promptText = "";
switch (columnIndex) {
case 1:
promptText = "請下拉選擇或輸入有效項!且先選擇類型!";
break;
case 3:
promptText = "請輸入大於0的整數!";
break;
}
return promptText;
}
/**
* 在主sheet中校驗數量
* @param mainSheet
*/
private static void initCount(HSSFSheet mainSheet) {
DataValidation quantityValidation = getDecimalValidation(1, XLS_MAX_ROW, 2);
mainSheet.addValidationData(quantityValidation);
}
}