Java 實現Excel 下拉聯動,本示例中實現了省市區鄉鎮村聯動。適用於03版本Exce。
首先我們需要導入我們依賴
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>3.17</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.17</version> </dependency> <!--模板導入--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>ooxml-schemas</artifactId> <version>1.1</version> </dependency>
代碼實現如下:
import org.apache.poi.hssf.usermodel.*; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddressList; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; 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 zhouchuangbin * @Date 2021/8/2 * @Description */ public class ExcelTest { /** * 影響最大行數 */ private static final int XLS_MAX_ROW = 60000; /** * 導出模板 * * @param provinceList * @param areaFatherNameList * @param areaMap * @throws IOException */ public static void exportHSSFTemplate(List<String> provinceList, List<String> areaFatherNameList, Map<String, List<String>> areaMap) { String[] tileList = new String[]{"姓名", "手機號", "省", "市", "縣", "鄉鎮", "村"}; //創建工作簿對象 HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb.createSheet("sheet"); sheet.setDefaultColumnWidth(18); HSSFRow row = sheet.createRow(0); HSSFCellStyle style = getStyle(wb); HSSFCell cell = null; int provinceIndex = 0; for (int i = 0; i < tileList.length; i++) { String title = tileList[i]; if ("省".equals(title)) { provinceIndex = i; } cell = row.createCell(i); cell.setCellValue(title); cell.setCellStyle(style); } //創建隱藏目錄 createHideSheetHSSF(wb, provinceList, areaFatherNameList, areaMap); //如果省市區的excel位置不是如上tileList中的位置,需要變更則需要INDIRECT中所在的列名稱 // 省規則 DVConstraint provConstraint = DVConstraint.createExplicitListConstraint(provinceList.toArray(new String[]{})); CellRangeAddressList provRangeAddressList = new CellRangeAddressList(1, XLS_MAX_ROW, provinceIndex, provinceIndex); DataValidation provinceDataValidation = new HSSFDataValidation(provRangeAddressList, provConstraint); provinceDataValidation.createErrorBox("error", "請選擇正確的省份"); sheet.addValidationData(provinceDataValidation); //市規則 CellRangeAddressList cityRange = new CellRangeAddressList(1, XLS_MAX_ROW, provinceIndex + 1, provinceIndex + 1); DataValidation cityValidation = new HSSFDataValidation(cityRange, DVConstraint.createFormulaListConstraint("INDIRECT($C1)")); cityValidation.createErrorBox("error", "請選擇正確的市"); sheet.addValidationData(cityValidation); //區縣規則 CellRangeAddressList areaRange = new CellRangeAddressList(1, XLS_MAX_ROW, provinceIndex + 2, provinceIndex + 2); DataValidation areaValidation = new HSSFDataValidation(areaRange, DVConstraint.createFormulaListConstraint("INDIRECT($D1)")); areaValidation.createErrorBox("error", "請選擇正確的縣"); sheet.addValidationData(areaValidation); //區縣鄉鎮 CellRangeAddressList townRange = new CellRangeAddressList(1, XLS_MAX_ROW, provinceIndex + 3, provinceIndex + 3); DataValidation townValidation = new HSSFDataValidation(townRange, DVConstraint.createFormulaListConstraint("INDIRECT($E1)")); townValidation.createErrorBox("error", "請選擇正確的鄉鎮"); sheet.addValidationData(townValidation); //村規則 CellRangeAddressList villageRange = new CellRangeAddressList(1, XLS_MAX_ROW, provinceIndex + 4, provinceIndex + 4); DataValidation villageValidation = new HSSFDataValidation(villageRange, DVConstraint.createFormulaListConstraint("INDIRECT($F1)")); villageValidation.createErrorBox("error", "請選擇正確的村"); sheet.addValidationData(villageValidation); FileOutputStream fileOut; try { fileOut = new FileOutputStream("d://excel_template.xls"); wb.write(fileOut); fileOut.close(); } catch (Exception e) { e.printStackTrace(); } } /** * 創建隱藏頁 * * @param wb * @param provinceArr * @param areaFatherNameArr * @param areaMap */ public static void createHideSheetHSSF(HSSFWorkbook wb, List<String> provinceArr, List<String> areaFatherNameArr, Map<String, List<String>> areaMap) { //創建一個專門用來存放地區信息的隱藏sheet頁 HSSFSheet hideSheet = wb.createSheet("area"); int rowId = 0; // 設置第1行,存省的信息 Row provinceRow = hideSheet.createRow(rowId++); for (int i = 0; i < provinceArr.size(); i++) { Cell provinceCell = provinceRow.createCell(i); provinceCell.setCellValue(provinceArr.get(i)); } // 將具體的數據寫入到每一行中,行開頭為父級區域,后面是子區域。 for (int i = 0; i < areaFatherNameArr.size(); i++) { String key = areaFatherNameArr.get(i); List<String> son = areaMap.get(key); Row prow = hideSheet.createRow(rowId++); prow.createCell(0).setCellValue(key); System.out.println(key); for (int j = 0; j < son.size(); j++) { Cell cell = prow.createCell(j + 1); cell.setCellValue(son.get(j)); } // 添加名稱管理器 String range = getRange(1, rowId, son.size()); Name name = wb.createName(); //key不可重復 name.setNameName(key); String formula = "area!" + range; name.setRefersToFormula(formula); } wb.setSheetHidden(1, true); } /** * 計算formula * * @param offset 偏移量,如果給0,表示從A列開始,1,就是從B列 * @param rowId 第幾行 * @param colCount 一共多少列 * @return 如果給入參 1,1,10. 表示從B1-K1。最終返回 $B$1:$K$1 */ public static String getRange(int offset, int rowId, int colCount) { char start = (char) ('A' + offset); if (colCount <= 25) { char end = (char) (start + colCount - 1); return "$" + start + "$" + rowId + ":$" + end + "$" + rowId; } else { char endPrefix = 'A'; char endSuffix = 'A'; if ((colCount - 25) / 26 == 0 || colCount == 51) {// 26-51之間,包括邊界(僅兩次字母表計算) if ((colCount - 25) % 26 == 0) {// 邊界值 endSuffix = (char) ('A' + 25); } else { endSuffix = (char) ('A' + (colCount - 25) % 26 - 1); } } else {// 51以上 if ((colCount - 25) % 26 == 0) { endSuffix = (char) ('A' + 25); endPrefix = (char) (endPrefix + (colCount - 25) / 26 - 1); } else { endSuffix = (char) ('A' + (colCount - 25) % 26 - 1); endPrefix = (char) (endPrefix + (colCount - 25) / 26); } } return "$" + start + "$" + rowId + ":$" + endPrefix + endSuffix + "$" + rowId; } } /** * 樣式 * * @param wb * @return */ private static HSSFCellStyle getStyle(HSSFWorkbook wb) { HSSFCellStyle cellStyle = wb.createCellStyle(); cellStyle.setAlignment(HorizontalAlignment.CENTER);//水平居中 cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直居中 //cellStyle.setWrapText(true);//自動換行 HSSFFont font = wb.createFont(); font.setFontName("宋體");//設置字體名稱 font.setFontHeightInPoints((short) 12);//字體大小 font.setBold(true); cellStyle.setFont(font); return cellStyle; } public static void main(String[] args) { //省數據 List<String> provinceArr = Arrays.asList("廣東省", "河北省"); //所有區域父類(只到最后一層的上級即可) List<String> areaFatherNameArr = Arrays.asList("廣東省", "河北省", "深圳市", "衡水市", "寶安區", "武強縣", "西鄉街道辦事處", "街關鎮"); //父子類關系 Map<String, List<String>> areaMap = new HashMap<>(); areaMap.put("廣東省", Arrays.asList("深圳市")); areaMap.put("河北省", Arrays.asList("衡水市")); areaMap.put("深圳市", Arrays.asList("寶安區")); areaMap.put("衡水市", Arrays.asList("武強縣")); areaMap.put("寶安區", Arrays.asList("西鄉街道辦事處")); areaMap.put("武強縣", Arrays.asList("街關鎮")); areaMap.put("西鄉街道辦事處", Arrays.asList("西鄉社區居委會", "固戍社區居委會", "南昌社區居委會", "永豐社區居委會")); areaMap.put("街關鎮", Arrays.asList("五里屯村委會", "北關村委會", "西關村委會", "南關村委會")); exportHSSFTemplate(provinceArr, areaFatherNameArr, areaMap); } }