From 3879b288cec2f672d1a6e3fc21eda4b462cb1dff Mon Sep 17 00:00:00 2001 From: zhouhaibin Date: Tue, 11 Jun 2024 09:29:30 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BD=BF=E7=94=A8elasticsearh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/CostTableController.java | 12 + .../mapper/CostTableMapper.java | 3 + .../service/CostTableService.java | 4 + .../service/impl/CostTableServiceImpl.java | 154 +++++++++++- .../SupplierProductsController.java | 10 +- .../entity/SupplierProducts.java | 18 ++ .../service/SupplierProductsService.java | 14 ++ .../impl/SupplierProductsServiceImpl.java | 66 +++++ .../platform/support/SerialNoServiceTest.java | 91 ++++++- .../entity/SupplierProductsDTO.java | 167 +++++++++++++ platform-common/pom.xml | 6 + .../abc/platform/common/base/BaseEntity.java | 1 + .../platform/common/base/BaseMapEntity.java | 5 + .../common/extension/EasyExcelUtils.java | 231 ++++++++++++++++++ .../extension/ExcelColumnMergeHandler.java | 108 ++++++++ .../extension/ExcelExportExtension.java | 1 - .../extension/ExcelRowMergeHandler.java | 87 +++++++ 17 files changed, 969 insertions(+), 9 deletions(-) create mode 100644 platform-boot-starter-elasticsearch/src/main/java/tech/abc/platform/elasticsearch/entity/SupplierProductsDTO.java create mode 100644 platform-common/src/main/java/tech/abc/platform/common/extension/EasyExcelUtils.java create mode 100644 platform-common/src/main/java/tech/abc/platform/common/extension/ExcelColumnMergeHandler.java create mode 100644 platform-common/src/main/java/tech/abc/platform/common/extension/ExcelRowMergeHandler.java diff --git a/platform-boot-started-costManagement/src/main/java/tech/abc/platform/costManagement/controller/CostTableController.java b/platform-boot-started-costManagement/src/main/java/tech/abc/platform/costManagement/controller/CostTableController.java index b73c8fe..2fc39b0 100644 --- a/platform-boot-started-costManagement/src/main/java/tech/abc/platform/costManagement/controller/CostTableController.java +++ b/platform-boot-started-costManagement/src/main/java/tech/abc/platform/costManagement/controller/CostTableController.java @@ -23,6 +23,9 @@ import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -69,6 +72,15 @@ public class CostTableController extends BaseController { CostDetailViewVO vo = costTableService.getCostTableDetail(id); return ResultUtil.success(vo); } + /** + * 导出单条数据表格文件 + */ + @GetMapping("/exportData/{id}") + @SystemLog(value = "-导出造价") + @PreAuthorize("hasPermission(null,'costManagement:costTable:view')") + public void exportData(@PathVariable("id") String id, HttpServletResponse response) throws IOException { + costTableService.exportData(id,response); + } //region 基本操作 /** * 初始化 diff --git a/platform-boot-started-costManagement/src/main/java/tech/abc/platform/costManagement/mapper/CostTableMapper.java b/platform-boot-started-costManagement/src/main/java/tech/abc/platform/costManagement/mapper/CostTableMapper.java index 1fb8fe2..8fe1f45 100644 --- a/platform-boot-started-costManagement/src/main/java/tech/abc/platform/costManagement/mapper/CostTableMapper.java +++ b/platform-boot-started-costManagement/src/main/java/tech/abc/platform/costManagement/mapper/CostTableMapper.java @@ -3,6 +3,8 @@ package tech.abc.platform.costManagement.mapper; import tech.abc.platform.costManagement.entity.CostTable; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import java.util.List; + /** * Mapper 接口 @@ -12,5 +14,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; */ public interface CostTableMapper extends BaseMapper { + } diff --git a/platform-boot-started-costManagement/src/main/java/tech/abc/platform/costManagement/service/CostTableService.java b/platform-boot-started-costManagement/src/main/java/tech/abc/platform/costManagement/service/CostTableService.java index 3b6dd30..0d0ae8a 100644 --- a/platform-boot-started-costManagement/src/main/java/tech/abc/platform/costManagement/service/CostTableService.java +++ b/platform-boot-started-costManagement/src/main/java/tech/abc/platform/costManagement/service/CostTableService.java @@ -4,6 +4,8 @@ import tech.abc.platform.costManagement.entity.CostTable; import tech.abc.platform.common.base.BaseService; import tech.abc.platform.costManagement.vo.CostDetailViewVO; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.List; import java.util.Map; @@ -28,5 +30,7 @@ public interface CostTableService extends BaseService { CostDetailViewVO getCostTableDetail(String id); void modifyCostTable(CostDetailViewVO vo); + + void exportData(String id,HttpServletResponse response) throws IOException; } diff --git a/platform-boot-started-costManagement/src/main/java/tech/abc/platform/costManagement/service/impl/CostTableServiceImpl.java b/platform-boot-started-costManagement/src/main/java/tech/abc/platform/costManagement/service/impl/CostTableServiceImpl.java index 7f33b5e..59ca677 100644 --- a/platform-boot-started-costManagement/src/main/java/tech/abc/platform/costManagement/service/impl/CostTableServiceImpl.java +++ b/platform-boot-started-costManagement/src/main/java/tech/abc/platform/costManagement/service/impl/CostTableServiceImpl.java @@ -1,6 +1,15 @@ package tech.abc.platform.costManagement.service.impl; +import cn.hutool.core.convert.NumberChineseFormatter; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.ExcelWriter; +import com.alibaba.excel.write.metadata.WriteSheet; +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.ss.formula.functions.T; import org.springframework.beans.factory.annotation.Autowired; +import tech.abc.platform.common.extension.EasyExcelUtils; +import tech.abc.platform.common.extension.ExcelColumnMergeHandler; +import tech.abc.platform.common.extension.ExcelRowMergeHandler; import tech.abc.platform.costManagement.entity.CostTable; import tech.abc.platform.costManagement.mapper.CostTableMapper; import tech.abc.platform.costManagement.service.CostItemDetailService; @@ -9,15 +18,17 @@ import tech.abc.platform.common.base.BaseServiceImpl; import org.springframework.stereotype.Service; import lombok.extern.slf4j.Slf4j; +import java.io.IOException; +import java.net.URLEncoder; import java.time.LocalDateTime; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.HashMap; +import java.util.*; + import com.baomidou.mybatisplus.core.toolkit.IdWorker; import tech.abc.platform.costManagement.vo.CostDetailViewVO; import tech.abc.platform.costManagement.vo.CostItemDetailVO; +import javax.servlet.http.HttpServletResponse; + /** * 服务实现类 * @@ -58,6 +69,65 @@ public class CostTableServiceImpl extends BaseServiceImpl costItemDetail = costItemDetailService.getCostItemDetail(costTable.getId()); + List heads = new ArrayList<>(); + heads.add("序号"); + heads.add("费用类型"); + heads.add("建设内容"); + heads.add("小计(元)"); + heads.add("备注"); + List childHeads = new ArrayList<>(); + childHeads.add("序号"); + childHeads.add("设备名称"); + childHeads.add("主要技术参数"); + childHeads.add("数量"); + childHeads.add("单位"); + childHeads.add("单价"); + childHeads.add("小计"); + List otherCostData = new ArrayList<>(); + List> otherCostList= new ArrayList<>(); + ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build(); + List> dataList = new ArrayList<>(); + ExcelColumnMergeHandler columnMergeHandler = new ExcelColumnMergeHandler(1, new int[]{0, 1}); + ExcelRowMergeHandler rowMergeHandler = new ExcelRowMergeHandler(); + Integer xuhao= 1; + Integer num=0; + for (int i = 0; i < costItemDetail.size(); i++) { + CostItemDetailVO costItemDetailVO = costItemDetail.get(i); + if(StringUtils.isBlank(costItemDetailVO.getCostType())){ + List objects = getChildDataList(costItemDetailVO, i); + otherCostList.add(objects); + continue; + } + List objectList = getDataList(costItemDetail, i, xuhao); + dataList.add(objectList); + + num = setChildDataSheet(costItemDetailVO,excelWriter,num,heads,childHeads,columnMergeHandler,rowMergeHandler); + + } + num=num+1; + WriteSheet sheet2 = EasyExcel.writerSheet(num,"未分类费用").head(EasyExcelUtils.head(childHeads)).registerWriteHandler(columnMergeHandler).registerWriteHandler(rowMergeHandler).build(); + excelWriter.write(otherCostList, sheet2); + WriteSheet sheet1 = EasyExcel.writerSheet(0, "项目投资概算总表").head(EasyExcelUtils.head(heads)).registerWriteHandler(columnMergeHandler).registerWriteHandler(rowMergeHandler).build(); + excelWriter.write(dataList, sheet1); + log.info(num+"个sheet已写入"); + excelWriter.finish(); + //3.返回结果 + } + @Override public void afterRemove(CostTable entity) { costItemDetailService.removeByCostTableId(entity.getId()); @@ -92,6 +162,82 @@ public class CostTableServiceImpl extends BaseServiceImpl getChildDataList(CostItemDetailVO children, Integer j) { + List childObject = new ArrayList<>(); + childObject.add(NumberChineseFormatter.format(j + 1, false, false)); + childObject.add(children.getCostName()); + childObject.add(children.getCostDescribe()); + childObject.add(children.getQuantity()); + childObject.add(children.getUnit()); + childObject.add(children.getUnitPrice()); + childObject.add(children.getTotalPrice()); + return childObject; + } + private List getDataList(List costItemDetail, Integer i, Integer xuhao) { + CostItemDetailVO costItemDetailVO = costItemDetail.get(i); + List objectList = new ArrayList<>(); + if(i>=1){ + //比较后一个和前一个是否一样 + String newCostType = costItemDetailVO.getCostType(); + String lastCostType = costItemDetail.get(i-1).getCostType(); + if(!newCostType.equals(lastCostType)) { + xuhao=xuhao+1; + } + } + objectList.add(NumberChineseFormatter.format(xuhao,false,false)); + objectList.add(costItemDetailVO.getCostType()); + objectList.add(costItemDetailVO.getConstructContent()); + objectList.add(costItemDetailVO.getTotalPrice()); + objectList.add(costItemDetailVO.getRemarks()); + return objectList; + } + /** + * 递归获取子节点数据 + * @param costItemDetailVO + * @param num + * @return + */ + private Integer setChildDataSheet(CostItemDetailVO costItemDetailVO, + ExcelWriter excelWriter, + Integer num, + List heads, + List childHeads, + ExcelColumnMergeHandler columnMergeHandler, + ExcelRowMergeHandler rowMergeHandler) { + List childrenList = costItemDetailVO.getChildren(); + List> childDataList = new ArrayList<>(); + Boolean isDetail = true; + for (Integer j = 0; j < childrenList.size(); j++) { + CostItemDetailVO child = childrenList.get(j); + if(child.getIsDetail().equals("1")){ + isDetail=true; + List childObject = getChildDataList(child, j); + childDataList.add(childObject); + List childChildren = child.getChildren(); + if(childChildren.size()>0){ + num = setChildDataSheet(child,excelWriter,num,heads,childHeads,columnMergeHandler,rowMergeHandler); + } + }else{ + isDetail=false; + Integer xuhao=1; + List childObject = getDataList(childrenList, j, xuhao); + childDataList.add(childObject); + List childChildren = child.getChildren(); + if(childChildren.size()>0){ + num = setChildDataSheet(child,excelWriter,num,heads,childHeads,columnMergeHandler,rowMergeHandler); + } + } + } + num=num+1; + if(!isDetail){ + WriteSheet sheet2 = EasyExcel.writerSheet(num,costItemDetailVO.getConstructContent()).head(EasyExcelUtils.head(heads)).registerWriteHandler(columnMergeHandler).registerWriteHandler(rowMergeHandler).build(); + excelWriter.write(childDataList, sheet2); + return num; + } + WriteSheet sheet2 = EasyExcel.writerSheet(num,costItemDetailVO.getConstructContent()).head(EasyExcelUtils.head(childHeads)).registerWriteHandler(columnMergeHandler).registerWriteHandler(rowMergeHandler).build(); + excelWriter.write(childDataList, sheet2); + return num; + } } diff --git a/platform-boot-started-productManagement/src/main/java/tech/abc/platform/productManagement/controller/SupplierProductsController.java b/platform-boot-started-productManagement/src/main/java/tech/abc/platform/productManagement/controller/SupplierProductsController.java index 6008e5e..65cd993 100644 --- a/platform-boot-started-productManagement/src/main/java/tech/abc/platform/productManagement/controller/SupplierProductsController.java +++ b/platform-boot-started-productManagement/src/main/java/tech/abc/platform/productManagement/controller/SupplierProductsController.java @@ -98,7 +98,9 @@ public class SupplierProductsController extends BaseController { @SystemLog(value = "-分页") @PreAuthorize("hasPermission(null,'productManagement:supplierProducts:query')") public ResponseEntity page(SupplierProductsVO queryVO, PageInfo pageInfo, SortInfo sortInfo) { - //构造分页对象 + IPage pageVO=null; + if (StringUtils.isBlank(queryVO.getProductName())) { + //构造分页对象 IPage page = new Page(pageInfo.getPageNum(), pageInfo.getPageSize()); @@ -108,9 +110,13 @@ public class SupplierProductsController extends BaseController { //查询数据 supplierProductsService.page(page, queryWrapper); //转换vo - IPage pageVO = mapperFacade.map(page, IPage.class); + pageVO = mapperFacade.map(page, IPage.class); List supplierProductsVOList=convert2VO(page.getRecords()); pageVO.setRecords(supplierProductsVOList); + }else{ + pageVO = supplierProductsService.querypagebyes(queryVO, pageInfo, sortInfo); + } + return ResultUtil.success(pageVO); } diff --git a/platform-boot-started-productManagement/src/main/java/tech/abc/platform/productManagement/entity/SupplierProducts.java b/platform-boot-started-productManagement/src/main/java/tech/abc/platform/productManagement/entity/SupplierProducts.java index 1e1409a..8b644ea 100644 --- a/platform-boot-started-productManagement/src/main/java/tech/abc/platform/productManagement/entity/SupplierProducts.java +++ b/platform-boot-started-productManagement/src/main/java/tech/abc/platform/productManagement/entity/SupplierProducts.java @@ -2,7 +2,11 @@ package tech.abc.platform.productManagement.entity; import com.baomidou.mybatisplus.annotation.*; +import java.lang.annotation.Documented; import java.math.BigDecimal; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; import tech.abc.platform.common.base.BaseEntity; import lombok.Data; import lombok.EqualsAndHashCode; @@ -25,81 +29,95 @@ public class SupplierProducts extends BaseEntity { * 供应商id */ @TableField("supplier_information_id") + @JsonProperty("supplier_information_id") private String supplierInformationId; /** * 厂商产品型号id */ @TableField("model_id") + @JsonProperty("model_id") private String modelId; /** * 个人产品规格 */ @TableField("product_specifications") + @JsonProperty("product_specifications") private String productSpecifications; /** * 产品名称 */ @TableField("product_name") + @JsonProperty("product_name") private String productName; /** * 产品标识(型号) */ @TableField("product_identity") + @JsonProperty("product_identity") private String productIdentity; /** * 产品价格 */ @TableField(value="product_price",updateStrategy= FieldStrategy.IGNORED) + @JsonProperty("product_price") private BigDecimal productPrice; /** * 信息来源 */ @TableField("source_information") + @JsonProperty("source_information") private String sourceInformation; /** * 备注 */ @TableField("remarks") + @JsonProperty("remarks") private String remarks; /** * 产品图片 */ @TableField("image") + @JsonProperty("image") private String image; /** * 产品品牌 */ @TableField("brand") + @JsonProperty("brand") private String brand; /** * 产品单位*/ @TableField("unit") + @JsonProperty("unit") private String unit; /** * 除税价格 */ @TableField("ex_tax_price") + @JsonProperty("ex_tax_price") private BigDecimal exTaxPrice; /** * 税率 */ @TableField("taxrate") + @JsonProperty("taxrate") private BigDecimal taxrate; /** * 分类id */ @TableField("category_id") + @JsonProperty("category_id") private String categoryId; /********非库表存储属性*****/ } diff --git a/platform-boot-started-productManagement/src/main/java/tech/abc/platform/productManagement/service/SupplierProductsService.java b/platform-boot-started-productManagement/src/main/java/tech/abc/platform/productManagement/service/SupplierProductsService.java index ad32395..72cc6f5 100644 --- a/platform-boot-started-productManagement/src/main/java/tech/abc/platform/productManagement/service/SupplierProductsService.java +++ b/platform-boot-started-productManagement/src/main/java/tech/abc/platform/productManagement/service/SupplierProductsService.java @@ -1,7 +1,12 @@ package tech.abc.platform.productManagement.service; +import com.baomidou.mybatisplus.core.metadata.IPage; +import tech.abc.platform.common.vo.PageInfo; +import tech.abc.platform.common.vo.SortInfo; import tech.abc.platform.productManagement.entity.SupplierProducts; import tech.abc.platform.common.base.BaseService; +import tech.abc.platform.productManagement.vo.SupplierProductsVO; + import java.util.List; import java.util.Map; @@ -21,5 +26,14 @@ public interface SupplierProductsService extends BaseService { */ Map getNameMap(List idList); + /** + * es分页查询 + * @param queryVO + * @param pageInfo + * @param sortInfo + * @return + */ + + IPage querypagebyes(SupplierProductsVO queryVO, PageInfo pageInfo, SortInfo sortInfo); } diff --git a/platform-boot-started-productManagement/src/main/java/tech/abc/platform/productManagement/service/impl/SupplierProductsServiceImpl.java b/platform-boot-started-productManagement/src/main/java/tech/abc/platform/productManagement/service/impl/SupplierProductsServiceImpl.java index 5cf7800..8e16c46 100644 --- a/platform-boot-started-productManagement/src/main/java/tech/abc/platform/productManagement/service/impl/SupplierProductsServiceImpl.java +++ b/platform-boot-started-productManagement/src/main/java/tech/abc/platform/productManagement/service/impl/SupplierProductsServiceImpl.java @@ -1,7 +1,17 @@ package tech.abc.platform.productManagement.service.impl; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.query_dsl.Operator; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.core.search.Hit; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; +import tech.abc.platform.common.vo.PageInfo; +import tech.abc.platform.common.vo.SortInfo; +import tech.abc.platform.elasticsearch.entity.SupplierProductsDTO; import tech.abc.platform.productManagement.entity.SupplierProductModel; import tech.abc.platform.productManagement.entity.SupplierProductModelDetails; import tech.abc.platform.productManagement.entity.SupplierProducts; @@ -12,12 +22,17 @@ import tech.abc.platform.productManagement.service.SupplierProductsService; import tech.abc.platform.common.base.BaseServiceImpl; import org.springframework.stereotype.Service; import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; import java.util.HashMap; import com.baomidou.mybatisplus.core.toolkit.IdWorker; +import tech.abc.platform.productManagement.vo.SupplierProductsVO; + /** * 服务实现类 * @@ -31,6 +46,8 @@ public class SupplierProductsServiceImpl extends BaseServiceImpl querypagebyes(SupplierProductsVO queryVO, PageInfo pageInfo, SortInfo sortInfo) { + // 执行查询 + Page supplierProductsVOPage = new Page<>(pageInfo.getPageNum(), pageInfo.getPageSize()); + String productName = queryVO.getProductName(); + try { + SearchResponse searchResponse = client.search(srBuilder -> srBuilder + .index("pmg_supplier_products") + // MultiMatch 查找:对输入内容先分词再查询。 + .query(queryBuilder -> queryBuilder + .multiMatch(multiMatchQueryBuilder -> multiMatchQueryBuilder + .fields("product_name", "product_specifications") + .query(productName) + .operator(Operator.Or))) + //高亮显示 + .highlight(highlightBuilder -> highlightBuilder + .preTags("") + .postTags("") + .requireFieldMatch(false) //多字段时,需要设置为false + .fields("product_name", highlightFieldBuilder -> highlightFieldBuilder) + .fields("product_specifications", highlightFieldBuilder -> highlightFieldBuilder) + ) + .from(pageInfo.getPageNum()-1) + .size(pageInfo.getPageSize()) + , SupplierProductsDTO.class); + List> hitList = searchResponse.hits().hits(); + supplierProductsVOPage.setTotal(searchResponse.hits().total().value()); + List supplierProductsVOList =new ArrayList<>(); + for (Hit hit : hitList) { + SupplierProductsVO supplierProductsVO = new SupplierProductsVO(); + BeanUtils.copyProperties(hit.source(),supplierProductsVO); +// SupplierProductsVO map = mapperFacade.map(hit.source(), SupplierProductsVO.class); + if(hit.highlight().get("product_name")!=null){ + supplierProductsVO.setProductName(hit.highlight().get("product_name").get(0)); + + } + if(hit.highlight().get("product_specifications")!=null){ + supplierProductsVO.setProductSpecifications(hit.highlight().get("product_specifications").get(0)); + + } + supplierProductsVOList.add(supplierProductsVO); + } + supplierProductsVOPage.setRecords(supplierProductsVOList); + } catch (IOException e) { + throw new RuntimeException(e); + } + return supplierProductsVOPage; + } + @Override protected void copyPropertyHandle(SupplierProducts entity, String... value) { } diff --git a/platform-boot-starter-demo/src/test/java/tech/abc/platform/support/SerialNoServiceTest.java b/platform-boot-starter-demo/src/test/java/tech/abc/platform/support/SerialNoServiceTest.java index 0eccfaa..deae57a 100644 --- a/platform-boot-starter-demo/src/test/java/tech/abc/platform/support/SerialNoServiceTest.java +++ b/platform-boot-starter-demo/src/test/java/tech/abc/platform/support/SerialNoServiceTest.java @@ -1,12 +1,22 @@ package tech.abc.platform.support; +import co.elastic.clients.elasticsearch.ElasticsearchClient; +import co.elastic.clients.elasticsearch._types.SortOrder; +import co.elastic.clients.elasticsearch._types.query_dsl.Operator; +import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.core.search.Hit; +import co.elastic.clients.transport.endpoints.BooleanResponse; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import tech.abc.platform.boot.PlatformBootApplication; +import tech.abc.platform.elasticsearch.entity.SupplierProductsDTO; +import tech.abc.platform.productManagement.entity.SupplierProducts; import tech.abc.platform.support.service.SerialNoService; +import java.io.IOException; + /** * @author wqliu @@ -17,6 +27,8 @@ import tech.abc.platform.support.service.SerialNoService; class SerialNoServiceTest { @Autowired private SerialNoService serialNoService; + @Autowired + private ElasticsearchClient client; @Test void generateSingleNo() { @@ -26,12 +38,87 @@ class SerialNoServiceTest { } + /** + * 全量数据分页和排序 + * @throws IOException + * .sort(sortOptionsBuilder -> sortOptionsBuilder + * .field(fieldSortBuilder -> fieldSortBuilder + * .field("age").order(SortOrder.Desc) + * .field("id").order(SortOrder.Desc))), Map.class); + * + * + * // 执行查询 数据过滤 + * SearchResponse searchResponse = elasticsearchClient.search(srBuilder -> srBuilder + * .index("db_idx4") + * // 执行要返回的字段 + * .source(sourceConfigBuilder -> sourceConfigBuilder + * .filter(sourceFilterBuilder -> sourceFilterBuilder + * .includes("id", "name", "age") + * .excludes("age"))), Map.class); + * + * //解析查询结果 + * System.out.println(searchResponse); + + */ + @Test + void testSendTextMail() throws IOException { + SearchResponse pmgSupplierProducts = client.search(s -> s + .index("pmg_supplier_products") + .from(0) + .size(10).sort(sort->sort.field(f->f.field("id").order(SortOrder.Desc))), + SupplierProductsDTO.class); + for (Hit hit: pmgSupplierProducts.hits().hits()) { + SupplierProductsDTO pd = hit.source(); + System.out.println(pd); + } + + } + + /** + * 单字段分词查询 match在匹配时会对所查找的关键词进行分词,然后按分词匹配查找 + * @throws IOException + */ @Test - void testSendTextMail() { + void query() throws IOException { + SearchResponse pmgSupplierProducts = client.search(s -> s + .index("pmg_supplier_products") + .query(queryBuilder -> queryBuilder.match(matchBuilder -> matchBuilder.field("product_name").query("计算机显卡"))) + .from(0) + .size(10).sort(sort->sort.field(f->f.field("id").order(SortOrder.Desc))), + SupplierProductsDTO.class); + for (Hit hit: pmgSupplierProducts.hits().hits()) { + SupplierProductsDTO pd = hit.source(); + System.out.println(pd); + } } + /** + * 多字段查询multi_match multi_match 关键字:可以根据字段类型,决定是否使用分词查询,得分最高的在前面。 + * @throws IOException + */ @Test - void sendHtmlMail() { + void sendHtmlMail() throws IOException { + // 执行查询 + SearchResponse searchResponse = client.search(srBuilder -> srBuilder + .index("pmg_supplier_products") + // MultiMatch 查找:对输入内容先分词再查询。 + .query(queryBuilder -> queryBuilder + .multiMatch(multiMatchQueryBuilder -> multiMatchQueryBuilder + .fields("product_name", "product_specifications") + .query("电脑显卡主机") + .operator(Operator.Or))) + //高亮显示 + .highlight(highlightBuilder -> highlightBuilder + .preTags("") + .postTags("") + .requireFieldMatch(false) //多字段时,需要设置为false + .fields("product_name", highlightFieldBuilder -> highlightFieldBuilder) + .fields("product_specifications", highlightFieldBuilder -> highlightFieldBuilder) + ) + , SupplierProductsDTO.class); + + //解析查询结果 + System.out.println(searchResponse); } @Test diff --git a/platform-boot-starter-elasticsearch/src/main/java/tech/abc/platform/elasticsearch/entity/SupplierProductsDTO.java b/platform-boot-starter-elasticsearch/src/main/java/tech/abc/platform/elasticsearch/entity/SupplierProductsDTO.java new file mode 100644 index 0000000..2253dc5 --- /dev/null +++ b/platform-boot-starter-elasticsearch/src/main/java/tech/abc/platform/elasticsearch/entity/SupplierProductsDTO.java @@ -0,0 +1,167 @@ +package tech.abc.platform.elasticsearch.entity; + +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.experimental.Accessors; +import tech.abc.platform.common.base.BaseEntity; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 实体类 + * + * @author ZHB + * @date 2024-05-08 + * + */ +@Data +@TableName("pmg_supplier_products") +@JsonIgnoreProperties(ignoreUnknown=true) + +public class SupplierProductsDTO { + + /** + * 供应商id + */ + @TableField("supplier_information_id") + @JsonProperty("supplier_information_id") + private String supplierInformationId; + + /** + * 厂商产品型号id + */ + @TableField("model_id") + @JsonProperty("model_id") + private String modelId; + + /** + * 个人产品规格 + */ + @TableField("product_specifications") + @JsonProperty("product_specifications") + private String productSpecifications; + + /** + * 产品名称 + */ + @TableField("product_name") + @JsonProperty("product_name") + private String productName; + + /** + * 产品标识(型号) + */ + @TableField("product_identity") + @JsonProperty("product_identity") + private String productIdentity; + + /** + * 产品价格 + */ + @TableField(value="product_price",updateStrategy= FieldStrategy.IGNORED) + @JsonProperty("product_price") + private BigDecimal productPrice; + + /** + * 信息来源 + */ + @TableField("source_information") + @JsonProperty("source_information") + private String sourceInformation; + + /** + * 备注 + */ + @TableField("remarks") + @JsonProperty("remarks") + private String remarks; + /** + * 产品图片 + */ + @TableField("image") + @JsonProperty("image") + private String image; + + /** + * 产品品牌 + */ + @TableField("brand") + @JsonProperty("brand") + private String brand; + + /** + * 产品单位*/ + @TableField("unit") + @JsonProperty("unit") + private String unit; + + /** + * 除税价格 + */ + @TableField("ex_tax_price") + @JsonProperty("ex_tax_price") + private BigDecimal exTaxPrice; + + /** + * 税率 + */ + @TableField("taxrate") + @JsonProperty("taxrate") + private BigDecimal taxrate; + /** + * 分类id + */ + @TableField("category_id") + @JsonProperty("category_id") + private String categoryId; + + /** + * 逻辑删除 + */ + @TableField(value = "delete_flag", fill = FieldFill.INSERT) + @TableLogic + @JsonProperty("delete_flag") + protected String deleteFlag; + /** + * 创建人标识 + */ + + @TableField(value = "create_id", fill = FieldFill.INSERT) + @JsonProperty("create_id") + private String createId; + + /** + * 创建时间 + */ + @TableField(value = "create_time", fill = FieldFill.INSERT) + @JsonProperty("create_time") + private String createTime; + + /** + * 更新人标识 + */ + + @TableField(value = "update_id", fill = FieldFill.INSERT_UPDATE) + @JsonProperty("update_id") + private String updateId; + + /** + * 更新时间 + */ + @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) + @JsonProperty("update_time") + private String updateTime; + + /** + * 版本 + */ + + @TableField(value = "version", fill = FieldFill.INSERT) + @JsonProperty("version") + private Integer version; + /********非库表存储属性*****/ +} diff --git a/platform-common/pom.xml b/platform-common/pom.xml index d5c0b52..c2687eb 100644 --- a/platform-common/pom.xml +++ b/platform-common/pom.xml @@ -147,6 +147,12 @@ easyexcel 3.3.1 + + cn.hutool + hutool-all + 5.8.16 + + diff --git a/platform-common/src/main/java/tech/abc/platform/common/base/BaseEntity.java b/platform-common/src/main/java/tech/abc/platform/common/base/BaseEntity.java index b26411b..587bbf0 100644 --- a/platform-common/src/main/java/tech/abc/platform/common/base/BaseEntity.java +++ b/platform-common/src/main/java/tech/abc/platform/common/base/BaseEntity.java @@ -1,6 +1,7 @@ package tech.abc.platform.common.base; import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import java.time.LocalDateTime; diff --git a/platform-common/src/main/java/tech/abc/platform/common/base/BaseMapEntity.java b/platform-common/src/main/java/tech/abc/platform/common/base/BaseMapEntity.java index 91ace67..7cf1726 100644 --- a/platform-common/src/main/java/tech/abc/platform/common/base/BaseMapEntity.java +++ b/platform-common/src/main/java/tech/abc/platform/common/base/BaseMapEntity.java @@ -1,6 +1,11 @@ package tech.abc.platform.common.base; import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import lombok.Data; import java.time.LocalDateTime; diff --git a/platform-common/src/main/java/tech/abc/platform/common/extension/EasyExcelUtils.java b/platform-common/src/main/java/tech/abc/platform/common/extension/EasyExcelUtils.java new file mode 100644 index 0000000..535587e --- /dev/null +++ b/platform-common/src/main/java/tech/abc/platform/common/extension/EasyExcelUtils.java @@ -0,0 +1,231 @@ +package tech.abc.platform.common.extension; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.excel.EasyExcel; +import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder; + +import org.springframework.util.CollectionUtils; +import javax.servlet.http.HttpServletResponse; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.io.IOException; +import java.net.URLEncoder; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * EasyExcel工具类 + */ +public class EasyExcelUtils { + + + /** + * 注入的具有排序功能的handle + */ +// private static final SortRowWriteHandler SORT_ROW_WRITE_HANDLER = new SortRowWriteHandler(); + + /** + * 导出excel-按指定顺序 + * + * @param 类(必须是小写,并遵守阿里开发规范) + * @param list 列表数据 + * @param fileName 文件名称 + * @param useDefaultStyle 是否使用默认样式 + * @param response 响应 + */ + public static Map exportExcelInclude(List list, String fileName,Boolean useDefaultStyle, HttpServletResponse response) throws IOException { + Map resultMap = new HashMap<>(); + if (list.size() == 0) { + resultMap.put("msg", "数据长度为空"); + resultMap.put("result", -1); + return resultMap; + } + + Class clazz = list.get(0).getClass(); + + /*定义编码,格式*/ + response.setContentType("application/vnd.ms-excel"); + response.setCharacterEncoding("utf-8"); + String exportFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20"); + response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + exportFileName + ".xlsx"); + response.setHeader("filename", exportFileName + ".xlsx"); + response.setHeader("Access-Control-Expose-Headers", "filename"); + /** + * .head(head(headNameList)) + * 改行代码不可以用ExcelWriterSheetBuilder类型的变量单独写,否则会包错:表头长度与字段列表长度不符 + */ + /*导出表格*/ + ExcelWriterSheetBuilder excelWriterSheetBuilder = EasyExcel.write(response.getOutputStream(), clazz) + .useDefaultStyle(useDefaultStyle) + .sheet(fileName); + excelWriterSheetBuilder.doWrite(list); + + resultMap.put("msg", "excel export success"); + resultMap.put("result", 0); + return resultMap; + } + + + /** + * 导出excel-默认顺序 + * + * @param 类(必须是小写,并遵守阿里开发规范) + * @param list 列表数据 + * @param fileName 文件名称 + * @param useDefaultStyle 是否使用默认样式 + * @param response 响应 + * @param headNameList + * @param columnList 设置列字段(必须是小写) + */ + public static Map exportExcelInclude(List list, String fileName,Boolean useDefaultStyle, HttpServletResponse response, List columnList, List headNameList) throws IOException { + Map resultMap = new HashMap<>(); + if (list.size() == 0) { + resultMap.put("msg", "数据长度为空"); + resultMap.put("result", -1); + return resultMap; + } + + if (CollectionUtils.isEmpty(headNameList)) { + /*设置表头*/ + resultMap.put("msg", "表头长度为空"); + resultMap.put("result", -2); + return resultMap; + } + + if (CollectionUtils.isEmpty(columnList)) { + /*设置列字段*/ + resultMap.put("msg", "列字段长度为空"); + resultMap.put("result", -3); + return resultMap; + } + + Class clazz = list.get(0).getClass(); + + /*定义编码,格式*/ + response.setContentType("application/vnd.ms-excel"); + response.setCharacterEncoding("utf-8"); + String exportFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20"); + response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + exportFileName + ".xlsx"); + response.setHeader("filename", exportFileName + ".xlsx"); + response.setHeader("Access-Control-Expose-Headers", "filename"); + /** + * .head(head(headNameList)) + * 改行代码不可以用ExcelWriterSheetBuilder类型的变量单独写,否则会包错:表头长度与字段列表长度不符 + */ + /*导出表格*/ + ExcelWriterSheetBuilder excelWriterSheetBuilder = EasyExcel.write(response.getOutputStream(), clazz) + .head(head(headNameList)) + /*设置列字段(会按顺序)*/ + .includeColumnFiledNames(columnList) + /*注入的具有排序功能的handle*/ +// .registerWriteHandler(SORT_ROW_WRITE_HANDLER) + .useDefaultStyle(useDefaultStyle) + .sheet(fileName); + excelWriterSheetBuilder.doWrite(list); + + resultMap.put("msg", "excel export success"); + resultMap.put("result", 0); + return resultMap; + } + + + /** + * 支持动态头,行列合并导出 + * + * @param response web响应 + * @param headList 动态头 + * @param dataList 数据列表 + * @param columnMergeHandler 注入列合并 + * @param rowMergeHandler 注入行合并 + * @throws IOException + */ + public static Map writeDynamicExcel(HttpServletResponse response, @NotEmpty List> headList, @NotEmpty List> dataList, @NotNull ExcelColumnMergeHandler columnMergeHandler,@NotNull ExcelRowMergeHandler rowMergeHandler) throws IOException { + Map resultMap = new HashMap<>(); + if (dataList.size() == 0) { + resultMap.put("msg", "数据长度为空"); + resultMap.put("result", -1); + return resultMap; + } + + if (CollectionUtils.isEmpty(headList)) { + /*设置表头*/ + resultMap.put("msg", "表头长度为空"); + resultMap.put("result", -2); + return resultMap; + } + + if (columnMergeHandler == null || rowMergeHandler == null) { + /*设置列字段*/ + resultMap.put("msg", "行列处理器为空"); + resultMap.put("result", -3); + return resultMap; + } + + EasyExcel.write(response.getOutputStream()) + // 设置动态头 + .head(headList) + .sheet("模板") + /*注入列合并*/ + .registerWriteHandler(columnMergeHandler) + /*注入行合并*/ + .registerWriteHandler(rowMergeHandler) + /*传需要写入的数据,类型List>*/ + .doWrite(dataList); + + resultMap.put("msg", "excel export success"); + resultMap.put("result", 0); + return resultMap; + } + + + /** + * 支持动态头导出 + * + * @param response web响应 + * @param headList 动态头 + * @param dataList 数据列表 + * @throws IOException + */ + public static void writeDynamicExcel(HttpServletResponse response,List> headList, List> dataList) throws IOException { + EasyExcel.write(response.getOutputStream()) + // 设置动态头 + .head(headList) + .sheet("模板") + /*传需要写入的数据,类型List>*/ + .doWrite(dataList); + } + + + /** + * 设置Excel头 + * + * @param headList Excel头信息 + * @return + */ + public static List> head(List headList) { + List> list = new ArrayList<>(); + for (String value : headList) { + List head = new ArrayList<>(); + head.add(value); + list.add(head); + } + return list; + } + + /** + * Excel头对应的字段转换小写 + * + * @param ColumnListTemp Excel字段 + * @return + */ + public static List castLowerCase(List ColumnListTemp) { + List ColumnList = new ArrayList<>(); + for (String name : ColumnListTemp) { + ColumnList.add(StrUtil.lowerFirst(name)); + } + return ColumnList; + } + +} diff --git a/platform-common/src/main/java/tech/abc/platform/common/extension/ExcelColumnMergeHandler.java b/platform-common/src/main/java/tech/abc/platform/common/extension/ExcelColumnMergeHandler.java new file mode 100644 index 0000000..9f507f1 --- /dev/null +++ b/platform-common/src/main/java/tech/abc/platform/common/extension/ExcelColumnMergeHandler.java @@ -0,0 +1,108 @@ +package tech.abc.platform.common.extension; + +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteTableHolder; +import lombok.Data; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.util.CellRangeAddress; + +import java.util.List; + +/*** + * 列合并处理器 + * + */ +@Data +public class ExcelColumnMergeHandler implements CellWriteHandler { + /** + * 合并字段的下标,如new int[]{0,1,2,3,4,10},0-4合并,10合并 + */ + private int[] mergeColumnIndex; + /** + * 从第几行开始合并,如果表头占两行,这个数字就是2 + */ + private int mergeRowIndex; + + public ExcelColumnMergeHandler() { + } + + public ExcelColumnMergeHandler(int mergeRowIndex, int[] mergeColumnIndex) { + this.mergeRowIndex = mergeRowIndex; + this.mergeColumnIndex = mergeColumnIndex; + } + + @Override + public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, + Head head, Integer integer, Integer integer1, Boolean aBoolean) { + + } + + @Override + public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, + Head head, Integer integer, Boolean aBoolean) { + + } + + @Override + public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, + WriteCellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) { + + } + + @Override + public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, + List> list, Cell cell, Head head, Integer integer, Boolean aBoolean) { + //当前行 + int curRowIndex = cell.getRowIndex(); + //当前列 + int curColIndex = cell.getColumnIndex(); + + if (curRowIndex > mergeRowIndex) { + for (int i = 0; i < mergeColumnIndex.length; i++) { + if (curColIndex == mergeColumnIndex[i]) { + mergeWithPrevRow(writeSheetHolder, cell, curRowIndex, curColIndex); + break; + } + } + } + } + + private void mergeWithPrevRow(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex) { + //获取当前行的当前列的数据和上一行的当前列列数据,通过上一行数据是否相同进行合并 + Object curData = cell.getCellTypeEnum() == CellType.STRING ? cell.getStringCellValue() : + cell.getNumericCellValue(); + Cell preCell = cell.getSheet().getRow(curRowIndex - 1).getCell(curColIndex); + Object preData = preCell.getCellTypeEnum() == CellType.STRING ? preCell.getStringCellValue() : + preCell.getNumericCellValue(); + // 比较当前行的第一列的单元格与上一行是否相同,相同合并当前单元格与上一行 + // + if (curData.equals(preData)) { + Sheet sheet = writeSheetHolder.getSheet(); + List mergeRegions = sheet.getMergedRegions(); + boolean isMerged = false; + for (int i = 0; i < mergeRegions.size() && !isMerged; i++) { + CellRangeAddress cellRangeAddr = mergeRegions.get(i); + // 若上一个单元格已经被合并,则先移出原有的合并单元,再重新添加合并单元 + if (cellRangeAddr.isInRange(curRowIndex - 1, curColIndex)) { + sheet.removeMergedRegion(i); + cellRangeAddr.setLastRow(curRowIndex); + sheet.addMergedRegion(cellRangeAddr); + isMerged = true; + } + } + // 若上一个单元格未被合并,则新增合并单元 + if (!isMerged) { + CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex - 1, curRowIndex, curColIndex, + curColIndex); + sheet.addMergedRegion(cellRangeAddress); + } + } + } +} + diff --git a/platform-common/src/main/java/tech/abc/platform/common/extension/ExcelExportExtension.java b/platform-common/src/main/java/tech/abc/platform/common/extension/ExcelExportExtension.java index 40b1266..e7c8705 100644 --- a/platform-common/src/main/java/tech/abc/platform/common/extension/ExcelExportExtension.java +++ b/platform-common/src/main/java/tech/abc/platform/common/extension/ExcelExportExtension.java @@ -65,7 +65,6 @@ public class ExcelExportExtension extends BaseController { String fileName = URLEncoder.encode("导出数据.xlsx", "UTF-8"); response.setHeader("Content-disposition", "attachment;filename=" + fileName); - // excel导出处理 ExcelWriter excelWriter = EasyExcel.write(outputStream, this.getClazz()) .withTemplate(inputStream).build(); diff --git a/platform-common/src/main/java/tech/abc/platform/common/extension/ExcelRowMergeHandler.java b/platform-common/src/main/java/tech/abc/platform/common/extension/ExcelRowMergeHandler.java new file mode 100644 index 0000000..1f0acc9 --- /dev/null +++ b/platform-common/src/main/java/tech/abc/platform/common/extension/ExcelRowMergeHandler.java @@ -0,0 +1,87 @@ +package tech.abc.platform.common.extension; + +import com.alibaba.excel.metadata.Head; +import com.alibaba.excel.metadata.data.WriteCellData; +import com.alibaba.excel.write.handler.CellWriteHandler; +import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; +import com.alibaba.excel.write.metadata.holder.WriteTableHolder; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.util.CellRangeAddress; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 行合并处理器 + * + */ +public class ExcelRowMergeHandler implements CellWriteHandler { + private static final String KEY ="%s-%s"; + //所有的合并信息都存在了这个map里面 + Map mergeInfo = new HashMap<>(); + + public ExcelRowMergeHandler() { + } + public ExcelRowMergeHandler(Map mergeInfo) { + this.mergeInfo = mergeInfo; + } + + @Override + public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) { + + } + + @Override + public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) { + + } + + @Override + public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, WriteCellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) { + + } + + @Override + public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List> list, Cell cell, Head head, Integer integer, Boolean aBoolean) { + //当前行 + int curRowIndex = cell.getRowIndex(); + //当前列 + int curColIndex = cell.getColumnIndex(); + + Integer num = mergeInfo.get(String.format(KEY, curRowIndex, curColIndex)); + if(null != num){ + // 合并最后一行 ,列 + mergeWithPrevCol(writeSheetHolder, cell, curRowIndex, curColIndex,num); + } + } + + public void mergeWithPrevCol(WriteSheetHolder writeSheetHolder, Cell cell, int curRowIndex, int curColIndex, int num) { + Sheet sheet = writeSheetHolder.getSheet(); + CellRangeAddress cellRangeAddress = new CellRangeAddress(curRowIndex, curRowIndex, curColIndex, curColIndex + num); + sheet.addMergedRegion(cellRangeAddress); + } + + + /** + * 添加合并行 + * 比如参数:(3,0,2) + * 从第三行的地0列开始向右合并2格 + * 这样,第三行的地0列到第2列就会合并 + * + * 注意: + * 合并不能冲突,如果合并到已经被合并的地方会报一个POI错误 + * (java.lang.IllegalStateException: Cannot add merged region B3:B6 to sheet because it overlaps with an existing merged region (A6:C6).) + * + * @param curRowIndex 当前行: 需要合并的哪一行(一般用数据List的“index”+“表头的行数”,表头站的行数是1就+1,是2就+2) + * @param curColIndex 合并开始列:从第几行开始合并 + * @param num 合并列的数量:从第curColIndex行开始,向右合并多少格 + */ + public void add (int curRowIndex, int curColIndex , int num){ + mergeInfo.put(String.format(KEY, curRowIndex, curColIndex),num); + } + +} +