实体类
java
@Data
@ToString
@AllArgsConstructor
@NoArgsConstructor
@TableName("zhuzao_xiaohao_lingwai_daoru")
public class ZhuzaoLingWaiData implements Serializable {
@Excel(name = "日期")
private String date;
@Excel(name = "批次号")
private String batchno;
@Excel(name = "第几周")
private String weekday;
@Excel(name = "生产线")
private String productline;
@Excel(name = "图号")
private String produtname;
@Excel(name = "物料编码")
private String productdescription;
@Excel(name = "产品名称")
private String productweight;
@Excel(name = "铸件毛重")
private String box;
@Excel(name = "件/箱")
private String classes;
@Excel(name = "班次")
private String ronghualu;
@Excel(name = "熔化(炉)")
private String tieshuit;
@Excel(name = "铁水(t)")
private String zaoxing;
@Excel(name = "造型\n" +
"(箱)")
private String jiaozhuxiang;
@Excel(name = "浇注\n" +
"(箱)")
private String jiaozhujian;
@Excel(name = "浇注\n" +
"(件)")
private String shizhi;
@Excel(name = "试制")
private String zhujiandongshu;
@Excel(name = "铸件吨数")
private String beizhu1;
private String beizhu2;
}
注解类
java
/**
* 自定义导出Excel数据注解
*
* @author ruoyi
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Excel
{
/**
* 导出时在excel中排序
*/
public int sort() default Integer.MAX_VALUE;
/**
* 导出到Excel中的名字.
*/
public String name() default "";
/**
* 日期格式, 如: yyyy-MM-dd
*/
public String dateFormat() default "";
/**
* 如果是字典类型,请设置字典的type值 (如: sys_user_sex)
*/
public String dictType() default "";
/**
* 读取内容转表达式 (如: 0=男,1=女,2=未知)
*/
public String readConverterExp() default "";
/**
* 分隔符,读取字符串组内容
*/
public String separator() default ",";
/**
* BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化)
*/
public int scale() default -1;
/**
* BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
*/
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
/**
* 导出时在excel中每个列的高度
*/
public double height() default 14;
/**
* 导出时在excel中每个列的宽度
*/
public double width() default 16;
/**
* 文字后缀,如% 90 变成90%
*/
public String suffix() default "";
/**
* 当值为空时,字段的默认值
*/
public String defaultValue() default "";
/**
* 提示信息
*/
public String prompt() default "";
/**
* 设置只能选择不能输入的列内容.
*/
public String[] combo() default {};
/**
* 是否需要纵向合并单元格,应对需求:含有list集合单元格)
*/
public boolean needMerge() default false;
/**
* 是否导出数据,应对需求:有时我们需要导出一份模板,这是标题需要但内容需要用户手工填写.
*/
public boolean isExport() default true;
/**
* 另一个类中的属性名称,支持多级获取,以小数点隔开
*/
public String targetAttr() default "";
/**
* 是否自动统计数据,在最后追加一行统计数据总和
*/
public boolean isStatistics() default false;
/**
* 导出类型(0数字 1字符串 2图片)
*/
public ColumnType cellType() default ColumnType.STRING;
/**
* 导出列头背景颜色
*/
public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT;
/**
* 导出列头字体颜色
*/
public IndexedColors headerColor() default IndexedColors.WHITE;
/**
* 导出单元格背景颜色
*/
public IndexedColors backgroundColor() default IndexedColors.WHITE;
/**
* 导出单元格字体颜色
*/
public IndexedColors color() default IndexedColors.BLACK;
/**
* 导出字段对齐方式
*/
public HorizontalAlignment align() default HorizontalAlignment.CENTER;
/**
* 自定义数据处理器
*/
public Class<?> handler() default ExcelHandlerAdapter.class;
/**
* 自定义数据处理器参数
*/
public String[] args() default {};
/**
* 字段类型(0:导出导入;1:仅导出;2:仅导入)
*/
Type type() default Type.ALL;
public enum Type
{
ALL(0), EXPORT(1), IMPORT(2);
private final int value;
Type(int value)
{
this.value = value;
}
public int value()
{
return this.value;
}
}
public enum ColumnType
{
NUMERIC(0), STRING(1), IMAGE(2);
private final int value;
ColumnType(int value)
{
this.value = value;
}
public int value()
{
return this.value;
}
}
}
控制类
java
/**
* 描述:
*
* @author 石加伟
* @date 2024/3/18
*/
@RestController
@RequestMapping("/api/excel")
@Slf4j
public class ZhuzaoLingWaiDataController {
@Autowired
private ZhuzaoLingWaiDataService zhuzaoLingWaiDataService;
@GetMapping("/importExceHTest")
// public Result importExcel111(@RequestParam("file") MultipartFile file) {
public String importExceHTest(String saveDirectory) throws IOException, IllegalAccessException {
// String saveDirectory = "D:\\phoneAuto\\demo2-新副本\\铸造一厂24年3月17日报表 - - (1).xlsx";
Optional<ZhuzaoLingWaiData> maxDateItem = zhuzaoLingWaiDataService.list().stream()
.filter(item -> item.getProductline().equals("灰铁线"))
.max(Comparator.comparing(ZhuzaoLingWaiData::getDate));
ZhuzaoLingWaiData dataWithMaxDate = maxDateItem.get() ;
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS");
LocalDateTime date = LocalDateTime.parse(dataWithMaxDate.getDate(), formatter);
System.out.println("最大日期的时间对象: " + date.toString());
// for (ZhuzaoLingWaiData zhuzaoLingWaiData : list)
// System.out.println(zhuzaoLingWaiData.toString());
List<ZhuzaoLingWaiData> zhuzaoLingWaiData = getimportJobsFromExcel(saveDirectory)
.stream().filter(item -> item.getProductline().equals("灰铁线"))
.collect(Collectors.toList());
// for (ZhuzaoLingWaiData zhuzaoLingWaiData1 : zhuzaoLingWaiData)
// System.out.println("--------------------"+zhuzaoLingWaiData1.toString());
// 假设ZhuzaoLingWaiData类已正确覆盖equals和hashCode方法
// 找出存在于Excel数据中但不在服务数据中的项
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
List<ZhuzaoLingWaiData> notInService = zhuzaoLingWaiData.stream()
.filter(excelItem -> LocalDateTime.parse(excelItem.getDate(), formatter1).isAfter(date))
.collect(Collectors.toList());
// 输出这些数据
boolean b = zhuzaoLingWaiDataService.saveBatch(notInService);
if (b) {
System.out.println("导入成功");
return "导入成功";
} else {
System.out.println("导入失败");
return "导入失败";
}
}
@GetMapping("/importExceQTest")
// public Result importExcel111(@RequestParam("file") MultipartFile file) {
public String importExceQTest(String saveDirectory) throws IOException, IllegalAccessException {
// String saveDirectory = "D:\\phoneAuto\\demo2-新副本\\铸造一厂24年3月17日报表 - - (1).xlsx";
System.out.println(saveDirectory);
Optional<ZhuzaoLingWaiData> maxDateItem = zhuzaoLingWaiDataService.list().stream()
.filter(item -> item.getProductline().equals("球铁线"))
.max(Comparator.comparing(ZhuzaoLingWaiData::getDate));
ZhuzaoLingWaiData dataWithMaxDate = maxDateItem.get();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSSS");
LocalDateTime date = LocalDateTime.parse(dataWithMaxDate.getDate(), formatter);
System.out.println("最大日期的时间对象: " + date.toString());
// for (ZhuzaoLingWaiData zhuzaoLingWaiData : list)
// System.out.println(zhuzaoLingWaiData.toString());
List<ZhuzaoLingWaiData> zhuzaoLingWaiData = getimportJobsFromExcel(saveDirectory).stream()
.filter(item -> item.getProductline().equals("球铁线"))
.collect(Collectors.toList());
// for (ZhuzaoLingWaiData zhuzaoLingWaiData1 : zhuzaoLingWaiData)
// System.out.println("--------------------"+zhuzaoLingWaiData1.toString());
// 假设ZhuzaoLingWaiData类已正确覆盖equals和hashCode方法
// 找出存在于Excel数据中但不在服务数据中的项
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
List<ZhuzaoLingWaiData> notInService = zhuzaoLingWaiData.stream()
.filter(excelItem -> LocalDateTime.parse(excelItem.getDate(), formatter1).isAfter(date))
.collect(Collectors.toList());
// 输出这些数据
boolean b = zhuzaoLingWaiDataService.saveBatch(notInService);
if (b) {
System.out.println("导入成功");
return "导入成功";
} else {
System.out.println("导入失败");
return "导入失败";
}
}
public List<ZhuzaoLingWaiData> getimportJobsFromExcel(String saveDirectory) throws IOException, IllegalAccessException {
// String saveDirectory = "D:\\phoneAuto\\demo2-新副本\\铸造一厂24年3月17日报表 - - (1).xlsx";
File file = new File(saveDirectory);
if (!file.exists() || !file.canRead()) {
System.err.println("指定的文件无法读取。请确保文件路径正确且文件可读。");
return null;
}
List<ZhuzaoLingWaiData> zhuzaoLingWaiData = null;
try {
//已经查询到数据
//需要过滤已经有的数据
//然后把最后数据进行导入
zhuzaoLingWaiData = importJobsFromExcel(file);
} catch (IOException | IllegalAccessException e) {
// 增加了日志记录异常信息,给出了用户友好的错误提示
e.printStackTrace();
System.err.println("导入Excel时发生错误:" + e.getMessage());
}
return zhuzaoLingWaiData;
}
// 在实际导入逻辑中
public static List<ZhuzaoLingWaiData> importJobsFromExcel(File file) throws IOException, IllegalAccessException {
List<ZhuzaoLingWaiData> jobs = new ArrayList<>();
try (InputStream excelFileInputStream = new FileInputStream(file)) {
// 使用try-with-resources确保输入流被关闭
Workbook workbook = null;
try {
workbook = WorkbookFactory.create(excelFileInputStream);
// 假设目标工作表的名称为 "Sheet2"
List<Sheet> matchingSheets = new ArrayList<>();
for (Sheet sheet : workbook) {
String sheetName = sheet.getSheetName();
if (sheetName.contains("铸造部")) {
matchingSheets.add(sheet);
}
}
// 根据名称获取工作表
Sheet sheet = workbook.getSheet(matchingSheets.get(0).getSheetName()); // 获取第一个工作表
Map<String, Integer> columnHeaders = new HashMap<>(); // 初始化一个列名到索引的映射
// 遍历第一行(通常是标题行)收集列名及其索引
Row headerRow = sheet.getRow(1);
for (Cell headerCell : headerRow) {
String columnName = headerCell.getStringCellValue().trim(); // 假设标题单元格内容是字符串
int columnIndex = headerCell.getColumnIndex();
//限制在左边10列
if (columnIndex < 20)
columnHeaders.put(columnName, columnIndex);
}
for (Row row : sheet) {
// System.out.println("第" + (row.getRowNum() + 1) + "行:" );
if (row.getRowNum() == 0) continue; // 跳过标题行
if (row.getRowNum() == 1) continue; // 跳过标题行
ZhuzaoLingWaiData job = new ZhuzaoLingWaiData();
// 根据注解获取字段名与Excel列名的映射关系
Field[] fields = ZhuzaoLingWaiData.class.getDeclaredFields();
for (Field field : fields) {
Excel annotation = field.getAnnotation(Excel.class);
if (annotation != null) {
String columnName = annotation.name();
// 使用之前收集的映射表查找列索引
Cell cell = row.getCell(columnHeaders.get(columnName));
// 将单元格内容转换为对应类型并赋值给实体类属性
if (cell != null) {
Object value = convertCellValue(cell, field.getType());
field.setAccessible(true);
field.set(job, value);
}
}
}
// 现在job对象已经被填充了从Excel读取的数据,可以将其保存到数据库
if (job.getDate() != null && job.getDate() != "")
jobs.add(job);
// saveJobToDatabase(job);
}
} finally {
if (workbook != null) {
workbook.close();
}
}
} catch (IllegalArgumentException e) {
// 特定异常的处理,比如Excel文件格式不正确
System.err.println("无法识别的Excel文件格式。");
e.printStackTrace();
}
// for(ZhuzaoLingWaiData job:jobs){
// System.out.println(job);
// }
return jobs;
}
private static Object convertCellValue(Cell cell, Class<?> targetType) {
// 获取单元格原始类型
CellType cellType = cell.getCellType();
switch (cellType) {
case STRING:
// 将所有非日期类型的值都转换为字符串
return cell.getStringCellValue();
case NUMERIC:
// 检查是否为日期格式
if (DateUtil.isCellDateFormatted(cell)) {
Date cellDate = cell.getDateCellValue();
// 使用SimpleDateFormat来格式化日期
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return dateFormat.format(cellDate);
} else {
// 处理纯数字情况,保留之前逻辑
return String.valueOf(cell.getNumericCellValue());
// try {
// DecimalFormat formatter = new DecimalFormat("#.##");
// double numericValue = cell.getNumericCellValue();
// return formatter.format(numericValue);
// } catch (IllegalStateException e) {
// e.printStackTrace();
// return "Error processing numeric cell";
// }
}
case BOOLEAN:
// 布尔类型转换为字符串
return String.valueOf(cell.getBooleanCellValue());
case FORMULA:
switch (cell.getCachedFormulaResultType()) {
case NUMERIC:
return String.valueOf(cell.getNumericCellValue());
case BOOLEAN:
return String.valueOf(cell.getBooleanCellValue());
case STRING:
return cell.getStringCellValue();
case BLANK:
return cell.getCellFormula() + " (BLANK)";
case ERROR:
return cell.getCellFormula() + " (ERROR)";
default:
throw new IllegalArgumentException("Unexpected cell type after formula evaluation: " + cell.getCachedFormulaResultType());
}
case BLANK:
// 空单元格返回空字符串
return "";
case ERROR:
// 处理 #N/A 或其他错误类型,可以返回自定义错误信息或默认值
return "";
// CELL_TYPE_ERROR 等其他类型处理...
default:
throw new IllegalArgumentException(cellType.toString() + "不支持的单元格类型转换到" + targetType.getName());
}
}
其他类
java
public interface ZhuzaoLingWaiDataService extends IService<ZhuzaoLingWaiData> {
}
@Service
public class ZhuzaoLingWaiDataServiceImpl extends ServiceImpl<ZhuzaoLingWaiDataMapper, ZhuzaoLingWaiData> implements ZhuzaoLingWaiDataService {
}
@Mapper
public interface ZhuzaoLingWaiDataMapper extends BaseMapper<ZhuzaoLingWaiData> {
}
总结
实现了从excel快捷的导入到文件中,文件有重复的列名,限制了列数
java
//限制在左边20列
if (columnIndex < 20)
columnHeaders.put(columnName, columnIndex);