更新导入插件

main
HUOJIN\92525 2025-09-09 13:32:59 +08:00
parent 74d7f757f3
commit 0f1069cac3
6 changed files with 166 additions and 74 deletions

View File

@ -1,5 +1,6 @@
package com.youchain.basicdata.service.impl;
import cn.idev.excel.read.metadata.ReadSheet;
import com.youchain.basicdata.domain.BillType;
import com.youchain.basicdata.domain.Item;
import com.youchain.basicdata.repository.*;
@ -21,7 +22,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;
@ -52,18 +52,18 @@ public class ImportAsnServiceImpl implements ImportAsnService {
// String type = FileUtil.getFileType(suffix);
// FileUtil.upload(file, properties.getPath().getPath() + type + File.separator);
// 验证模板类型是否正确
isValidTemplateType(file, templateType);
List<ReadSheet> readSheets = isValidTemplateType(file, templateType);
// 根据模板类型进行不同的处理
switch (templateType) {
case "template1":
baseImportTemplate(file);
baseImportTemplate(file, readSheets);
break;
case "template2":
bigItemTemplate(file);
bigItemTemplate(file, readSheets);
break;
case "template3":
invoicePackingTemplate(file);
invoicePackingTemplate(file, readSheets);
break;
default:
throw new BadRequestException("不支持的模板类型: " + templateType);
@ -72,26 +72,25 @@ public class ImportAsnServiceImpl implements ImportAsnService {
// 处理标准模板
@Transactional
public void baseImportTemplate(MultipartFile file) {
public void baseImportTemplate(MultipartFile file, List<ReadSheet> readSheets) {
// 读取sheet数据
List<BaseImport> dataList = FastExcelUtil.readExcelData(file, BaseImport.class, 0, 1);
List<BaseImport> dataList = FastExcelUtil.readExcelData(file, BaseImport.class, readSheets.get(0).getSheetNo(), 1);
//批量导入
importAsnData(dataList);
}
//处理大物模板
private void bigItemTemplate(MultipartFile file) {
private void bigItemTemplate(MultipartFile file, List<ReadSheet> readSheets) {
// 获取发票号
FastExcelCellListener reader = new FastExcelCellListener()
.addTargetCell(5, 55); // invoiceNo
Map<String, String> cellValues = FastExcelUtil.readExcelCellValues(file, reader);
String invoiceNo = cellValues.get("5-55");
.addTargetCell(6, 55); // invoiceNo
FastExcelUtil.readExcelCellValues(file, reader, readSheets.get(0).getSheetNo());
String invoiceNo = reader.getCellValue(6, 55);
// 读取两个sheet的数据
List<BaseImport> sheet1Data = FastExcelUtil.readExcelData(file, BaseImport.class, 0, 21);
List<BaseImport> sheet2Data = FastExcelUtil.readExcelData(file, BaseImport.class, 1, 21);
List<BaseImport> sheet1Data = FastExcelUtil.readExcelData(file, BaseImport.class, readSheets.get(0).getSheetNo(), 21);
List<BaseImport> sheet2Data = FastExcelUtil.readExcelData(file, BaseImport.class, readSheets.get(1).getSheetNo(), 21);
//大物数据处理
List<BaseImport> dataList = bigItemDataProcess(invoiceNo, sheet1Data, sheet2Data);
@ -102,21 +101,20 @@ public class ImportAsnServiceImpl implements ImportAsnService {
}
// 处理发票箱单模板
private void invoicePackingTemplate(MultipartFile file) {
// 获取发票
FastExcelCellListener reader = new FastExcelCellListener().addTargetCell(2, 11); // invoiceNo
Map<String, String> cellValues = FastExcelUtil.readExcelCellValues(file, reader);
String invoiceNo = cellValues.get("2-11");
private void invoicePackingTemplate(MultipartFile file, List<ReadSheet> readSheets) {
// 读取第二个sheet的invoiceNo
FastExcelCellListener reader = new FastExcelCellListener().addTargetCell(3, 11); // invoiceNo
FastExcelUtil.readExcelCellValues(file, reader, readSheets.get(1).getSheetNo());//
String invoiceNo = reader.getCellValue(3, 11);
// 读取sheet数据
List<InvoicePackingImport> sheet1Data = FastExcelUtil.readExcelData(file, InvoicePackingImport.class, 0, 24);
List<InvoicePackingImport> sheet1Data = FastExcelUtil.readExcelData(file, InvoicePackingImport.class, readSheets.get(0).getSheetNo(), 24);
// 读取sheet数据
List<InvoicePackingImport> sheet2Data = FastExcelUtil.readExcelData(file, InvoicePackingImport.class, 1, 5);
List<InvoicePackingImport> sheet2Data = FastExcelUtil.readExcelData(file, InvoicePackingImport.class, readSheets.get(1).getSheetNo(), 5);
//发票箱单数据处理
List<BaseImport> dataList = invoicePackingDataProcess(invoiceNo, sheet1Data,sheet2Data);
List<BaseImport> dataList = invoicePackingDataProcess(invoiceNo, sheet1Data, sheet2Data);
//批量导入
importAsnData(dataList);
@ -239,41 +237,56 @@ public class ImportAsnServiceImpl implements ImportAsnService {
}
//验证模板是否使用正确
private void isValidTemplateType(MultipartFile file, String templateType) {
private List<ReadSheet> isValidTemplateType(MultipartFile file, String templateType) {
// 根据模板类型进行不同的处理
if ("template1".equals(templateType)) {
List<ReadSheet> readSheets = FastExcelUtil.readSheets(file);
if (readSheets.size() != 1) {
throw new BadRequestException("标准导入模板中只能包含1个sheet目录");
}
List<String> requiredColumns = Arrays.asList("INVOICE NO.", "BOI", "PO&LN NO.", "PART NO.", "DESCRIPTION", "Q'TY \n" + "(PCS)", "C/NO.");
List<String> headers = FastExcelUtil.readHeadContent(file, requiredColumns, 0, 0);
List<String> headers = FastExcelUtil.readHeadContent(file, readSheets.get(0).getSheetNo(), 0);
if (!SmartStringUtil.containsAllIgnoreCase(requiredColumns, headers)) {
throw new BadRequestException("标准导入模板不正确,请确认模板信息");
}
} else if ("template2".equals(templateType)){
return readSheets;
} else if ("template2".equals(templateType)) {
List<ReadSheet> readSheets = FastExcelUtil.readSheets(file);
if (readSheets.size() != 2) {
throw new BadRequestException("大物导入模板中只能包含2个sheet目录");
}
List<String> requiredColumns = Arrays.asList("BOI", "PO&LN NO.", "PART NO.", "DESCRIPTION", "Q'TY \n" + "(PCS)");
List<String> sheet1Headers = FastExcelUtil.readHeadContent(file, requiredColumns, 0, 20);
List<String> sheet1Headers = FastExcelUtil.readHeadContent(file, readSheets.get(0).getSheetNo(), 20);
if (!SmartStringUtil.containsAllIgnoreCase(requiredColumns, sheet1Headers)) {
throw new BadRequestException("大物第1个Sheet目录模板不正确,请确认模板信息");
}
List<String> requiredColumns2 = Collections.singletonList("C/NO.");
List<String> sheet2Headers = FastExcelUtil.readHeadContent(file, requiredColumns2, 1, 20);
List<String> sheet2Headers = FastExcelUtil.readHeadContent(file, readSheets.get(1).getSheetNo(), 20);
if (!SmartStringUtil.containsAllIgnoreCase(requiredColumns2, sheet2Headers)) {
throw new BadRequestException("大物第2个Sheet目录模板不正确,请确认模板信息");
}
return readSheets;
} else if ("template3".equals(templateType)) {
List<ReadSheet> readSheets = FastExcelUtil.readSheets(file);
if (readSheets.size() != 2) {
throw new BadRequestException("发票箱单模板中只能包含2个sheet目录");
}
List<String> requiredColumns = Collections.singletonList("(BOI)");
List<String> headers = FastExcelUtil.readHeadContent(file, requiredColumns, 0, 23);
List<String> headers = FastExcelUtil.readHeadContent(file, readSheets.get(0).getSheetNo(), 23);
if (!SmartStringUtil.containsAllIgnoreCase(requiredColumns, headers)) {
throw new BadRequestException("发票箱单第1个Sheet目录模板不正确,请确认模板信息");
}
List<String> requiredColumns2 = Arrays.asList("A-PROS\n" + "CASE NO", "KMT NO. PO&LN NO.", "PART NO.", "DESCRIPTION", "Q'TY");
List<String> headers2 = FastExcelUtil.readHeadContent(file, requiredColumns2, 1, 4);
List<String> headers2 = FastExcelUtil.readHeadContent(file, readSheets.get(1).getSheetNo(), 4);
if (!SmartStringUtil.containsAllIgnoreCase(requiredColumns2, headers2)) {
throw new BadRequestException("发票箱单第2个Sheet目录模板不正确,请确认模板信息");
}
return readSheets;
} else {
throw new BadRequestException("模板类型错误");
}
}

View File

@ -322,7 +322,7 @@ public class ImportBomAccountServiceImpl implements ImportBomAccountService {
"组顺/刻印号前2位",
"台用量"
);
List<String> headers = FastExcelUtil.readHeadContent(file, requiredColumns, 0, 0);
List<String> headers = FastExcelUtil.readHeadContent(file, 0, 0);
if (!SmartStringUtil.containsAllIgnoreCase(requiredColumns, headers)) {
throw new BadRequestException("标准导入模板不正确,请确认模板信息");
}

View File

@ -111,7 +111,7 @@ public class ImportItemServiceImpl implements ImportItemService {
"高",
"保管期限"
);
List<String> headers = FastExcelUtil.readHeadContent(file, requiredColumns, 0, 0);
List<String> headers = FastExcelUtil.readHeadContent(file, 0, 0);
if (!SmartStringUtil.containsAllIgnoreCase(requiredColumns, headers)) {
throw new BadRequestException("标准导入模板不正确,请确认模板信息");
}

View File

@ -127,7 +127,7 @@ public class ImportPointServiceImpl implements ImportPointService {
"纳所",
"标签类型"
);
List<String> headers = FastExcelUtil.readHeadContent(file, requiredColumns, 0, 0);
List<String> headers = FastExcelUtil.readHeadContent(file, 0, 0);
if (!SmartStringUtil.containsAllIgnoreCase(requiredColumns, headers)) {
throw new BadRequestException("标准导入模板不正确,请确认模板信息");
}

View File

@ -2,42 +2,45 @@ package com.youchain.utils;
import cn.idev.excel.context.AnalysisContext;
import cn.idev.excel.read.listener.ReadListener;
import com.youchain.exception.BadRequestException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class FastExcelCellListener implements ReadListener<Map<Integer, String>> {
private final Map<String, String> cellValues = new HashMap<>();
private final Set<String> targetCells = new HashSet<>();
private boolean isCellRead = false;
private final Map<CellPosition, String> cellValues = new ConcurrentHashMap<>();
private final Set<CellPosition> targetCells = new HashSet<>();
private volatile boolean allCellsRead = false;
/**
*
* @param row 0
* @param col 0
*
* @param row 1Excel
* @param col 1Excel
* @return
*/
public FastExcelCellListener addTargetCell(int row, int col) {
targetCells.add(row + "-" + col);
if (row < 1 || col < 1) {
throw new BadRequestException("行列索引必须从1开始");
}
targetCells.add(new CellPosition(row, col));
return this;
}
@Override
public void invoke(Map<Integer, String> data, AnalysisContext context) {
if (isCellRead) {
public void invoke(Map<Integer, String> rowData, AnalysisContext context) {
// 如果所有目标单元格已读取完毕,直接返回
if (allCellsRead) {
return;
}
int currentRowIndex = context.readRowHolder().getRowIndex()-1;
// EasyExcel 的行索引从0开始转换为Excel格式从1开始
int currentRowIndex = context.readRowHolder().getRowIndex() + 1;
for (String targetCell : targetCells) {
String[] parts = targetCell.split("-");
int targetRow = Integer.parseInt(parts[0]);
int targetCol = Integer.parseInt(parts[1]);
if (currentRowIndex == targetRow-1) {
String cellValue = data.get(targetCol-1);
// 检查当前行是否包含目标单元格
for (CellPosition targetCell : targetCells) {
if (currentRowIndex == targetCell.row) {
// 列索引需要减1转换为0-based
String cellValue = rowData.get(targetCell.col - 1);
if (cellValue != null) {
cellValues.put(targetCell, cellValue);
}
@ -46,7 +49,7 @@ public class FastExcelCellListener implements ReadListener<Map<Integer, String>>
// 检查是否所有目标单元格都已读取
if (cellValues.size() == targetCells.size()) {
isCellRead = true;
allCellsRead = true;
}
}
@ -57,19 +60,56 @@ public class FastExcelCellListener implements ReadListener<Map<Integer, String>>
/**
*
* @param row 0
* @param col 0
* @return
*
* @param row 1Excel
* @param col 1Excel
* @return null
*/
public String getCellValue(int row, int col) {
return cellValues.get(row + "-" + col);
return cellValues.get(new CellPosition(row, col));
}
/**
*
* @return Map
* key
*
* @return Mapkey"row-col"
*/
public Map<String, String> getAllCellValues() {
return new HashMap<>(cellValues);
Map<String, String> result = new HashMap<>();
cellValues.forEach((pos, value) ->
result.put(pos.row + "-" + pos.col, value));
return result;
}
/**
*
*/
public static class CellPosition {
private final int row;
private final int col;
public CellPosition(int row, int col) {
this.row = row;
this.col = col;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CellPosition that = (CellPosition) o;
return row == that.row && col == that.col;
}
@Override
public int hashCode() {
return Objects.hash(row, col);
}
@Override
public String toString() {
return "(" + row + "," + col + ")";
}
}
}

View File

@ -1,7 +1,9 @@
package com.youchain.utils;
import cn.idev.excel.ExcelReader;
import cn.idev.excel.ExcelWriter;
import cn.idev.excel.FastExcel;
import cn.idev.excel.read.metadata.ReadSheet;
import cn.idev.excel.write.metadata.WriteSheet;
import cn.idev.excel.write.metadata.style.WriteCellStyle;
import cn.idev.excel.write.metadata.style.WriteFont;
@ -12,13 +14,14 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
@ -170,7 +173,7 @@ public class FastExcelUtil {
}
public static List<Map<Integer, Object>> readExcelData2(MultipartFile file, int headRowNumber) {
public static List<Map<Integer, Object>> readExcelData2(MultipartFile file, int headRowNumber) {
try {
return FastExcel.read(file.getInputStream())
.sheet()
@ -188,10 +191,10 @@ public class FastExcelUtil {
* @param file Excel
* @param reader
*/
public static Map<String, String> readExcelCellValues(MultipartFile file, FastExcelCellListener reader) {
public static Map<String, String> readExcelCellValues(MultipartFile file, FastExcelCellListener reader, int sheetNo) {
try {
FastExcel.read(file.getInputStream(), reader)
.sheet()
.sheet(sheetNo)
.doReadSync();
} catch (IOException e) {
throw new BadRequestException("数据格式存在问题,无法读取");
@ -230,13 +233,9 @@ public class FastExcelUtil {
/**
* Excel
*
* @param requiredColumns
* @return true
*/
public static List<String> readHeadContent(MultipartFile file, List<String> requiredColumns, int sheetNo, int headRowNumber) {
if (requiredColumns.isEmpty()) {
return Collections.emptyList();
}
public static List<String> readHeadContent(MultipartFile file, int sheetNo, int headRowNumber) {
try {
//判断头部内容是否包含所有必填列
return readHeadContent(file.getInputStream(), sheetNo, headRowNumber);
@ -245,8 +244,48 @@ public class FastExcelUtil {
}
}
private static String readHeadContent(File file, int headRowNumber) {
return "";
public static List<ReadSheet> readSheets(MultipartFile file) {
try (ExcelReader excelReader = FastExcel.read(file.getInputStream()).build()) {
// 获取所有Sheet
List<ReadSheet> allSheets = excelReader.excelExecutor().sheetList();
// 使用 POI 检测隐的sheet
Set<String> hiddenSheetNames = getHiddenSheetNames(file);
//过滤隐藏的sheet
return allSheets.stream()
.filter(sheet -> !hiddenSheetNames.contains(sheet.getSheetName()))
.collect(Collectors.toList());
} catch (IOException e) {
log.error("读取Excel Sheet信息失败", e);
throw new BadRequestException("读取Excel Sheet信息失败");
}
}
/**
* Sheet
*
* @param file
*/
private static Set<String> getHiddenSheetNames(MultipartFile file) {
Set<String> hiddenSheets = new HashSet<>();
try (InputStream inputStream = file.getInputStream();
Workbook workbook = WorkbookFactory.create(inputStream)) {
int numberOfSheets = workbook.getNumberOfSheets();
for (int i = 0; i < numberOfSheets; i++) {
if (workbook.isSheetHidden(i) || workbook.isSheetVeryHidden(i)) {
String sheetName = workbook.getSheetName(i);
hiddenSheets.add(sheetName);
}
}
} catch (Exception e) {
throw new BadRequestException("获取隐藏的Sheet名称失败");
}
return hiddenSheets;
}