Browse Source

2026-09-21

IQC基础数据导入
master
fengyuan_yang 12 hours ago
parent
commit
cb1c58ea19
  1. 13
      src/main/java/com/heai/modules/pms/controller/QcController.java
  2. 561
      src/main/java/com/heai/modules/pms/service/Impl/QcServiceImpl.java
  3. 4
      src/main/java/com/heai/modules/pms/service/QcService.java
  4. 500
      src/main/java/com/heai/modules/pms/util/QcExcelImportHelper.java

13
src/main/java/com/heai/modules/pms/controller/QcController.java

@ -164,6 +164,19 @@ public class QcController {
return R.ok();
}
@PostMapping("/uploadMethodExcel")
public R uploadMethodExcel(@RequestParam(value = "file") MultipartFile file, @ModelAttribute GetParamInData data){
qcService.uploadMethodExcel(file, data);
return R.ok();
}
@RequestMapping(value = "/downloadQcImportTemplate", method = {RequestMethod.GET, RequestMethod.POST})
public void downloadQcImportTemplate(@RequestParam("flag") String flag,
@RequestParam(value = "site", required = false) String site,
HttpServletResponse response) {
qcService.downloadQcImportTemplate(flag, site, response);
}
// ======================= 根据物料设置检验模板API =======================
/**

561
src/main/java/com/heai/modules/pms/service/Impl/QcServiceImpl.java

@ -18,6 +18,7 @@ import com.heai.modules.pms.mapper.QcDao;
import com.heai.modules.pms.mapper.QcMapper;
import com.heai.modules.pms.service.QcService;
import com.heai.modules.pms.util.HttpClientUtil;
import com.heai.modules.pms.util.QcExcelImportHelper;
import com.heai.modules.pms.util.ResponseData;
import com.heai.modules.board.dao.BoardMapper;
import com.heai.modules.production.dao.PrintLabelRecordMapper;
@ -36,6 +37,9 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
@ -53,10 +57,12 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
@ -324,82 +330,278 @@ public class QcServiceImpl implements QcService {
@Override
@Transactional
public void taskUploadExcel(MultipartFile file, GetParamInData data) {
try{
// 转流
InputStream is = file.getInputStream();
// 读取工作簿
XSSFWorkbook workbook = new XSSFWorkbook(is);
// 读取工作表
XSSFSheet sheet = workbook.getSheetAt(0);
// 获取行数
int rows = sheet.getPhysicalNumberOfRows();
// 声明对象
QcItemData task = null;
// 遍历每一行从第二行开始
for (int j = 1; j < rows; j++) {
// 实例化对象
task = new QcItemData();
//获得该行
XSSFRow row = sheet.getRow(j);
// 为对象赋值
task.setSite(data.getSite());
task.setInspectionTypeNo(row.getCell(3).getRawValue());
// 获取编码
String itemNo = qcMapper.getItemNo(task);
if ("101".equals(task.getInspectionTypeNo()) || "102".equals(task.getInspectionTypeNo()) || "103".equals(task.getInspectionTypeNo()) || "104".equals(task.getInspectionTypeNo())) {
task.setItemNo("IPQC-" + itemNo);
} else if ("105".equals(task.getInspectionTypeNo())) {
task.setItemNo("IQC-" + itemNo);
} else if ("106".equals(task.getInspectionTypeNo())) {
task.setItemNo("FAI-" + itemNo);
} else if ("107".equals(task.getInspectionTypeNo())) {
task.setItemNo("FQC-" + itemNo);
} else if ("108".equals(task.getInspectionTypeNo())) {
task.setItemNo("PQC-" + itemNo);
}else if("109".equals(task.getInspectionTypeNo())) {
data.setItemNo("SQC-" + itemNo);
}else if("110".equals(task.getInspectionTypeNo())) {
data.setItemNo("OQC-" + itemNo);
String site = QcExcelImportHelper.resolveSite(data.getSite());
String buNo = QcExcelImportHelper.resolveBuNo();
List<QcInspectionTypeData> types = loadInspectionTypes(site);
List<QcSamplingInspectionProgrammeData> programmes = loadSamplingProgrammes(site);
List<QcSamplingInspectionLevelData> levels = loadSamplingLevels(site);
List<String> errors = new ArrayList<>();
List<QcItemData> toSave = new ArrayList<>();
try (Workbook workbook = QcExcelImportHelper.openWorkbook(file)) {
Sheet sheet = QcExcelImportHelper.getDataSheet(workbook, QcExcelImportHelper.FLAG_ITEM);
Map<String, Integer> headers = QcExcelImportHelper.readHeaderIndex(sheet.getRow(0));
int lastRow = sheet.getLastRowNum();
for (int r = 1; r <= lastRow; r++) {
Row row = sheet.getRow(r);
if (QcExcelImportHelper.isBlankRow(row, headers)) {
continue;
}
task.setItemDesc(row.getCell(0).getStringCellValue());
task.setValueType(row.getCell(1).getStringCellValue());
if (row.getCell(1).getStringCellValue().equals("文本")){
task.setValueTypeDb("T");
task.setMaxValue(null);
task.setMinValue(null);
} else if (row.getCell(1).getStringCellValue().equals("数字")) {
task.setValueTypeDb("N");
if (row.getCell(3) == null) {
task.setMaxValue(null);
} else {
task.setMaxValue(BigDecimal.valueOf(row.getCell(3).getNumericCellValue()));
int excelRow = r + 1;
try {
QcItemData item = new QcItemData();
item.setSite(site);
item.setBuNo(buNo);
item.setItemType("D");
item.setCreatedBy(data.getCreateBy());
item.setUpdateBy(data.getCreateBy());
item.setItemDesc(QcExcelImportHelper.getString(row, headers, "项目名称"));
if (StringUtils.isBlank(item.getItemDesc())) {
throw new RuntimeException("项目名称不能为空");
}
if (row.getCell(4) == null) {
task.setMinValue(null);
String valueTypeDb = QcExcelImportHelper.resolveValueTypeDb(QcExcelImportHelper.getString(row, headers, "检验值类型"));
if (StringUtils.isBlank(valueTypeDb)) {
throw new RuntimeException("检验值类型不能为空");
}
item.setValueTypeDb(valueTypeDb);
String typeValue = QcExcelImportHelper.getString(row, headers, "检验类型");
if (StringUtils.isBlank(typeValue)) {
throw new RuntimeException("检验类型不能为空");
}
item.setInspectionTypeNo(QcExcelImportHelper.resolveInspectionTypeNo(typeValue, types));
item.setMethodNo(QcExcelImportHelper.getString(row, headers, "方法编码"));
if (StringUtils.isBlank(item.getMethodNo())) {
throw new RuntimeException("方法编码不能为空");
}
assertMethodExists(site, item.getMethodNo(), item.getInspectionTypeNo());
item.setDefaultValue(blankToNull(QcExcelImportHelper.getString(row, headers, "参照值")));
item.setMaxValue(QcExcelImportHelper.getDecimal(row, headers, "最大值"));
item.setMinValue(QcExcelImportHelper.getDecimal(row, headers, "最小值"));
if ("T".equals(item.getValueTypeDb())) {
item.setValueType("文本");
item.setMaxValue(null);
item.setMinValue(null);
} else {
task.setMinValue(BigDecimal.valueOf(row.getCell(4).getNumericCellValue()));
item.setValueType("数字");
if (item.getMaxValue() != null && item.getMinValue() != null
&& item.getMaxValue().compareTo(item.getMinValue()) < 0) {
throw new RuntimeException("最大值不能小于最小值");
}
}
} else {
task.setValueTypeDb(null);
item.setSamplingProgrammeNo(resolveSamplingProgrammeNo(
QcExcelImportHelper.getString(row, headers, "抽样方案编码"), programmes));
item.setSamplingLevelNo(resolveSamplingLevelNo(
QcExcelImportHelper.getString(row, headers, "检验水平编码"), levels));
if (StringUtils.isNotBlank(item.getSamplingProgrammeNo()) && StringUtils.isBlank(item.getSamplingLevelNo())) {
throw new RuntimeException("填写抽样方案时必须填写检验水平");
}
item.setItemSamplingQuantity(QcExcelImportHelper.getDecimal(row, headers, "抽样数量"));
item.setDefaultSamplingProportion(QcExcelImportHelper.getDecimal(row, headers, "抽样比例%", "抽样比例"));
String pictureFlag = QcExcelImportHelper.resolveYn(QcExcelImportHelper.getString(row, headers, "需上传图片"));
item.setPictureFlag(StringUtils.defaultIfBlank(pictureFlag, "N"));
toSave.add(item);
} catch (RuntimeException e) {
errors.add("第" + excelRow + "行:" + e.getMessage());
}
if (row.getCell(2) == null) {
task.setDefaultValue(null);
} else {
task.setDefaultValue(row.getCell(2).getRawValue());
}
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("导入失败:" + e.getMessage());
}
if (toSave.isEmpty() && errors.isEmpty()) {
throw new RuntimeException("没有可导入的数据,请检查Excel内容");
}
if (!errors.isEmpty()) {
throw new RuntimeException("导入失败:<br/>" + String.join("<br/>", errors));
}
for (QcItemData item : toSave) {
item.setItemNo(QcExcelImportHelper.buildTypePrefixNo(item.getInspectionTypeNo(), qcMapper.getItemNo(item)));
qcMapper.qcItemSave(item);
qcMapper.qcItemMethodSave(item);
}
}
/**
* 检验方法导入
**/
@Override
@Transactional
public void uploadMethodExcel(MultipartFile file, GetParamInData data) {
String site = QcExcelImportHelper.resolveSite(data.getSite());
String buNo = QcExcelImportHelper.resolveBuNo();
List<QcInspectionTypeData> types = loadInspectionTypes(site);
List<String> errors = new ArrayList<>();
List<QcMethodData> toSave = new ArrayList<>();
try (Workbook workbook = QcExcelImportHelper.openWorkbook(file)) {
Sheet sheet = QcExcelImportHelper.getDataSheet(workbook, QcExcelImportHelper.FLAG_METHOD);
Map<String, Integer> headers = QcExcelImportHelper.readHeaderIndex(sheet.getRow(0));
int lastRow = sheet.getLastRowNum();
for (int r = 1; r <= lastRow; r++) {
Row row = sheet.getRow(r);
if (QcExcelImportHelper.isBlankRow(row, headers)) {
continue;
}
int excelRow = r + 1;
try {
QcMethodData method = new QcMethodData();
method.setSite(site);
method.setBuNo(buNo);
method.setCreateBy(data.getCreateBy());
method.setUpdateBy(data.getCreateBy());
method.setMethodName(QcExcelImportHelper.getString(row, headers, "方法名称"));
if (StringUtils.isBlank(method.getMethodName())) {
throw new RuntimeException("方法名称不能为空");
}
String typeValue = QcExcelImportHelper.getString(row, headers, "检验类型");
if (StringUtils.isBlank(typeValue)) {
throw new RuntimeException("检验类型不能为空");
}
method.setInspectionTypeNo(QcExcelImportHelper.resolveInspectionTypeNo(typeValue, types));
method.setMethodRemark(blankToNull(QcExcelImportHelper.getString(row, headers, "检验方法说明")));
toSave.add(method);
} catch (RuntimeException e) {
errors.add("第" + excelRow + "行:" + e.getMessage());
}
task.setItemType("D");
task.setCreatedBy(data.getCreateBy());
task.setMethodNo(row.getCell(5).getRawValue());
// 新增
qcMapper.qcItemSave(task);
// 新增项目里的方法
qcMapper.qcItemMethodSave(task);
}
}catch (Exception e){
throw new RuntimeException("导入失败:"+e.getMessage());
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("导入失败:" + e.getMessage());
}
if (toSave.isEmpty() && errors.isEmpty()) {
throw new RuntimeException("没有可导入的数据,请检查Excel内容");
}
if (!errors.isEmpty()) {
throw new RuntimeException("导入失败:<br/>" + String.join("<br/>", errors));
}
for (QcMethodData method : toSave) {
method.setMethodNo(QcExcelImportHelper.buildTypePrefixNo(method.getInspectionTypeNo(), qcMapper.getMethodNo(method)));
qcMapper.qcMethodSave(method);
}
}
@Override
public void downloadQcImportTemplate(String flag, String site, HttpServletResponse response) {
String optionSite = StringUtils.isBlank(site) ? "" : QcExcelImportHelper.resolveSite(site);
try (Workbook workbook = QcExcelImportHelper.createTemplateWorkbook(flag, buildExcelTemplateOptions(optionSite));
OutputStream os = response.getOutputStream()) {
String fileName = URLEncoder.encode(QcExcelImportHelper.templateFileName(flag), "UTF-8").replaceAll("\\+", "%20");
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + fileName);
workbook.write(os);
os.flush();
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("下载导入模板失败:" + e.getMessage());
}
}
private QcExcelImportHelper.TemplateOptions buildExcelTemplateOptions(String site) {
QcExcelImportHelper.TemplateOptions options = new QcExcelImportHelper.TemplateOptions();
if (StringUtils.isBlank(site)) {
return options;
}
List<String> typeNames = new ArrayList<>();
for (QcInspectionTypeData type : loadInspectionTypes(site)) {
if (type != null && StringUtils.isNotBlank(type.getInspectionTypeName())) {
typeNames.add(type.getInspectionTypeName());
}
}
options.setInspectionTypeNames(typeNames);
return options;
}
private List<QcInspectionTypeData> loadInspectionTypes(String site) {
QcInspectionTypeData query = new QcInspectionTypeData();
query.setSite(site);
List<QcInspectionTypeData> list = qcMapper.inspectionTypeSearch(query);
return list == null ? Collections.emptyList() : list;
}
private List<QcSamplingInspectionProgrammeData> loadSamplingProgrammes(String site) {
QcSamplingInspectionProgrammeData query = new QcSamplingInspectionProgrammeData();
query.setSite(site);
IPage<QcSamplingInspectionProgrammeData> page = qcMapper.samplingProgrammeSearch(
new Page<QcSamplingInspectionProgrammeData>(1, 10000), query);
return page == null || page.getRecords() == null ? Collections.emptyList() : page.getRecords();
}
private List<QcSamplingInspectionLevelData> loadSamplingLevels(String site) {
QcSamplingInspectionLevelData query = new QcSamplingInspectionLevelData();
query.setSite(site);
IPage<QcSamplingInspectionLevelData> page = qcMapper.samplingLevelSearch(
new Page<QcSamplingInspectionLevelData>(1, 10000), query);
return page == null || page.getRecords() == null ? Collections.emptyList() : page.getRecords();
}
private String resolveSamplingProgrammeNo(String value, List<QcSamplingInspectionProgrammeData> programmes) {
if (StringUtils.isBlank(value)) {
return null;
}
String input = value.trim();
if (programmes != null) {
for (QcSamplingInspectionProgrammeData programme : programmes) {
if (programme != null && input.equals(programme.getSamplingProgrammeNo())) {
return programme.getSamplingProgrammeNo();
}
}
for (QcSamplingInspectionProgrammeData programme : programmes) {
if (programme != null && input.equals(programme.getSamplingProgrammeDesc())) {
return programme.getSamplingProgrammeNo();
}
}
}
throw new RuntimeException("抽样方案不存在:" + value);
}
private String resolveSamplingLevelNo(String value, List<QcSamplingInspectionLevelData> levels) {
if (StringUtils.isBlank(value)) {
return null;
}
String input = value.trim();
if (levels != null) {
for (QcSamplingInspectionLevelData level : levels) {
if (level != null && input.equals(level.getSamplingLevelNo())) {
return level.getSamplingLevelNo();
}
}
for (QcSamplingInspectionLevelData level : levels) {
if (level != null && input.equals(level.getSamplingLevelDesc())) {
return level.getSamplingLevelNo();
}
}
}
throw new RuntimeException("检验水平不存在:" + value);
}
private void assertMethodExists(String site, String methodNo, String inspectionTypeNo) {
QcMethodData query = new QcMethodData();
query.setSite(site);
query.setMethodNo(methodNo);
List<QcMethodData> list = qcMapper.queryMethodList(query);
QcMethodData found = null;
if (list != null) {
for (QcMethodData method : list) {
if (methodNo.equals(method.getMethodNo())) {
found = method;
break;
}
}
}
if (found == null) {
throw new RuntimeException("检验方法不存在:" + methodNo);
}
if (StringUtils.isNotBlank(inspectionTypeNo) && StringUtils.isNotBlank(found.getInspectionTypeNo())
&& !inspectionTypeNo.equals(found.getInspectionTypeNo())) {
throw new RuntimeException("方法编码【" + methodNo + "】与检验类型不匹配");
}
}
private String blankToNull(String value) {
return StringUtils.isBlank(value) ? null : value;
}
// ======================= 质检员信息维护 =======================
/**
@ -735,164 +937,83 @@ public class QcServiceImpl implements QcService {
@Override
@Transactional
public void uploadTemplateExcel(MultipartFile file, GetParamInData paraData) {
try{
// 转流
InputStream is = file.getInputStream();
// 读取工作簿
XSSFWorkbook workbook = new XSSFWorkbook(is);
// 读取工作表
XSSFSheet sheet = workbook.getSheetAt(0);
// 获取行数
int rows = sheet.getPhysicalNumberOfRows();
// 声明对象
QcTemplateData task = null;
//排除标准数据下的空白行数据
int nonEmptyRows = 0;
for (int i = 0; i < rows; i++) {
XSSFRow row = sheet.getRow(i);
if (row != null && row.getCell(0) != null && StringUtils.isNotBlank(row.getCell(0).toString())) {
nonEmptyRows++;
}
}
// 遍历每一行从第二行开始
for (int j = 1; j < nonEmptyRows; j++) {
// 实例化对象
task = new QcTemplateData();
// 获得该行
XSSFRow row = sheet.getRow(j);
//截取site和bu
String[] split = paraData.getSite().split("_");
// 为对象赋值
task.setSite(split[0]);
task.setBuNo(split[1]);
//获取用户传入的 检验类型描述
String type = row.getCell(9).getStringCellValue();
//根据type 设置检验类型编码 检验模板编码
if (type.equals("IPQC")){
task.setInspectionTypeNo("101");
task.setTemplateId("IPQC-" + qcMapper.getTemplateNo(task));
}else if (type.equals("IQC")){
task.setInspectionTypeNo("105");
task.setTemplateId("IQC-" + qcMapper.getTemplateNo(task));
}else if (type.equals("FAI")){
task.setInspectionTypeNo("106");
task.setTemplateId("FAI-" + qcMapper.getTemplateNo(task));
}else if (type.equals("FQC")){
task.setInspectionTypeNo("107");
task.setTemplateId("FQC-" + qcMapper.getTemplateNo(task));
}else if (type.equals("PQC")){
task.setInspectionTypeNo("108");
task.setTemplateId("PQC-" + qcMapper.getTemplateNo(task));
}
// task.setInspectionTypeNo(row.getCell(9).getRawValue());
// 获取编码
// String templateNo = qcMapper.getTemplateNo(task);
// if ("101".equals(task.getInspectionTypeNo()) || "102".equals(task.getInspectionTypeNo()) || "103".equals(task.getInspectionTypeNo()) || "104".equals(task.getInspectionTypeNo())) {
// task.setTemplateId("IPQC-" + templateNo);
// } else if ("105".equals(task.getInspectionTypeNo())) {
// task.setTemplateId("IQC-" + templateNo);
// } else if ("106".equals(task.getInspectionTypeNo())) {
// task.setTemplateId("FAI-" + templateNo);
// } else if ("107".equals(task.getInspectionTypeNo())) {
// task.setTemplateId("FQC-" + templateNo);
// } else if ("108".equals(task.getInspectionTypeNo())) {
// task.setTemplateId("PQC-" + templateNo);
// }
//判断用户是否输入 抽样方案编码默认抽样数量和默认抽样比例 其中之一
boolean isFlag = false;
task.setTemplateName(row.getCell(0).getStringCellValue());
// task.setSamplingProgrammeNo(row.getCell(1).getRawValue());
// task.setSamplingLevelNo(row.getCell(2).getRawValue());
if (row.getCell(1)==null){
task.setSamplingProgrammeNo(null);
}else {
isFlag = true;
task.setSamplingProgrammeNo(row.getCell(1).getRawValue());
}
if (row.getCell(2)==null){
task.setSamplingLevelNo(null);
}else {
task.setSamplingLevelNo(row.getCell(2).getRawValue());
}
if (row.getCell(3) == null){
task.setInspectionCycle(null);
}else {
task.setInspectionCycle(BigDecimal.valueOf(row.getCell(3).getNumericCellValue()));
}
if (row.getCell(4) == null){
task.setDefaultSamplingQuantity(null);
}else {
isFlag = true;
task.setDefaultSamplingQuantity(BigDecimal.valueOf(row.getCell(4).getNumericCellValue()));
}
if (row.getCell(5) == null){
task.setDefaultSamplingProportion(null);
}else {
isFlag = true;
task.setDefaultSamplingProportion(BigDecimal.valueOf(row.getCell(5).getNumericCellValue()));
}
if (!isFlag){
throw new RuntimeException("抽象方案编码、默认抽样数量和默认抽样比例至少填写一个!");
}
if (row.getCell(6) == null){
task.setAql(null);
}else {
task.setAql(BigDecimal.valueOf(row.getCell(6).getNumericCellValue()));
}
if (row.getCell(7) == null){
task.setAc(null);
}else {
task.setAc(BigDecimal.valueOf(row.getCell(7).getNumericCellValue()));
}
if (row.getCell(8) == null){
task.setRe(null);
}else {
task.setRe(BigDecimal.valueOf(row.getCell(8).getNumericCellValue()));
}
if (row.getCell(10) == null){
task.setTemplateRemark(null);
}else {
task.setTemplateRemark(row.getCell(10).getStringCellValue());
}
// task.setTemplateVersion(row.getCell(11).getRawValue());
if (row.getCell(11)==null){
task.setTemplateVersion(null);
}else {
task.setTemplateVersion(row.getCell(11).getRawValue());
}
task.setCreateBy(paraData.getCreateBy());
// 查重
QcTemplateData templateData = qcMapper.selectTemplateByDesc(task);
if(templateData != null){
throw new RuntimeException("该模板已存在已存在!");
String site = QcExcelImportHelper.resolveSite(paraData.getSite());
String buNo = QcExcelImportHelper.resolveBuNo();
List<QcInspectionTypeData> types = loadInspectionTypes(site);
List<QcSamplingInspectionProgrammeData> programmes = loadSamplingProgrammes(site);
List<QcSamplingInspectionLevelData> levels = loadSamplingLevels(site);
List<String> errors = new ArrayList<>();
List<QcTemplateData> toSave = new ArrayList<>();
try (Workbook workbook = QcExcelImportHelper.openWorkbook(file)) {
Sheet sheet = QcExcelImportHelper.getDataSheet(workbook, QcExcelImportHelper.FLAG_TEMPLATE);
Map<String, Integer> headers = QcExcelImportHelper.readHeaderIndex(sheet.getRow(0));
int lastRow = sheet.getLastRowNum();
for (int r = 1; r <= lastRow; r++) {
Row row = sheet.getRow(r);
if (QcExcelImportHelper.isBlankRow(row, headers)) {
continue;
}
// 新增模板
qcMapper.templateSave(task);
// 新增模板中的项目
int cells = row.getLastCellNum();
for (int i = 1; i <= cells - 12; i++) {
String itemNo = row.getCell(11 + i).getStringCellValue();
String itemType = "D";
QcTemplateData data = qcMapper.selectItem(itemNo,itemType,split[1]);
if (data== null){
throw new RuntimeException("BU为"+split[1]+"时,检验项目不存在:"+itemNo);
int excelRow = r + 1;
try {
QcTemplateData task = new QcTemplateData();
task.setSite(site);
task.setBuNo(buNo);
task.setCreateBy(paraData.getCreateBy());
task.setUpdateBy(paraData.getCreateBy());
task.setTemplateName(QcExcelImportHelper.getString(row, headers, "检验模板名称"));
if (StringUtils.isBlank(task.getTemplateName())) {
throw new RuntimeException("检验模板名称不能为空");
}
data.setTemplateId(task.getTemplateId());
data.setOrderId(i);
// 新增
qcMapper.addItemDetails(data);
String typeValue = QcExcelImportHelper.getString(row, headers, "检验类型");
if (StringUtils.isBlank(typeValue)) {
throw new RuntimeException("检验类型不能为空");
}
task.setInspectionTypeNo(QcExcelImportHelper.resolveInspectionTypeNo(typeValue, types));
task.setSamplingProgrammeNo(resolveSamplingProgrammeNo(
QcExcelImportHelper.getString(row, headers, "抽样方案编码"), programmes));
task.setSamplingLevelNo(resolveSamplingLevelNo(
QcExcelImportHelper.getString(row, headers, "检验水平编码"), levels));
task.setInspectionCycle(QcExcelImportHelper.getDecimal(row, headers, "检验完成时间(h)"));
task.setDefaultSamplingQuantity(QcExcelImportHelper.getDecimal(row, headers, "默认抽样数量"));
task.setDefaultSamplingProportion(QcExcelImportHelper.getDecimal(row, headers, "默认抽样比例"));
if (StringUtils.isBlank(task.getSamplingProgrammeNo())
&& task.getDefaultSamplingQuantity() == null
&& task.getDefaultSamplingProportion() == null) {
throw new RuntimeException("抽样方案编码、默认抽样数量和默认抽样比例至少填写一个");
}
if (StringUtils.isNotBlank(task.getSamplingProgrammeNo()) && StringUtils.isBlank(task.getSamplingLevelNo())) {
throw new RuntimeException("填写抽样方案时必须填写检验水平");
}
task.setAql(QcExcelImportHelper.getDecimal(row, headers, "AQL"));
task.setAc(QcExcelImportHelper.getDecimal(row, headers, "AC"));
task.setRe(QcExcelImportHelper.getDecimal(row, headers, "RE"));
task.setTemplateVersion(blankToNull(QcExcelImportHelper.getString(row, headers, "版本号")));
task.setTemplateRemark(blankToNull(QcExcelImportHelper.getString(row, headers, "检验模板备注")));
if (StringUtils.isNotBlank(task.getTemplateVersion())) {
QcTemplateData exists = qcMapper.selectTemplateByDesc(task);
if (exists != null) {
throw new RuntimeException("该模板已存在");
}
}
toSave.add(task);
} catch (RuntimeException e) {
errors.add("第" + excelRow + "行:" + e.getMessage());
}
}
//给新导入为null的orderId排序
qcMapper.updateQCDetailOrderIdNull();
}catch (Exception e){
throw new RuntimeException("导入失败:"+e.getMessage());
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException("导入失败:" + e.getMessage());
}
if (toSave.isEmpty() && errors.isEmpty()) {
throw new RuntimeException("没有可导入的数据,请检查Excel内容");
}
if (!errors.isEmpty()) {
throw new RuntimeException("导入失败:<br/>" + String.join("<br/>", errors));
}
for (QcTemplateData task : toSave) {
task.setTemplateId(QcExcelImportHelper.buildTypePrefixNo(task.getInspectionTypeNo(), qcMapper.getTemplateNo(task)));
qcMapper.templateSave(task);
}
}

4
src/main/java/com/heai/modules/pms/service/QcService.java

@ -80,6 +80,10 @@ public interface QcService {
void taskUploadExcel(MultipartFile file, GetParamInData data);
void uploadMethodExcel(MultipartFile file, GetParamInData data);
void downloadQcImportTemplate(String flag, String site, javax.servlet.http.HttpServletResponse response);
void saveItemDetailed(QcTemplateData data);
PageUtils samplingQtySearch(QcSamplingInspectionQtyData data);

500
src/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);
}
}
Loading…
Cancel
Save