4 changed files with 858 additions and 220 deletions
-
13src/main/java/com/heai/modules/pms/controller/QcController.java
-
561src/main/java/com/heai/modules/pms/service/Impl/QcServiceImpl.java
-
4src/main/java/com/heai/modules/pms/service/QcService.java
-
500src/main/java/com/heai/modules/pms/util/QcExcelImportHelper.java
@ -0,0 +1,500 @@ |
|||||
|
package com.heai.modules.pms.util; |
||||
|
|
||||
|
import com.heai.modules.pms.data.QcInspectionTypeData; |
||||
|
import org.apache.commons.lang3.StringUtils; |
||||
|
import org.apache.poi.ss.usermodel.BorderStyle; |
||||
|
import org.apache.poi.ss.usermodel.Cell; |
||||
|
import org.apache.poi.ss.usermodel.CellStyle; |
||||
|
import org.apache.poi.ss.usermodel.DataFormatter; |
||||
|
import org.apache.poi.ss.usermodel.DataValidation; |
||||
|
import org.apache.poi.ss.usermodel.DataValidationConstraint; |
||||
|
import org.apache.poi.ss.usermodel.DataValidationHelper; |
||||
|
import org.apache.poi.ss.usermodel.FillPatternType; |
||||
|
import org.apache.poi.ss.usermodel.Font; |
||||
|
import org.apache.poi.ss.usermodel.HorizontalAlignment; |
||||
|
import org.apache.poi.ss.usermodel.IndexedColors; |
||||
|
import org.apache.poi.ss.usermodel.Name; |
||||
|
import org.apache.poi.ss.usermodel.Row; |
||||
|
import org.apache.poi.ss.usermodel.Sheet; |
||||
|
import org.apache.poi.ss.usermodel.VerticalAlignment; |
||||
|
import org.apache.poi.ss.usermodel.Workbook; |
||||
|
import org.apache.poi.ss.usermodel.WorkbookFactory; |
||||
|
import org.apache.poi.ss.util.CellRangeAddressList; |
||||
|
import org.apache.poi.xssf.usermodel.XSSFDataValidation; |
||||
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook; |
||||
|
import org.springframework.web.multipart.MultipartFile; |
||||
|
|
||||
|
import java.io.IOException; |
||||
|
import java.io.InputStream; |
||||
|
import java.math.BigDecimal; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.Arrays; |
||||
|
import java.util.Collections; |
||||
|
import java.util.HashMap; |
||||
|
import java.util.LinkedHashMap; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
/** |
||||
|
* QC 检验方法 / 项目 / 模板 Excel 导入辅助 |
||||
|
*/ |
||||
|
public final class QcExcelImportHelper { |
||||
|
|
||||
|
public static final String FLAG_METHOD = "method"; |
||||
|
public static final String FLAG_ITEM = "item"; |
||||
|
public static final String FLAG_TEMPLATE = "template"; |
||||
|
public static final String DEFAULT_BU_NO = "*"; |
||||
|
|
||||
|
private static final int DATA_ROW_END = 1000; |
||||
|
private static final String OPTIONS_SHEET = "下拉选项"; |
||||
|
private static final DataFormatter FORMATTER = new DataFormatter(); |
||||
|
|
||||
|
private static final Map<String, String> TYPE_ALIAS; |
||||
|
static { |
||||
|
Map<String, String> map = new HashMap<>(); |
||||
|
map.put("IPQC", "101"); |
||||
|
map.put("IQC", "105"); |
||||
|
map.put("FAI", "106"); |
||||
|
map.put("FQC", "107"); |
||||
|
map.put("PQC", "108"); |
||||
|
map.put("SQC", "109"); |
||||
|
map.put("OQC", "110"); |
||||
|
TYPE_ALIAS = Collections.unmodifiableMap(map); |
||||
|
} |
||||
|
|
||||
|
public static class TemplateOptions { |
||||
|
private List<String> inspectionTypeNames = new ArrayList<>(); |
||||
|
|
||||
|
public List<String> getInspectionTypeNames() { |
||||
|
return inspectionTypeNames; |
||||
|
} |
||||
|
|
||||
|
public void setInspectionTypeNames(List<String> inspectionTypeNames) { |
||||
|
this.inspectionTypeNames = inspectionTypeNames == null ? new ArrayList<String>() : inspectionTypeNames; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private QcExcelImportHelper() { |
||||
|
} |
||||
|
|
||||
|
public static String[] methodHeaders() { |
||||
|
return new String[]{"*方法名称", "*检验类型", "检验方法说明"}; |
||||
|
} |
||||
|
|
||||
|
public static String[] itemHeaders() { |
||||
|
return new String[]{ |
||||
|
"*项目名称", "*检验值类型", "*检验类型", "*方法编码", |
||||
|
"抽样方案编码", "检验水平编码", "参照值", "最大值", "最小值", |
||||
|
"抽样数量", "抽样比例%", "需上传图片" |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
public static String[] templateHeaders() { |
||||
|
return new String[]{ |
||||
|
"*检验模板名称", "*检验类型", "抽样方案编码", "检验水平编码", |
||||
|
"检验完成时间(h)", "默认抽样数量", "默认抽样比例", "AQL", "AC", "RE", |
||||
|
"版本号", "检验模板备注" |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
public static String dataSheetName(String flag) { |
||||
|
if (FLAG_METHOD.equals(flag)) { |
||||
|
return "检验方法"; |
||||
|
} |
||||
|
if (FLAG_ITEM.equals(flag)) { |
||||
|
return "检验项目"; |
||||
|
} |
||||
|
if (FLAG_TEMPLATE.equals(flag)) { |
||||
|
return "检验模板"; |
||||
|
} |
||||
|
throw new RuntimeException("不支持的导入模板类型"); |
||||
|
} |
||||
|
|
||||
|
public static Sheet getDataSheet(Workbook workbook, String flag) { |
||||
|
if (workbook == null || workbook.getNumberOfSheets() == 0) { |
||||
|
throw new RuntimeException("Excel 中没有工作表"); |
||||
|
} |
||||
|
String expected = dataSheetName(flag); |
||||
|
Sheet named = workbook.getSheet(expected); |
||||
|
if (named != null) { |
||||
|
return named; |
||||
|
} |
||||
|
for (int i = 0; i < workbook.getNumberOfSheets(); i++) { |
||||
|
Sheet sheet = workbook.getSheetAt(i); |
||||
|
String name = sheet.getSheetName(); |
||||
|
if (OPTIONS_SHEET.equals(name) || "填写说明".equals(name)) { |
||||
|
continue; |
||||
|
} |
||||
|
if (workbook.isSheetHidden(i) || workbook.isSheetVeryHidden(i)) { |
||||
|
continue; |
||||
|
} |
||||
|
return sheet; |
||||
|
} |
||||
|
throw new RuntimeException("未找到数据工作表,请使用系统下载的导入模板"); |
||||
|
} |
||||
|
|
||||
|
public static Workbook createTemplateWorkbook(String flag, TemplateOptions options) { |
||||
|
XSSFWorkbook workbook = new XSSFWorkbook(); |
||||
|
if (options == null) { |
||||
|
options = new TemplateOptions(); |
||||
|
} |
||||
|
String sheetName = dataSheetName(flag); |
||||
|
String[] headers; |
||||
|
String note; |
||||
|
if (FLAG_METHOD.equals(flag)) { |
||||
|
headers = methodHeaders(); |
||||
|
note = "带*列为必填。检验类型请用下拉选择。方法编码由系统自动生成。工厂取当前用户默认工厂,不必填写。"; |
||||
|
} else if (FLAG_ITEM.equals(flag)) { |
||||
|
headers = itemHeaders(); |
||||
|
note = "带*列为必填。检验类型、检验值类型、需上传图片请用下拉选择。方法编码、抽样方案编码、检验水平编码请按系统中已有编码手填。填写抽样方案时须同时填写检验水平。项目编码由系统自动生成。"; |
||||
|
} else { |
||||
|
headers = templateHeaders(); |
||||
|
note = "带*列为必填。检验类型请用下拉选择。抽样方案编码、检验水平编码请按系统中已有编码手填。抽样方案编码、默认抽样数量、默认抽样比例至少填一项;填写抽样方案时须同时填写检验水平。模板编码由系统自动生成。"; |
||||
|
} |
||||
|
|
||||
|
Sheet sheet = workbook.createSheet(sheetName); |
||||
|
CellStyle requiredStyle = createHeaderStyle(workbook, true); |
||||
|
CellStyle optionalStyle = createHeaderStyle(workbook, false); |
||||
|
Row headerRow = sheet.createRow(0); |
||||
|
for (int i = 0; i < headers.length; i++) { |
||||
|
Cell cell = headerRow.createCell(i); |
||||
|
cell.setCellValue(headers[i]); |
||||
|
cell.setCellStyle(headers[i].startsWith("*") ? requiredStyle : optionalStyle); |
||||
|
sheet.setColumnWidth(i, 18 * 256); |
||||
|
} |
||||
|
|
||||
|
CellStyle textStyle = workbook.createCellStyle(); |
||||
|
textStyle.setDataFormat(workbook.createDataFormat().getFormat("@")); |
||||
|
applyTextColumns(sheet, headers, textStyle, |
||||
|
"检验类型", "检验值类型", "方法编码", "抽样方案编码", "检验水平编码", "需上传图片"); |
||||
|
|
||||
|
writeOptionsSheet(workbook, options); |
||||
|
addDropdown(sheet, headers, "检验类型", "optInspectionType"); |
||||
|
addDropdown(sheet, headers, "检验值类型", "optValueType"); |
||||
|
addDropdown(sheet, headers, "需上传图片", "optYn"); |
||||
|
|
||||
|
Sheet noteSheet = workbook.createSheet("填写说明"); |
||||
|
noteSheet.setColumnWidth(0, 120 * 256); |
||||
|
noteSheet.createRow(0).createCell(0).setCellValue(note); |
||||
|
noteSheet.createRow(1).createCell(0).setCellValue("请从第2行开始填写数据。红色带*列为必填。检验类型、检验值类型、需上传图片请点单元格右侧箭头选择;方法编码、抽样方案编码、检验水平编码请手填系统中已有编码。"); |
||||
|
noteSheet.createRow(2).createCell(0).setCellValue("工厂取当前登录人默认工厂,部门固定为 *,无需在Excel中填写。"); |
||||
|
workbook.setSheetHidden(workbook.getSheetIndex(OPTIONS_SHEET), true); |
||||
|
workbook.setSheetOrder(sheetName, 0); |
||||
|
workbook.setActiveSheet(workbook.getSheetIndex(sheetName)); |
||||
|
return workbook; |
||||
|
} |
||||
|
|
||||
|
public static String templateFileName(String flag) { |
||||
|
if (FLAG_METHOD.equals(flag)) { |
||||
|
return "检验方法导入模板.xlsx"; |
||||
|
} |
||||
|
if (FLAG_ITEM.equals(flag)) { |
||||
|
return "检验项目导入模板.xlsx"; |
||||
|
} |
||||
|
if (FLAG_TEMPLATE.equals(flag)) { |
||||
|
return "检验模板导入模板.xlsx"; |
||||
|
} |
||||
|
return "QC导入模板.xlsx"; |
||||
|
} |
||||
|
|
||||
|
public static Workbook openWorkbook(MultipartFile file) throws IOException { |
||||
|
if (file == null || file.isEmpty()) { |
||||
|
throw new RuntimeException("请先上传文件"); |
||||
|
} |
||||
|
try (InputStream is = file.getInputStream()) { |
||||
|
return WorkbookFactory.create(is); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static Map<String, Integer> readHeaderIndex(Row headerRow) { |
||||
|
if (headerRow == null) { |
||||
|
throw new RuntimeException("Excel 缺少表头行"); |
||||
|
} |
||||
|
Map<String, Integer> index = new LinkedHashMap<>(); |
||||
|
short last = headerRow.getLastCellNum(); |
||||
|
for (int i = 0; i < last; i++) { |
||||
|
String name = normalizeHeader(cellString(headerRow.getCell(i))); |
||||
|
if (StringUtils.isNotBlank(name) && !index.containsKey(name)) { |
||||
|
index.put(name, i); |
||||
|
} |
||||
|
} |
||||
|
if (index.isEmpty()) { |
||||
|
throw new RuntimeException("Excel 表头为空,请使用系统下载的导入模板"); |
||||
|
} |
||||
|
return index; |
||||
|
} |
||||
|
|
||||
|
public static String normalizeHeader(String header) { |
||||
|
if (header == null) { |
||||
|
return ""; |
||||
|
} |
||||
|
String value = header.trim(); |
||||
|
if (value.startsWith("*")) { |
||||
|
value = value.substring(1).trim(); |
||||
|
} |
||||
|
if (value.endsWith("%")) { |
||||
|
value = value.substring(0, value.length() - 1).trim(); |
||||
|
} |
||||
|
return value; |
||||
|
} |
||||
|
|
||||
|
public static String getString(Row row, Map<String, Integer> headers, String... names) { |
||||
|
Integer idx = findIndex(headers, names); |
||||
|
if (idx == null) { |
||||
|
return ""; |
||||
|
} |
||||
|
return cellString(row.getCell(idx)); |
||||
|
} |
||||
|
|
||||
|
public static BigDecimal getDecimal(Row row, Map<String, Integer> headers, String... names) { |
||||
|
String value = getString(row, headers, names); |
||||
|
if (StringUtils.isBlank(value)) { |
||||
|
return null; |
||||
|
} |
||||
|
try { |
||||
|
return new BigDecimal(value.replace(",", "").trim()); |
||||
|
} catch (NumberFormatException e) { |
||||
|
throw new RuntimeException("【" + names[0] + "】不是有效数字:" + value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static boolean isBlankRow(Row row, Map<String, Integer> headers) { |
||||
|
if (row == null) { |
||||
|
return true; |
||||
|
} |
||||
|
for (Integer idx : headers.values()) { |
||||
|
if (StringUtils.isNotBlank(cellString(row.getCell(idx)))) { |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
public static String resolveInspectionTypeNo(String value, List<QcInspectionTypeData> types) { |
||||
|
if (StringUtils.isBlank(value)) { |
||||
|
return ""; |
||||
|
} |
||||
|
String input = value.trim(); |
||||
|
if (types != null) { |
||||
|
for (QcInspectionTypeData type : types) { |
||||
|
if (input.equals(type.getInspectionTypeNo()) || input.equalsIgnoreCase(type.getInspectionTypeName())) { |
||||
|
return type.getInspectionTypeNo(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
String alias = TYPE_ALIAS.get(input.toUpperCase()); |
||||
|
if (alias != null) { |
||||
|
return alias; |
||||
|
} |
||||
|
throw new RuntimeException("检验类型无法识别:" + value); |
||||
|
} |
||||
|
|
||||
|
public static String resolveYn(String value) { |
||||
|
if (StringUtils.isBlank(value)) { |
||||
|
return null; |
||||
|
} |
||||
|
String input = value.trim(); |
||||
|
if ("Y".equalsIgnoreCase(input) || "是".equals(input) || "true".equalsIgnoreCase(input) || "1".equals(input)) { |
||||
|
return "Y"; |
||||
|
} |
||||
|
if ("N".equalsIgnoreCase(input) || "否".equals(input) || "false".equalsIgnoreCase(input) || "0".equals(input)) { |
||||
|
return "N"; |
||||
|
} |
||||
|
throw new RuntimeException("只能选择 是 或 否"); |
||||
|
} |
||||
|
|
||||
|
public static String resolveValueTypeDb(String value) { |
||||
|
if (StringUtils.isBlank(value)) { |
||||
|
return ""; |
||||
|
} |
||||
|
String input = value.trim(); |
||||
|
if ("T".equalsIgnoreCase(input) || "文本".equals(input) || "文字".equals(input)) { |
||||
|
return "T"; |
||||
|
} |
||||
|
if ("N".equalsIgnoreCase(input) || "数字".equals(input) || "数值".equals(input)) { |
||||
|
return "N"; |
||||
|
} |
||||
|
throw new RuntimeException("检验值类型请选择 文本 或 数字"); |
||||
|
} |
||||
|
|
||||
|
public static String resolveSite(String siteParam) { |
||||
|
if (StringUtils.isBlank(siteParam)) { |
||||
|
throw new RuntimeException("未获取到当前用户工厂"); |
||||
|
} |
||||
|
String site = siteParam.trim(); |
||||
|
int idx = site.indexOf('_'); |
||||
|
if (idx > 0) { |
||||
|
return site.substring(0, idx); |
||||
|
} |
||||
|
return site; |
||||
|
} |
||||
|
|
||||
|
public static String resolveBuNo() { |
||||
|
return DEFAULT_BU_NO; |
||||
|
} |
||||
|
|
||||
|
public static String buildTypePrefixNo(String inspectionTypeNo, String seqNo) { |
||||
|
if ("101".equals(inspectionTypeNo) || "102".equals(inspectionTypeNo) |
||||
|
|| "103".equals(inspectionTypeNo) || "104".equals(inspectionTypeNo)) { |
||||
|
return "IPQC-" + seqNo; |
||||
|
} |
||||
|
if ("105".equals(inspectionTypeNo)) { |
||||
|
return "IQC-" + seqNo; |
||||
|
} |
||||
|
if ("106".equals(inspectionTypeNo)) { |
||||
|
return "FAI-" + seqNo; |
||||
|
} |
||||
|
if ("107".equals(inspectionTypeNo)) { |
||||
|
return "FQC-" + seqNo; |
||||
|
} |
||||
|
if ("108".equals(inspectionTypeNo)) { |
||||
|
return "PQC-" + seqNo; |
||||
|
} |
||||
|
if ("109".equals(inspectionTypeNo)) { |
||||
|
return "SQC-" + seqNo; |
||||
|
} |
||||
|
if ("110".equals(inspectionTypeNo)) { |
||||
|
return "OQC-" + seqNo; |
||||
|
} |
||||
|
throw new RuntimeException("不支持的检验类型编码:" + inspectionTypeNo); |
||||
|
} |
||||
|
|
||||
|
public static String cellString(Cell cell) { |
||||
|
if (cell == null) { |
||||
|
return ""; |
||||
|
} |
||||
|
return StringUtils.trimToEmpty(FORMATTER.formatCellValue(cell)); |
||||
|
} |
||||
|
|
||||
|
private static Integer findIndex(Map<String, Integer> headers, String... names) { |
||||
|
if (headers == null || names == null) { |
||||
|
return null; |
||||
|
} |
||||
|
for (String name : names) { |
||||
|
Integer idx = headers.get(normalizeHeader(name)); |
||||
|
if (idx != null) { |
||||
|
return idx; |
||||
|
} |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
private static CellStyle createHeaderStyle(Workbook workbook, boolean required) { |
||||
|
CellStyle style = workbook.createCellStyle(); |
||||
|
Font font = workbook.createFont(); |
||||
|
font.setBold(true); |
||||
|
font.setColor(required ? IndexedColors.RED.getIndex() : IndexedColors.WHITE.getIndex()); |
||||
|
style.setFont(font); |
||||
|
style.setFillForegroundColor(required ? IndexedColors.LIGHT_YELLOW.getIndex() : IndexedColors.DARK_BLUE.getIndex()); |
||||
|
style.setFillPattern(FillPatternType.SOLID_FOREGROUND); |
||||
|
style.setAlignment(HorizontalAlignment.CENTER); |
||||
|
style.setVerticalAlignment(VerticalAlignment.CENTER); |
||||
|
style.setBorderBottom(BorderStyle.THIN); |
||||
|
style.setBorderLeft(BorderStyle.THIN); |
||||
|
style.setBorderRight(BorderStyle.THIN); |
||||
|
style.setBorderTop(BorderStyle.THIN); |
||||
|
style.setWrapText(true); |
||||
|
return style; |
||||
|
} |
||||
|
|
||||
|
private static void writeOptionsSheet(Workbook workbook, TemplateOptions options) { |
||||
|
Sheet sheet = workbook.createSheet(OPTIONS_SHEET); |
||||
|
String[] titles = {"检验类型", "检验值类型", "需上传图片"}; |
||||
|
Row titleRow = sheet.createRow(0); |
||||
|
for (int i = 0; i < titles.length; i++) { |
||||
|
titleRow.createCell(i).setCellValue(titles[i]); |
||||
|
sheet.setColumnWidth(i, 18 * 256); |
||||
|
} |
||||
|
writeOptionColumn(sheet, 0, options.getInspectionTypeNames()); |
||||
|
writeOptionColumn(sheet, 1, Arrays.asList("文本", "数字")); |
||||
|
writeOptionColumn(sheet, 2, Arrays.asList("是", "否")); |
||||
|
|
||||
|
createName(workbook, "optInspectionType", 0, sizeOf(options.getInspectionTypeNames())); |
||||
|
createName(workbook, "optValueType", 1, 2); |
||||
|
createName(workbook, "optYn", 2, 2); |
||||
|
} |
||||
|
|
||||
|
private static void writeOptionColumn(Sheet sheet, int col, List<String> values) { |
||||
|
if (values == null) { |
||||
|
return; |
||||
|
} |
||||
|
int rowIdx = 1; |
||||
|
for (String value : values) { |
||||
|
if (StringUtils.isBlank(value)) { |
||||
|
continue; |
||||
|
} |
||||
|
Row row = sheet.getRow(rowIdx); |
||||
|
if (row == null) { |
||||
|
row = sheet.createRow(rowIdx); |
||||
|
} |
||||
|
row.createCell(col).setCellValue(value.trim()); |
||||
|
rowIdx++; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private static int sizeOf(List<String> values) { |
||||
|
if (values == null) { |
||||
|
return 0; |
||||
|
} |
||||
|
int count = 0; |
||||
|
for (String value : values) { |
||||
|
if (StringUtils.isNotBlank(value)) { |
||||
|
count++; |
||||
|
} |
||||
|
} |
||||
|
return count; |
||||
|
} |
||||
|
|
||||
|
private static void createName(Workbook workbook, String name, int col, int size) { |
||||
|
if (size <= 0) { |
||||
|
return; |
||||
|
} |
||||
|
String colLetter = colLetter(col); |
||||
|
Name named = workbook.createName(); |
||||
|
named.setNameName(name); |
||||
|
named.setRefersToFormula("'" + OPTIONS_SHEET + "'!$" + colLetter + "$2:$" + colLetter + "$" + (size + 1)); |
||||
|
} |
||||
|
|
||||
|
private static void applyTextColumns(Sheet sheet, String[] headers, CellStyle textStyle, String... names) { |
||||
|
for (String name : names) { |
||||
|
for (int i = 0; i < headers.length; i++) { |
||||
|
if (normalizeHeader(name).equals(normalizeHeader(headers[i]))) { |
||||
|
sheet.setDefaultColumnStyle(i, textStyle); |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private static String colLetter(int col) { |
||||
|
return String.valueOf((char) ('A' + col)); |
||||
|
} |
||||
|
|
||||
|
private static void addDropdown(Sheet sheet, String[] headers, String headerName, String namedRange) { |
||||
|
int col = -1; |
||||
|
for (int i = 0; i < headers.length; i++) { |
||||
|
if (normalizeHeader(headerName).equals(normalizeHeader(headers[i]))) { |
||||
|
col = i; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
if (col < 0 || sheet.getWorkbook().getName(namedRange) == null) { |
||||
|
return; |
||||
|
} |
||||
|
DataValidationHelper helper = sheet.getDataValidationHelper(); |
||||
|
DataValidationConstraint constraint = helper.createFormulaListConstraint(namedRange); |
||||
|
CellRangeAddressList addressList = new CellRangeAddressList(1, DATA_ROW_END, col, col); |
||||
|
DataValidation validation = helper.createValidation(constraint, addressList); |
||||
|
validation.setShowErrorBox(true); |
||||
|
validation.setErrorStyle(DataValidation.ErrorStyle.STOP); |
||||
|
validation.createErrorBox("输入错误", "请从下拉列表中选择"); |
||||
|
validation.createPromptBox("请选择", "请从下拉列表中选择"); |
||||
|
validation.setShowPromptBox(true); |
||||
|
if (validation instanceof XSSFDataValidation) { |
||||
|
validation.setSuppressDropDownArrow(true); |
||||
|
} else { |
||||
|
validation.setSuppressDropDownArrow(false); |
||||
|
} |
||||
|
sheet.addValidationData(validation); |
||||
|
} |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue