更新导入插件
parent
74d7f757f3
commit
0f1069cac3
|
|
@ -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("模板类型错误");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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("标准导入模板不正确,请确认模板信息");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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("标准导入模板不正确,请确认模板信息");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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("标准导入模板不正确,请确认模板信息");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 行索引(从1开始,Excel格式)
|
||||
* @param col 列索引(从1开始,Excel格式)
|
||||
* @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 行索引(从1开始,Excel格式)
|
||||
* @param col 列索引(从1开始,Excel格式)
|
||||
* @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 所有单元格值的Map,key为"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 + ")";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue