public Boolean importMaterial(MultipartFile excel/*,String selectedCompanyName*/) throws IOException { Workbook workbook; UserContext.UserInfo currentUserInfo = UserContext.getCurrentUserInfo(); String currentUserName = null == currentUserInfo ? null : currentUserInfo.getUserName(); try { File file = multiPartFileToFile2(excel); FileInputStream excelFile = new FileInputStream(file); workbook = new XSSFWorkbook(excelFile); Sheet sheet = workbook.getSheetAt(0); Project project = new Project(); project.setCreatedTime(ZonedDateTime.now(ZoneId.of("UTC"))); project.setUpdatedTime(ZonedDateTime.now(ZoneId.of("UTC"))); project.setCreatedBy(StringUtils.isBlank(project.getCreatedBy()) ? currentUserName : project.getCreatedBy()); project.setUpdatedBy(StringUtils.isBlank(project.getUpdatedBy()) ? currentUserName : project.getUpdatedBy()); //project.setCompany_name(selectedCompanyName); project.setIs_ask(IsAskEnum.待审批); List<MaterialApply> materialApplyList = new ArrayList<>(); boolean projectDataFound = false; boolean materialDataFound = false; for (Row row : sheet) { if (!projectDataFound) { if (isDataRow(row, 0, "申请单号:")) { project.setId(UniqueIdGenerator.generateUniqueId()); extractProjectData(row, project); projectDataFound = true; } } else { if (isDataRow(row, 1, "物料编码")) { materialDataFound = true; continue; } if (materialDataFound && isMaterialDataRow(row)) { MaterialApply materialApply = new MaterialApply(); materialApply.setId(UniqueIdGenerator.generateUniqueId()); materialApply.setProject_id(project.getId()); materialApply.setRequest_no(project.getRequest_no()); materialApply.setData_from("Excel导入"); materialApply.setCreated_by(StringUtils.isBlank(materialApply.getCreated_by()) ? currentUserName : materialApply.getCreated_by()); materialApply.setUpdated_by(StringUtils.isBlank(materialApply.getUpdated_by()) ? currentUserName : materialApply.getUpdated_by()); extractMaterialData(row, materialApply); materialApplyList.add(materialApply); //handleItemcode(materialApply.getMaterial_code()); } else if (isDataRow(row, 0, "下单原因")) { String applyReason = getCellStringValue(row, 2); project.setApply_reason(applyReason); break; // 假设下单原因之后没有更多数据 } } } workbook.close(); QueryWrapper<Project> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("request_no", project.getRequest_no()); queryWrapper.eq("is_del", 0); boolean equals = projectService.exists(queryWrapper); if (equals){ throw new RuntimeException("申请单号已存在"); } //保存申请单数据 projectService.save(project); //保存物料申请单数据 boolean savedBatch = materialApplyService.saveBatch(materialApplyList); List<MultipartFile> excels = new ArrayList<>(); excels.add(excel); SendApproved(project, excels); return savedBatch; } catch (Exception e) { throw new RuntimeException(e); } }
时间: 2025-07-08 09:25:58 浏览: 15
<think>好的,我现在需要分析用户提供的Java方法`importMaterial`,并按照用户的要求进行介绍。首先,我得仔细阅读这段代码,理解它的功能、结构以及可能的业务场景。用户可能希望了解这个方法的作用、实现步骤、异常处理,或者代码中的某些细节。
首先,我会通读整个方法,确定它的大致流程。看起来这是一个处理Excel文件导入的方法,用于导入物料申请数据。方法接收一个MultipartFile参数,可能来自文件上传,返回一个Boolean表示操作是否成功。注释掉的`selectedCompanyName`参数可能表示这个功能尚未启用或还在开发中。
接下来,我会分解代码的结构。方法开始时创建了一个Workbook对象,用于处理Excel文件。然后获取当前用户信息,处理用户上下文。接着,将MultipartFile转换为File,并读取Excel内容。这里使用了Apache POI的XSSFWorkbook来处理.xlsx格式的文件。
然后,代码初始化了一个Project对象,设置创建和更新时间,以及操作用户。接着遍历Excel的工作表,分为两个主要部分:处理项目数据和物料数据。项目数据的部分通过查找特定的行(如“申请单号:”)来提取信息,物料数据则在识别“物料编码”行后开始处理。每个物料申请被封装为MaterialApply对象,并添加到列表中。
在处理完数据后,代码检查申请单号是否已存在,避免重复。如果不存在,则保存Project和MaterialApply列表,并发送审批请求。最后返回保存结果,捕获异常并抛出运行时异常。
需要注意的是,代码中有一些可能的问题点,例如异常处理部分直接抛出RuntimeException,可能不够细致;文件处理部分将MultipartFile转换为File,可能存在临时文件未清理的问题。此外,注释掉的company_name相关代码可能需要后续处理。
在向用户解释时,需要结构清晰,分步骤说明方法的流程,指出关键点,如数据提取、校验、保存,以及潜在的注意事项。同时,要使用中文,避免技术术语过于晦涩,确保用户能够理解每个步骤的作用和可能的影响。</think>以下是您提供的`importMaterial`方法的逐步解析:
---
### **方法功能概述**
这是一个**Excel物料申请数据导入方法**,主要实现:
1. 解析Excel文件中的项目信息和物料申请数据
2. 进行数据校验和业务逻辑处理
3. 持久化数据并触发审批流程
---
### **核心代码结构解析**
#### **1. 参数与返回值**
```java
public Boolean importMaterial(MultipartFile excel) throws IOException {
```
- 输入:`MultipartFile`类型的Excel文件
- 输出:保存操作是否成功(Boolean)
- 异常:显式声明抛出IOException
#### **2. 初始化处理**
```java
Workbook workbook;
UserContext.UserInfo currentUserInfo = UserContext.getCurrentUserInfo();
// 获取当前用户信息(用于审计字段)
File file = multiPartFileToFile2(excel);
FileInputStream excelFile = new FileInputStream(file);
workbook = new XSSFWorkbook(excelFile); // 处理.xlsx格式
```
*关键点:使用Apache POI处理Excel,注意文件类型匹配*
#### **3. 数据提取流程**
```java
Sheet sheet = workbook.getSheetAt(0); // 读取第一个工作表
// 初始化项目对象
Project project = new Project();
project.setCreatedTime(ZonedDateTime.now(ZoneId.of("UTC"))); // UTC时区时间
project.setIs_ask(IsAskEnum.待审批); // 初始状态设为待审批
// 数据解析逻辑
for (Row row : sheet) {
if (!projectDataFound) {
// 提取项目基本信息(通过"申请单号:"定位)
if (isDataRow(row, 0, "申请单号:")) {
project.setId(UniqueIdGenerator.generateUniqueId());
extractProjectData(row, project);
projectDataFound = true;
}
} else {
// 物料数据区识别(通过"物料编码"列)
if (isDataRow(row, 1, "物料编码")) {
materialDataFound = true;
continue;
}
// 物料数据行处理
if (materialDataFound && isMaterialDataRow(row)) {
MaterialApply materialApply = new MaterialApply();
materialApply.setProject_id(project.getId()); // 关联项目ID
extractMaterialData(row, materialApply);
materialApplyList.add(materialApply);
}
}
}
```
*流程图:*
```
开始读取Sheet
├─ 定位"申请单号:"行 → 初始化项目对象
└─ 定位"物料编码"行 → 开始遍历物料数据
```
#### **4. 数据校验与存储**
```java
// 校验申请单号唯一性
QueryWrapper<Project> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("request_no", project.getRequest_no())
.eq("is_del", 0);
if (projectService.exists(queryWrapper)){
throw new RuntimeException("申请单号已存在");
}
// 持久化操作
projectService.save(project);
materialApplyService.saveBatch(materialApplyList);
// 触发审批流程
SendApproved(project, excels);
```
*关键校验逻辑:*
$$ \text{存在性校验} = \exists \text{ request\_no} \land \text{is\_del}=0 $$
#### **5. 异常处理**
```java
try {
// 主逻辑
} catch (Exception e) {
throw new RuntimeException(e); // 建议细化异常类型
}
```
*潜在改进点:建议区分IOException、业务异常等类型*
---
### **关键注意事项**
1. **文件处理风险**
- `multiPartFileToFile2`可能产生临时文件未清理
- 建议使用流式处理代替文件转换
2. **事务一致性**
- `save`和`saveBatch`操作未使用事务管理
- 建议添加`@Transactional`注解
3. **性能优化**
- 大数据量时`saveBatch`可能效率低
- 可考虑分批提交或使用MyBatis Plus的批量插入优化
4. **扩展性设计**
- 当前硬编码读取第一个Sheet(`getSheetAt(0)`)
- 建议通过配置指定Sheet名称或索引
---
### **典型业务场景**
适用于以下流程:
1. 用户上传Excel格式的物料申请单
2. 系统自动解析并生成待审批申请
3. 数据校验通过后进入审批流程
---
是否需要针对某个具体代码段(如`extractProjectData`实现细节)或业务逻辑做进一步解析?
阅读全文
相关推荐


















