一、需求展示(一个订单多个商品,商品数量不限订单行合并)
二、技术选型(jxls自定义模板)
- <!-- 版本具体看官网Release,这里我们使用 2.13.0 -->
- <dependency>
- <groupId>org.jxls</groupId>
- <artifactId>jxls</artifactId>
- <version>2.13.0</version>
- </dependency>
- <dependency>
- <groupId>org.jxls</groupId>
- <artifactId>jxls-poi</artifactId>
- <version>2.13.0</version>
- </dependency>
- <!-- 要使用基于JavaExcelAPI的转换器实现,请添加以下依赖项 -->
- <dependency>
- <groupId>hu.blackbelt.bundles.jxls</groupId>
- <artifactId>org.jxls</artifactId>
- <version>2.10.0_1</version>
- </dependency>
三、导出订单的数据结构展示
- [{
- "orderName": "订单1",
- "no": "13465464464121",
- "terminalValue": "微信 小程序",
- "userInfo": "微信 小程序",
- "items": [{
- "spuName": "ipnoe 6s",
- "properties": "非卖品,勿拍!!!!",
- "count": "10",
- "originalUnitPrice": "10"
- }]
- }]
四、对应模板展示
1、局部效果展示(一定要使用xlsx格式作为模板文档,xls有点问题)
2、jx:area(lastCell = "P2")参数解释:整个表的作用域是到P列第2行,作用与必须要并且必须放在表格的的首行首列
3、jx:each(items="tpList"var="tradeOrderPageItemRespVO" lastCell="P2")参数解析:tpList是最外层的order集合,tradeOrderPageItemRespVO是tpList循环时item的别称,P2是tpList循环作用表的生效范围。
4、jx:mergeCells(rows="tradeOrderPageItemRespVO.items.size()" lastCell="A2")参数解析:rows要合并行的行数,lastcall是定位那A列第2行要进行单元行合并,有多少列要合并就拷贝多少次并将lastcall定位到相关列进行修改。尝试设置为C2没有从A2的位置自动每列合并到C2不知道为啥,就一列一列的设置的。
5、jx:each(items="tradeOrderPageItemRespVO.items" var="tradeOrderItemBaseVO" lastCell="H2")参数解析:tradeOrderPageItemRespVO.items就是订单里边商品做循环,别名叫tradeOrderItemBaseVO,tradeOrderPageItemRespVO.items的作用范围就是批注D2到H2的位置可以使用用${}去到里边的变量。
6、其他表达式使用请参考官网JXLS - (sourceforge.net)或文末备注
五、代码参考
1、引入依赖
- <!-- 版本具体看官网Release,这里我们使用 2.13.0 -->
- <dependency>
- <groupId>org.jxls</groupId>
- <artifactId>jxls</artifactId>
- <version>2.13.0</version>
- </dependency>
- <dependency>
- <groupId>org.jxls</groupId>
- <artifactId>jxls-poi</artifactId>
- <version>2.13.0</version>
- </dependency>
- <!-- 要使用基于JavaExcelAPI的转换器实现,请添加以下依赖项 -->
- <dependency>
- <groupId>hu.blackbelt.bundles.jxls</groupId>
- <artifactId>org.jxls</artifactId>
- <version>2.10.0_1</version>
- </dependency>
2、工具构建
- package cn.iocoder.yudao.module.trade.utils;
-
-
- import org.apache.commons.jexl3.JexlBuilder;
- import org.jxls.common.Context;
- import org.jxls.expression.JexlExpressionEvaluator;
- import org.jxls.transform.Transformer;
- import org.jxls.util.JxlsHelper;
-
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.util.HashMap;
- import java.util.Map;
-
- public class JxlsUtils {
- public static void exportExcel(InputStream is, OutputStream os, Map
model) throws IOException { - Context context = new Context();
- if (model != null) {
- for (String key : model.keySet()) {
- context.putVar(key, model.get(key));
- }
- }
- JxlsHelper jxlsHelper = JxlsHelper.getInstance();
- Transformer transformer = jxlsHelper.createTransformer(is, os);
- JexlExpressionEvaluator evaluator = (JexlExpressionEvaluator) transformer.getTransformationConfig()
- .getExpressionEvaluator();
- Map
funcs = new HashMap<>(); - funcs.put("utils", new JxlsUtils()); // 添加自定义功能
- evaluator.setJexlEngine(new JexlBuilder().namespaces(funcs).create());
- jxlsHelper.processTemplate(context, transformer);
- }
- }
3、Controller导出
- @GetMapping("/export-excel")
- @Operation(summary = "导出订单表格 Excel")
- @PreAuthorize("@ss.hasPermission('trade:order:export')")
- @OperateLog(type = EXPORT)
- public void exportActivityExcel(TradeOrderPageReqVO reqVO,
- HttpServletResponse response) throws IOException {
- CommonResult<PageResult<TradeOrderPageItemRespVO>> orderPage = getOrderPage(reqVO);
- List<TradeOrderPageItemRespVO> list = orderPage.getData().getList();
- List<TradeOrderExcelVO> result = new ArrayList<>();
- for (TradeOrderPageItemRespVO tradeOrderPageItemRespVO : list) {
- TradeOrderExcelVO convert = TradeOrderConvert.INSTANCE.convert(tradeOrderPageItemRespVO, 1);
- result.add(convert);
- }
- // 设置响应头
- response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
- response.setHeader("Content-Disposition", "attachment; filename=output.xlsx");
- // 使用 jXLS 进行模板变量替换并导出 Excel
- try (InputStream inputStream = getClass().getResourceAsStream("/tem/tem.xlsx");
- OutputStream outputStream = response.getOutputStream()) {
- //excel模板内,数据组装
- Map<String, Object> map = new HashMap<>();
- map.put("tpList", result);
- JxlsUtils.exportExcel(inputStream, outputStream, map);
- }
- }
六、备注
- jx:mergeCells(lastCell="合并单元格范围"
- [, cols="合并的列数"]
- [, rows="合并的行数"]
- [, minCols="要合并的最小列数"]
- [, minRows="要合并的最小行数"]
- )
-
- lastCell:合并单元格范围;
- cols:合并的列数;
- rows:合并的行数;
- minCols:要合并的最小列数;
- minRows:要合并的最小行数;
-
- jx:each(items="countMonths" var="month" lastCell="C3" direction="RIGHT")
- 这里还是通过jx:each来使用,不同的是direction 属性的值为:RIGHT(向右),默认为:DOWN(向下)
- countMonths:动态列集合,month为集合循环的实体,取值为:${month}
- contracts:行数据集合,contract、colData 都是集合循环的实体,取值为:${contract.custName}等
- colData.monthData.get(month):动态列的数据,根据列名去匹配实体字段
- ${empty()}:判断集合对应动态列数据 是否为空,做好判断,写入数据
- 动态列数据行的数据获取:${empty(colData.monthData.get(month) ) ? 0 : colData.monthData.get(month)}