依赖
<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.2.6</version> </dependency>
package cn.visight;import com.alibaba.excel.EasyExcel;import com.alibaba.excel.write.builder.ExcelWriterBuilder;import java.util.*;import java.util.stream.Collectors;public class ExcelTest { public static void main(String args[]) { // 文件输出位置 String fileName = "D:\\visi\\workspace\\统计.xlsx"; Set<String> allDateList = new HashSet<>(); Set<String> allOutletsNameList = new HashSet(); List<XData> dataList = getDataList(); dataList.forEach(r -> { // 1.获取所有的日期List allDateList.add(r.getDate()); // 2.获取所有的名字Map allOutletsNameList.add(r.getOutletsName()); }); // 3.获取所有的日期对应的数据Map Map<String, List<XData>> date2XDataMap = dataList.stream().collect(Collectors.groupingBy(XData::getDate)); ExcelWriterBuilder builder = EasyExcel.write(fileName); List<List<String>> headData = getExcelHeadData(allOutletsNameList); List<List<Object>> excelDataList = getExcelDataList(allDateList, allOutletsNameList, date2XDataMap); builder.head(headData).sheet("统计数据").doWrite(excelDataList); } private static List<List<Object>> getExcelDataList(Set<String> allDateList, Set<String> allOutletsNameList, Map<String, List<XData>> date2XDataMap) { List<List<Object>> excelDatalist = new ArrayList<>(); //网点小计 Map<String, Subtotal> outletsName2Subtotal = new HashMap<>(); //过包总计 Integer totalNumCount = 0; //违禁品总计 Integer dangerNumCount = 0; // 2.获取excel表数据 for (String currDate : allDateList) { List<Object> rowData = new ArrayList<>(); rowData.add(currDate); for (String outletsName : allOutletsNameList) { //初始化小计数据 Subtotal subtotal = outletsName2Subtotal.get(outletsName); if (subtotal == null) { outletsName2Subtotal.put(outletsName, new Subtotal(0, 0)); } List<XData> numList = date2XDataMap.get(currDate); boolean isNotExist = false; for (XData xData : numList) { if (outletsName.equals(xData.getOutletsName())) { Integer dangerNum = xData.getDangerNum() == null ? 0 : xData.getDangerNum(); Integer totalNum = xData.getTotalNum() == null ? 0 : xData.getTotalNum(); rowData.add(totalNum); rowData.add(dangerNum); isNotExist = false; //统计小计数量 Subtotal currSubtotal = outletsName2Subtotal.get(outletsName); currSubtotal.setSubTotalNum(currSubtotal.getSubTotalNum() + totalNum); currSubtotal.setSubDangerNum(currSubtotal.getSubDangerNum() + dangerNum); //统计总计数量 totalNumCount += totalNum; dangerNumCount += dangerNum; break; } else { isNotExist = true; } } //没有该网点的数量,则给默认值0 if (isNotExist) { rowData.add(0); rowData.add(0); } } excelDatalist.add(rowData); } // 3.存入小计 List<Object> rowSubtotalData = new ArrayList<>(); rowSubtotalData.add("小计"); allOutletsNameList.forEach(outletsName -> { Subtotal subtotal = outletsName2Subtotal.get(outletsName); Integer subTotalNum = subtotal.getSubTotalNum(); Integer subDangerNum = subtotal.getSubDangerNum(); rowSubtotalData.add(subTotalNum); rowSubtotalData.add(subDangerNum); }); excelDatalist.add(rowSubtotalData); // 4.存入总计 List<Object> rowTotalCountData = new ArrayList<>(); rowTotalCountData.add("过包总计"); rowTotalCountData.add(totalNumCount); excelDatalist.add(rowTotalCountData); List<Object> rowDangerCountData = new ArrayList<>(); rowDangerCountData.add("违禁品数总计"); rowDangerCountData.add(dangerNumCount); excelDatalist.add(rowDangerCountData); return excelDatalist; } private static List<List<String>> getExcelHeadData(Set<String> allOutletsNameList) { List<List<String>> list = new ArrayList<>(); // 1.获取excel表头 List<String> head0 = new ArrayList<>(); head0.add("网点\n数目\n日期"); list.add(head0); List<String> childrenHeadTitleList = new ArrayList<>(); childrenHeadTitleList.add("总数"); childrenHeadTitleList.add("违禁品数"); allOutletsNameList.forEach(outletsName -> { childrenHeadTitleList.forEach(childName -> { List<String> head = new ArrayList<>(); head.add(outletsName); head.add(childName); list.add(head); }); }); return list; } private static List<XData> getDataList() { List<XData> list = new ArrayList<>(); list.add(new XData("2021-08-19", 239, 0, "韵达")); list.add(new XData("2021-08-19", 6, 8, "申通")); list.add(new XData("2021-08-20", 5, 0, "德邦")); list.add(new XData("2021-08-20", 623, 0, "韵达")); list.add(new XData("2021-08-20", 74, 2, "长途汽车站")); list.add(new XData("2021-08-20", 2, 3, "申通")); return list; }}class XData { private String date; private String outletsName; private Integer totalNum; private Integer dangerNum; public XData(String date, Integer totalNum, Integer dangerNum, String outletsName) { this.date = date; this.outletsName = outletsName; this.totalNum = totalNum; this.dangerNum = dangerNum; } public String getDate() { return date; } public void setDate(String date) { this.date = date; } public String getOutletsName() { return outletsName; } public void setOutletsName(String outletsName) { this.outletsName = outletsName; } public Integer getTotalNum() { return totalNum; } public void setTotalNum(Integer totalNum) { this.totalNum = totalNum; } public Integer getDangerNum() { return dangerNum; } public void setDangerNum(Integer dangerNum) { this.dangerNum = dangerNum; }}class Subtotal { private Integer subTotalNum; private Integer subDangerNum; public Integer getSubTotalNum() { return subTotalNum; } public void setSubTotalNum(Integer subTotalNum) { this.subTotalNum = subTotalNum; } public Integer getSubDangerNum() { return subDangerNum; } public void setSubDangerNum(Integer subDangerNum) { this.subDangerNum = subDangerNum; } public Subtotal(Integer subTotalNum, Integer subDangerNum) { this.subTotalNum = subTotalNum; this.subDangerNum = subDangerNum; }}