diff --git a/dao/pom.xml b/dao/pom.xml index a142267..4b9e9aa 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -44,5 +44,10 @@ swagger-annotations 1.6.14 + + + com.alibaba + easyexcel + diff --git a/dao/src/main/java/cn/bunny/dao/dto/financial/bill/BillDto.java b/dao/src/main/java/cn/bunny/dao/dto/financial/bill/BillDto.java index 6234230..43ca3ee 100644 --- a/dao/src/main/java/cn/bunny/dao/dto/financial/bill/BillDto.java +++ b/dao/src/main/java/cn/bunny/dao/dto/financial/bill/BillDto.java @@ -37,4 +37,5 @@ public class BillDto { @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd") private LocalDate endDate; -} \ No newline at end of file +} + diff --git a/dao/src/main/java/cn/bunny/dao/dto/financial/bill/BillExportDto.java b/dao/src/main/java/cn/bunny/dao/dto/financial/bill/BillExportDto.java new file mode 100644 index 0000000..27fafe7 --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/dto/financial/bill/BillExportDto.java @@ -0,0 +1,33 @@ +package cn.bunny.dao.dto.financial.bill; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "BillExportDto对象", title = "导出账单信息", description = "导出账单信息") +public class BillExportDto { + + @Schema(name = "userId", title = "绑定的用户id") + private Long userId; + + @Schema(name = "startDate", title = "开始交易日期") + @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd") + @NotNull(message = "开始日期不能为空") + private LocalDate startDate; + + @Schema(name = "endDate", title = "结束交易日期") + @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd") + @NotNull(message = "结束日期不能为空") + private LocalDate endDate; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/dto/financial/bill/user/BillAddUserDto.java b/dao/src/main/java/cn/bunny/dao/dto/financial/bill/user/BillAddUserDto.java index f289df7..fd191bd 100644 --- a/dao/src/main/java/cn/bunny/dao/dto/financial/bill/user/BillAddUserDto.java +++ b/dao/src/main/java/cn/bunny/dao/dto/financial/bill/user/BillAddUserDto.java @@ -1,5 +1,6 @@ package cn.bunny.dao.dto.financial.bill.user; +import com.alibaba.excel.annotation.ExcelProperty; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.Max; @@ -24,23 +25,28 @@ public class BillAddUserDto { @NotNull(message = "类型不能为空") @Min(value = -1, message = "类型格式不正确") @Max(value = 1, message = "类型格式不正确") + @ExcelProperty(index = 0) private Byte type; @Schema(name = "amount", title = "金额") @NotNull(message = "金额不能为空") @Min(value = 0, message = "金额格式不正确") + @ExcelProperty("金额") private BigDecimal amount; @Schema(name = "description", title = "描述") + @ExcelProperty("描述") private String description; @Schema(name = "transactionDate", title = "交易日期") @NotNull(message = "交易日期不能为空") @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss") + @ExcelProperty("交易日期") private LocalDateTime transactionDate; @Schema(name = "categoryId", title = "类别id") @NotNull(message = "类别id不能为空") + @ExcelProperty("类别id") private Long categoryId; } \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/excel/BillUserExportExcel.java b/dao/src/main/java/cn/bunny/dao/excel/BillUserExportExcel.java new file mode 100644 index 0000000..1c9d87e --- /dev/null +++ b/dao/src/main/java/cn/bunny/dao/excel/BillUserExportExcel.java @@ -0,0 +1,47 @@ +package cn.bunny.dao.excel; + +import cn.bunny.dao.common.vo.BaseVo; +import com.alibaba.excel.annotation.ExcelProperty; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +@Schema(name = "BillUserVo对象", title = "用户账单信息返回内容", description = "用户账单信息返回内容") +public class BillUserExportExcel extends BaseVo { + + @Schema(name = "username", title = "类型:1 - 收入,-1 - 支出") + @ExcelProperty("类型:1 - 收入,-1 - 支出") + private String type; + + @Schema(name = "amount", title = "金额") + @ExcelProperty("金额") + private BigDecimal amount; + + @Schema(name = "description", title = "描述") + @ExcelProperty("描述") + private String description; + + @Schema(name = "transactionDate", title = "交易日期") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @JsonSerialize(using = LocalDateTimeSerializer.class) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + @ExcelProperty("交易日期") + private LocalDateTime transactionDate; + + @Schema(name = "categoryName", title = "类别分类") + @ExcelProperty("类别分类") + private String categoryName; + +} \ No newline at end of file diff --git a/dao/src/main/java/cn/bunny/dao/vo/financial/user/BillUserVo.java b/dao/src/main/java/cn/bunny/dao/vo/financial/user/BillUserVo.java index 086c0f4..b95c516 100644 --- a/dao/src/main/java/cn/bunny/dao/vo/financial/user/BillUserVo.java +++ b/dao/src/main/java/cn/bunny/dao/vo/financial/user/BillUserVo.java @@ -1,6 +1,7 @@ package cn.bunny.dao.vo.financial.user; import cn.bunny.dao.common.vo.BaseVo; +import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.fastjson2.annotation.JSONField; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @@ -23,18 +24,22 @@ import java.time.LocalDateTime; public class BillUserVo extends BaseVo { @Schema(name = "username", title = "类型:1 - 收入,-1 - 支出") + @ExcelProperty(index = 0) private Byte type; @Schema(name = "amount", title = "金额") + @ExcelProperty("金额") private BigDecimal amount; @Schema(name = "description", title = "描述") + @ExcelProperty("描述") private String description; @Schema(name = "transactionDate", title = "交易日期") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") @JsonSerialize(using = LocalDateTimeSerializer.class) @JsonDeserialize(using = LocalDateTimeDeserializer.class) + @ExcelProperty("交易日期") private LocalDateTime transactionDate; @Schema(name = "categoryId", title = "分类Id") @@ -43,6 +48,7 @@ public class BillUserVo extends BaseVo { private String categoryId; @Schema(name = "categoryName", title = "类别分类") + @ExcelProperty("类别分类") private String categoryName; } diff --git a/pom.xml b/pom.xml index 5917148..2122b39 100644 --- a/pom.xml +++ b/pom.xml @@ -39,6 +39,7 @@ 2.2 3.1 5.1.0 + 4.0.2 4.3.1 2.12.3 2.3.2 @@ -151,6 +152,12 @@ quartz ${quartz-scheduler.version} + + + com.alibaba + easyexcel + ${easyexcel.version} + diff --git a/service/pom.xml b/service/pom.xml index c32eb8d..2e3bc49 100644 --- a/service/pom.xml +++ b/service/pom.xml @@ -84,12 +84,6 @@ spring-context-support 6.1.6 - - - com.alibaba - easyexcel - 4.0.2 - diff --git a/service/src/main/java/cn/bunny/services/controller/financial/BillController.java b/service/src/main/java/cn/bunny/services/controller/financial/BillController.java index bda3e6c..f83e2b5 100644 --- a/service/src/main/java/cn/bunny/services/controller/financial/BillController.java +++ b/service/src/main/java/cn/bunny/services/controller/financial/BillController.java @@ -1,6 +1,7 @@ package cn.bunny.services.controller.financial; import cn.bunny.dao.dto.financial.bill.BillDto; +import cn.bunny.dao.dto.financial.bill.BillExportDto; import cn.bunny.dao.dto.financial.bill.ExpendWithIncomeDto; import cn.bunny.dao.dto.financial.bill.admin.BillAddDto; import cn.bunny.dao.dto.financial.bill.admin.BillUpdateDto; @@ -18,6 +19,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @@ -67,13 +69,25 @@ public class BillController { return Mono.just(Result.success(pageResult)); } - @Operation(summary = "账单收入和支出", description = "账单收入和支出") + @Operation(summary = "账单收入和支出图表展示", description = "账单收入和支出图表展示") @GetMapping("noManage/getExpendOrIncome") public Mono> getExpendOrIncome(ExpendWithIncomeDto dto) { ExpendWithIncomeListVo vo = billService.getExpendOrIncome(dto); return Mono.just(Result.success(vo)); } + @Operation(summary = "导出用户账单信息", description = "导出用户账单信息") + @PostMapping("noManage/exportBill") + public void exportBill(@Valid @RequestBody BillExportDto dto, HttpServletResponse response) { + billService.exportBill(dto, response); + } + + @Operation(summary = "管理员导出账单信息", description = "管理员导出账单信息") + @PostMapping("exportBillByAdmin") + public void exportBillByAdmin(@Valid @RequestBody BillExportDto dto, HttpServletResponse response) { + billService.exportBillByAdmin(dto, response); + } + @Operation(summary = "添加账单信息", description = "添加账单信息") @PostMapping("addBill") public Mono> addBill(@Valid @RequestBody BillAddDto dto) { diff --git a/service/src/main/java/cn/bunny/services/excel/BillAddUserDAO.java b/service/src/main/java/cn/bunny/services/excel/BillAddUserDAO.java new file mode 100644 index 0000000..fe99a69 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/excel/BillAddUserDAO.java @@ -0,0 +1,11 @@ +package cn.bunny.services.excel; + +import cn.bunny.dao.dto.financial.bill.user.BillAddUserDto; + +import java.util.List; + +public class BillAddUserDAO { + public void save(List list) { + // 如果是mybatis,尽量别直接调用多次insert,自己写一个mapper里面新增一个方法batchInsert,所有数据一次性插入 + } +} \ No newline at end of file diff --git a/service/src/main/java/cn/bunny/services/excel/BillAddUserListener.java b/service/src/main/java/cn/bunny/services/excel/BillAddUserListener.java new file mode 100644 index 0000000..5a6e64d --- /dev/null +++ b/service/src/main/java/cn/bunny/services/excel/BillAddUserListener.java @@ -0,0 +1,60 @@ +package cn.bunny.services.excel; + +import cn.bunny.dao.dto.financial.bill.user.BillAddUserDto; +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.read.listener.ReadListener; +import com.alibaba.excel.util.ListUtils; +import com.alibaba.fastjson2.JSON; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +@Slf4j +public class BillAddUserListener implements ReadListener { + + private static final int BATCH_COUNT = 100; + private final BillAddUserDAO billAddUserDAO; + private List cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); + + public BillAddUserListener() { + billAddUserDAO = new BillAddUserDAO(); + } + + public BillAddUserListener(BillAddUserDAO billAddUserDAO) { + this.billAddUserDAO = billAddUserDAO; + } + + /** + * 这个每一条数据解析都会来调用 + * + * @param data one row value. Is is same as {@link AnalysisContext#readRowHolder()} + */ + @Override + public void invoke(BillAddUserDto data, AnalysisContext context) { + log.info("解析到一条数据:{}", JSON.toJSONString(data)); + cachedDataList.add(data); + // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM + if (cachedDataList.size() >= BATCH_COUNT) { + saveData(); + // 存储完成清理 list + cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT); + } + } + + /** + * 所有数据解析完成了 都会来调用 + */ + @Override + public void doAfterAllAnalysed(AnalysisContext context) { + saveData(); + } + + /** + * 加上存储数据库 + */ + private void saveData() { + log.info("{}条数据,开始存储数据库!", cachedDataList.size()); + billAddUserDAO.save(cachedDataList); + log.info("存储数据库成功!"); + } +} diff --git a/service/src/main/java/cn/bunny/services/factory/BillFactory.java b/service/src/main/java/cn/bunny/services/factory/BillFactory.java new file mode 100644 index 0000000..7f9a0b4 --- /dev/null +++ b/service/src/main/java/cn/bunny/services/factory/BillFactory.java @@ -0,0 +1,97 @@ +package cn.bunny.services.factory; + +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.dto.financial.bill.BillExportDto; +import cn.bunny.dao.dto.financial.bill.ExpendWithIncomeDto; +import cn.bunny.dao.excel.BillUserExportExcel; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.financial.user.expendAndIncome.ExpendWithIncome; +import cn.bunny.services.mapper.financial.BillMapper; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.math.BigDecimal; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.time.LocalDate; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicReference; + +@Component +public class BillFactory { + + @Autowired + private BillMapper billMapper; + + public void exportBill(BillExportDto dto, HttpServletResponse response) { + LocalDate startDate = dto.getStartDate(); + LocalDate endDate = dto.getEndDate(); + + // 设置日期范围 + String dateRange = startDate + "~" + endDate; + + // 导出后的文件名 + String filename = URLEncoder.encode(dateRange, StandardCharsets.UTF_8).replaceAll("\\+", "%20"); + + // 初始化查询条件,将日期向后移一天查询包含当前的数据 + ExpendWithIncomeDto expendWithIncomeDto = new ExpendWithIncomeDto(); + BeanUtils.copyProperties(dto, expendWithIncomeDto); + expendWithIncomeDto.setEndDate(endDate.plusDays(1)); + + // 设置收入和支出的值 + AtomicReference income = new AtomicReference<>(new BigDecimal(0)); + AtomicReference expend = new AtomicReference<>(new BigDecimal(0)); + + // 查询数据 + List expendWithIncomeList = billMapper.selectListByExpendWithIncomeDto(expendWithIncomeDto); + List excelList = expendWithIncomeList.stream().map(expendWithIncome -> { + BillUserExportExcel billUserExportExcel = new BillUserExportExcel(); + BeanUtils.copyProperties(expendWithIncome, billUserExportExcel); + + // 设置收支类型 + String type; + if (expendWithIncome.getType().equals(Byte.parseByte("1"))) { + type = "收入"; + income.updateAndGet(amount -> amount.add(expendWithIncome.getAmount())); + } else { + type = "支出"; + expend.updateAndGet(bigDecimal -> bigDecimal.add(expendWithIncome.getAmount())); + } + billUserExportExcel.setType(type); + + return billUserExportExcel; + }).toList(); + + // 查找模板文件 + String filenameTemplate = Objects.requireNonNull(getClass().getResource("/static/bill-template.xlsx")).getFile(); + if (filenameTemplate == null) throw new BunnyException(ResultCodeEnum.MISSING_TEMPLATE_FILES); + + try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).withTemplate(filenameTemplate).build()) { + // 填充数据 + WriteSheet writeSheet = EasyExcel.writerSheet().build(); + excelWriter.fill(excelList, writeSheet); + + // 写入模板数据 + Map map = new HashMap<>(); + map.put("dateRange", dateRange); + map.put("income", income.get()); + map.put("expend", expend.get()); + map.put("profit", income.get().subtract(expend.get())); + excelWriter.fill(map, writeSheet); + + response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); + response.setCharacterEncoding("utf-8"); + response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + filename + ".xlsx"); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/service/src/main/java/cn/bunny/services/service/financial/BillService.java b/service/src/main/java/cn/bunny/services/service/financial/BillService.java index 3af1a81..2758c89 100644 --- a/service/src/main/java/cn/bunny/services/service/financial/BillService.java +++ b/service/src/main/java/cn/bunny/services/service/financial/BillService.java @@ -1,6 +1,7 @@ package cn.bunny.services.service.financial; import cn.bunny.dao.dto.financial.bill.BillDto; +import cn.bunny.dao.dto.financial.bill.BillExportDto; import cn.bunny.dao.dto.financial.bill.ExpendWithIncomeDto; import cn.bunny.dao.dto.financial.bill.admin.BillAddDto; import cn.bunny.dao.dto.financial.bill.admin.BillUpdateDto; @@ -13,6 +14,7 @@ import cn.bunny.dao.vo.financial.user.BillUserVo; import cn.bunny.dao.vo.financial.user.expendAndIncome.ExpendWithIncomeListVo; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.IService; +import jakarta.servlet.http.HttpServletResponse; import java.util.List; @@ -89,4 +91,20 @@ public interface BillService extends IService { * @return 账单收入和支出 */ ExpendWithIncomeListVo getExpendOrIncome(ExpendWithIncomeDto dto); + + /** + * 导出用户账单 + * + * @param dto 日期选择 + * @param response 响应体 + */ + void exportBill(BillExportDto dto, HttpServletResponse response); + + /** + * 管理员导出账单信息 + * + * @param dto 日期选择 + * @param response 响应体 + */ + void exportBillByAdmin(BillExportDto dto, HttpServletResponse response); } diff --git a/service/src/main/java/cn/bunny/services/service/financial/impl/BillServiceImpl.java b/service/src/main/java/cn/bunny/services/service/financial/impl/BillServiceImpl.java index a38b93d..47782fd 100644 --- a/service/src/main/java/cn/bunny/services/service/financial/impl/BillServiceImpl.java +++ b/service/src/main/java/cn/bunny/services/service/financial/impl/BillServiceImpl.java @@ -3,6 +3,7 @@ package cn.bunny.services.service.financial.impl; import cn.bunny.common.service.context.BaseContext; import cn.bunny.common.service.exception.BunnyException; import cn.bunny.dao.dto.financial.bill.BillDto; +import cn.bunny.dao.dto.financial.bill.BillExportDto; import cn.bunny.dao.dto.financial.bill.ExpendWithIncomeDto; import cn.bunny.dao.dto.financial.bill.admin.BillAddDto; import cn.bunny.dao.dto.financial.bill.admin.BillUpdateDto; @@ -16,6 +17,7 @@ import cn.bunny.dao.vo.financial.user.BillUserVo; import cn.bunny.dao.vo.financial.user.expendAndIncome.CategoryAmount; import cn.bunny.dao.vo.financial.user.expendAndIncome.ExpendWithIncome; import cn.bunny.dao.vo.financial.user.expendAndIncome.ExpendWithIncomeListVo; +import cn.bunny.services.factory.BillFactory; import cn.bunny.services.factory.HomeFactory; import cn.bunny.services.mapper.financial.BillMapper; import cn.bunny.services.service.financial.BillService; @@ -23,6 +25,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -44,6 +47,8 @@ public class BillServiceImpl extends ServiceImpl implements Bi @Autowired private HomeFactory homeFactory; + @Autowired + private BillFactory billFactory; /** * * 账单信息 服务实现类 @@ -208,6 +213,30 @@ public class BillServiceImpl extends ServiceImpl implements Bi .build(); } + /** + * 导出用户账单 + * + * @param dto 日期选择 + * @param response 返回响应 + */ + @Override + public void exportBill(BillExportDto dto, HttpServletResponse response) { + dto.setUserId(BaseContext.getUserId()); + billFactory.exportBill(dto, response); + } + + + /** + * 管理员导出账单信息 + * + * @param dto 日期选择 + * @param response 响应体 + */ + @Override + public void exportBillByAdmin(BillExportDto dto, HttpServletResponse response) { + billFactory.exportBill(dto, response); + } + /** * 删除|批量删除账单信息 * diff --git a/service/src/main/resources/mapper/financial/BillMapper.xml b/service/src/main/resources/mapper/financial/BillMapper.xml index b46f03f..05d1fea 100644 --- a/service/src/main/resources/mapper/financial/BillMapper.xml +++ b/service/src/main/resources/mapper/financial/BillMapper.xml @@ -62,7 +62,7 @@ select * from t_bill b left join t_category tc on b.category_id = tc.id - + and b.user_id = #{dto.userId} diff --git a/service/src/main/resources/static/bill-template.xlsx b/service/src/main/resources/static/bill-template.xlsx new file mode 100644 index 0000000..d35b08c Binary files /dev/null and b/service/src/main/resources/static/bill-template.xlsx differ diff --git a/service/src/test/java/cn/bunny/services/service/financial/impl/BillServiceImplTest.java b/service/src/test/java/cn/bunny/services/service/financial/impl/BillServiceImplTest.java new file mode 100644 index 0000000..4eba565 --- /dev/null +++ b/service/src/test/java/cn/bunny/services/service/financial/impl/BillServiceImplTest.java @@ -0,0 +1,84 @@ +package cn.bunny.services.service.financial.impl; + +import cn.bunny.common.service.exception.BunnyException; +import cn.bunny.dao.dto.financial.bill.ExpendWithIncomeDto; +import cn.bunny.dao.excel.BillUserExportExcel; +import cn.bunny.dao.pojo.result.ResultCodeEnum; +import cn.bunny.dao.vo.financial.user.expendAndIncome.ExpendWithIncome; +import cn.bunny.services.mapper.financial.BillMapper; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; +import org.junit.jupiter.api.Test; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicReference; + +@SpringBootTest +class BillServiceImplTest { + @Autowired + private BillMapper billMapper; + + @Test + void exportBill() { + // 设置数据库查询时间 + ExpendWithIncomeDto expendWithIncomeDto = new ExpendWithIncomeDto(); + expendWithIncomeDto.setUserId(1849444494908125181L); + expendWithIncomeDto.setStartDate(LocalDate.of(2024, 11, 1)); + expendWithIncomeDto.setEndDate(LocalDate.of(2024, 11, 30)); + + // 设置日期范围 + String dateRange = expendWithIncomeDto.getStartDate() + "~" + expendWithIncomeDto.getEndDate(); + + // 设置收入和支出的值 + AtomicReference income = new AtomicReference<>(new BigDecimal(0)); + AtomicReference expend = new AtomicReference<>(new BigDecimal(0)); + + // 查询数据 + List expendWithIncomeList = billMapper.selectListByExpendWithIncomeDto(expendWithIncomeDto); + List excelList = expendWithIncomeList.stream().map(expendWithIncome -> { + BillUserExportExcel billUserExportExcel = new BillUserExportExcel(); + BeanUtils.copyProperties(expendWithIncome, billUserExportExcel); + + // 设置收支类型 + String type; + if (expendWithIncome.getType().equals(Byte.parseByte("1"))) { + type = "收入"; + income.updateAndGet(amount -> amount.add(expendWithIncome.getAmount())); + } else { + type = "支出"; + expend.updateAndGet(bigDecimal -> bigDecimal.add(expendWithIncome.getAmount())); + } + billUserExportExcel.setType(type); + + return billUserExportExcel; + }).toList(); + + String filenameTemplate = Objects.requireNonNull(getClass().getResource("/static/bill-template.xlsx")).getFile(); + if (filenameTemplate == null) throw new BunnyException(ResultCodeEnum.MISSING_TEMPLATE_FILES); + + try (ExcelWriter excelWriter = EasyExcel.write("F:\\数据库备份\\" + dateRange + ".xlsx").withTemplate(filenameTemplate).build()) { + // 填充数据 + WriteSheet writeSheet = EasyExcel.writerSheet().build(); + excelWriter.fill(excelList, writeSheet); + + // 写入模板数据 + Map map = new HashMap<>(); + map.put("dateRange", dateRange); + map.put("income", income.get()); + map.put("expend", expend.get()); + map.put("profit", income.get().subtract(expend.get())); + excelWriter.fill(map, writeSheet); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/service/src/test/java/excel/fill/FillTest.java b/service/src/test/java/excel/fill/FillTest.java new file mode 100644 index 0000000..d3aab4b --- /dev/null +++ b/service/src/test/java/excel/fill/FillTest.java @@ -0,0 +1,30 @@ +package excel.fill; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +public class FillTest { + + @Test + void fillTest1() { + // // 模板注意 用{} 来表示你要用的变量 如果本来就有"{","}" 特殊字符 用"\{","\}"代替 + // String filenameTemplate = "F:\\数据库备份\\bill-template.xlsx"; + // + // // 设置数据库查询时间 + // BillExportDto billExportDto = new BillExportDto(); + // billExportDto.setUserId(1849444494908125181L); + // billExportDto.setStartDate(LocalDate.of(2024, 11, 1)); + // billExportDto.setEndDate(LocalDate.of(2024, 11, 30)); + // + // EasyExcel.write("F:\\数据库备份\\" + billExportDto.getStartDate() + "~" + billExportDto.getEndDate() + ".xlsx").withTemplate(filenameTemplate).sheet().doFill(fillData); + + // // 方案2 根据Map填充 + // fileName = TestFileUtil.getPath() + "simpleFill" + System.currentTimeMillis() + ".xlsx"; + // // 这里 会填充到第一个sheet, 然后文件流会自动关闭 + // Map map = MapUtils.newHashMap(); + // map.put("name", "张三"); + // map.put("number", 5.2); + // EasyExcel.write(fileName).withTemplate(templateFileName).sheet().doFill(map); + } +}