前言

最近项目上有个关于excel导出的需求,要求如下:
1,表头除了固定的几个,可以动态添加,比如下面表格,范围1,时间,值是固定,其他的表头都是动态的
2,范围1,范围2,范围3是合并列
3,范围2,范围3是联动的
4,自适应宽高,自适应居中,样式设置
5,生成多个excel最后zip压缩

注意:
1,因为产品的需求,合并列范围1,范围2,范围3严格遵守合并的格式,并不是任意合并,所以比较复杂。
2,不支持列与列之间的合并,如果想要支持,可以基于此demo开发是没任何问题的。

POM

  <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.5.0</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.20</version></dependency><!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel --><dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.0.5</version></dependency><dependency><groupId>org.postgresql</groupId><artifactId>postgresql</artifactId><version>42.2.5</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.22</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.1</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.8.0</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.7</version></dependency>

设计

1,数据库获取数据用List<Map<String,Object>>,后面需要转换成List<List>(原因:easyexcel对List不兼容)

代码如下

压缩工具类

public class ZipUtils {private static final Charset DEFAULT_CHARSET = Charset.defaultCharset();/*** 将文件流压缩到目标流中** @param out       目标流,压缩完成自动关闭* @param fileNames 流数据在压缩文件中的路径或文件名* @param ins       要压缩的源,添加完成后自动关闭流*/public static void zip(OutputStream out, List<String> fileNames, List<InputStream> ins) {zip(out, fileNames.toArray(new String[0]), ins.toArray(new InputStream[0]));}/*** 将文件流压缩到目标流中** @param out       目标流,压缩完成自动关闭* @param fileNames 流数据在压缩文件中的路径或文件名* @param ins       要压缩的源,添加完成后自动关闭流*/public static void zip(File out, List<String> fileNames, List<InputStream> ins) throws IOException {FileOutputStream outputStream = new FileOutputStream(out);zip(outputStream, fileNames.toArray(new String[0]), ins.toArray(new InputStream[0]));outputStream.flush();}/*** 将文件流压缩到目标流中** @param out       目标流,压缩完成自动关闭* @param fileNames 流数据在压缩文件中的路径或文件名* @param ins       要压缩的源,添加完成后自动关闭流*/public static void zip(OutputStream out, String[] fileNames, InputStream[] ins) {ZipOutputStream zipOutputStream = null;try {zipOutputStream = getZipOutputStream(out, DEFAULT_CHARSET);zip(zipOutputStream, fileNames, ins);} catch (IOException e) {
//            throw new Exception("压缩包导出失败!", e);} finally {IOUtils.closeQuietly(zipOutputStream);}}/*** 将文件流压缩到目标流中** @param zipOutputStream 目标流,压缩完成不关闭* @param fileNames       流数据在压缩文件中的路径或文件名* @param ins             要压缩的源,添加完成后自动关闭流* @throws IOException IO异常*/public static void zip(ZipOutputStream zipOutputStream, String[] fileNames, InputStream[] ins) throws IOException {if (ArrayUtils.isEmpty(fileNames) || ArrayUtils.isEmpty(ins)) {throw new IllegalArgumentException("文件名不能为空!");}if (fileNames.length != ins.length) {throw new IllegalArgumentException("文件名长度与输入流长度不一致!");}for (int i = 0; i < fileNames.length; i++) {add(ins[i], fileNames[i], zipOutputStream);}}/*** 添加文件流到压缩包,添加后关闭流** @param in       需要压缩的输入流,使用完后自动关闭* @param fileName 压缩的路径* @param out      压缩文件存储对象* @throws IOException IO异常*/private static void add(InputStream in, String fileName, ZipOutputStream out) throws IOException {if (null == in) {return;}try {out.putNextEntry(new ZipEntry(fileName));IOUtils.copy(in, out);} catch (IOException e) {throw new IOException(e);} finally {IOUtils.closeQuietly(in);closeEntry(out);}}/*** 获得 {@link ZipOutputStream}** @param out     压缩文件流* @param charset 编码* @return {@link ZipOutputStream}*/private static ZipOutputStream getZipOutputStream(OutputStream out, Charset charset) {if (out instanceof ZipOutputStream) {return (ZipOutputStream) out;}return new ZipOutputStream(out,  DEFAULT_CHARSET);}/*** 关闭当前Entry,继续下一个Entry** @param out ZipOutputStream*/private static void closeEntry(ZipOutputStream out) {try {out.closeEntry();} catch (IOException e) {// ignore}}}

自适应宽度

mport com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.CellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;import java.util.HashMap;
import java.util.List;
import java.util.Map;public class CustomCellWriteWeightStrategy extends AbstractColumnWidthStyleStrategy {private Map<Integer, Map<Integer, Integer>> CACHE = new HashMap<>();@Overrideprotected void setColumnWidth(WriteSheetHolder writeSheetHolder, List<WriteCellData<?>> cellDataList, Cell cell, Head head, Integer integer, Boolean isHead) {boolean needSetWidth = isHead || !CollectionUtils.isEmpty(cellDataList);if (needSetWidth) {Map<Integer, Integer> maxColumnWidthMap = CACHE.get(writeSheetHolder.getSheetNo());if (maxColumnWidthMap == null) {maxColumnWidthMap = new HashMap<>();CACHE.put(writeSheetHolder.getSheetNo(), maxColumnWidthMap);}Integer columnWidth = this.dataLength(cellDataList, cell, isHead);if (columnWidth >= 0) {if (columnWidth > 254) {columnWidth = 254;}Integer maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex());if (maxColumnWidth == null || columnWidth > maxColumnWidth) {maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth);Sheet sheet = writeSheetHolder.getSheet();sheet.setColumnWidth(cell.getColumnIndex(), columnWidth * 256);}}}}/*** 计算长度* @param cellDataList* @param cell* @param isHead* @return*/private Integer dataLength(List<WriteCellData<?>>  cellDataList, Cell cell, Boolean isHead) {if (isHead) {return cell.getStringCellValue().getBytes().length;} else {CellData cellData = cellDataList.get(0);CellDataTypeEnum type = cellData.getType();if (type == null) {return -1;} else {switch (type) {case STRING:// 换行符(数据需要提前解析好)int index = cellData.getStringValue().indexOf("\n");return index != -1 ?cellData.getStringValue().substring(0, index).getBytes().length + 1 : cellData.getStringValue().getBytes().length + 1;case BOOLEAN:return cellData.getBooleanValue().toString().getBytes().length;case NUMBER:return cellData.getNumberValue().toString().getBytes().length;default:return -1;}}}}
}

自适应高度

import com.alibaba.excel.write.style.row.AbstractRowHeightStyleStrategy;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;import java.util.Iterator;public class CustomCellWriteHeightStrategy extends AbstractRowHeightStyleStrategy {/*** 默认高度*/private static final Integer DEFAULT_HEIGHT = 300;@Overrideprotected void setHeadColumnHeight(Row row, int relativeRowIndex) {}@Overrideprotected void setContentColumnHeight(Row row, int relativeRowIndex) {Iterator<Cell> cellIterator = row.cellIterator();if (!cellIterator.hasNext()) {return;}// 默认为 1行高度Integer maxHeight = 1;while (cellIterator.hasNext()) {Cell cell = cellIterator.next();switch (cell.getCellType()) {case STRING:if (cell.getStringCellValue().contains("\n")) {int length = cell.getStringCellValue().split("\n").length;maxHeight = Math.max(maxHeight, length);}break;default:break;}}row.setHeight((short) (maxHeight * DEFAULT_HEIGHT));}
}

自适应居中及字体设置

    //设置样式 去除默认表头样式及设置内容居中public static HorizontalCellStyleStrategy getStyleStrategy(){//内容样式策略WriteCellStyle contentWriteCellStyle = new WriteCellStyle();//垂直居中,水平居中contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);contentWriteCellStyle.setBorderTop(BorderStyle.THIN);contentWriteCellStyle.setBorderRight(BorderStyle.THIN);contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);//设置 自动换行contentWriteCellStyle.setWrapped(true);// 字体策略WriteFont contentWriteFont = new WriteFont();// 字体大小contentWriteFont.setFontHeightInPoints((short) 12);contentWriteCellStyle.setWriteFont(contentWriteFont);//头策略使用默认WriteCellStyle headWriteCellStyle = new WriteCellStyle();headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);}

合并策略

import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.merge.AbstractMergeStrategy;
import com.yueyang.util.MergeParam;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;import java.util.List;
import java.util.Map;public class BizMergeStrategy  extends AbstractMergeStrategy {private Map<String, List<MergeParam>> strategyMap;private Sheet sheet;public BizMergeStrategy(Map<String, List<MergeParam>> strategyMap) {this.strategyMap = strategyMap;}@Overrideprotected void merge(Sheet sheet, Cell cell, Head head, Integer integer) {this.sheet = sheet;if (cell.getRowIndex() == 1 && cell.getColumnIndex() == 0) {/*** 保证每个cell被合并一次,如果不加上面的判断,因为是一个cell一个cell操作的,* 例如合并A2:A3,当cell为A2时,合并A2,A3,但是当cell为A3时,又是合并A2,A3,* 但此时A2,A3已经是合并的单元格了*/for (Map.Entry<String, List<MergeParam>> entry : strategyMap.entrySet()) {Integer columnIndex = Integer.valueOf(entry.getKey());entry.getValue().forEach(rowRange -> {//添加一个合并请求sheet.addMergedRegionUnsafe(new CellRangeAddress(rowRange.getStart(),rowRange.getEnd(), columnIndex, columnIndex));});}}}
}

对象类

数据库查询的映射类

import lombok.Data;@Data
public class XxglFieldDefine {private String fieldName;private String fieldKey;
}

合并基础类

import lombok.Data;@Data
public class MergeParam {private int start;private int end;
}

合并列枚举

import lombok.Getter;@Getter
public enum  MergeColumnEnum {/*** 通知消息模板*/MERGE_COLUMN1("column1", "范围1"),MERGE_COLUMN2("column2", "范围2"),MERGE_COLUMN3("column3", "范围3"),;private final String mergeColumn;private final String desc;MergeColumnEnum(String code, String title) {this.mergeColumn = code;this.desc = title;}
}

主要代码

 @Resourceprivate DataDbMapper mapper;@GetMapping("/test")@ApiOperation("/test")public List<Map<String, Object>> test() throws Exception {List<Map<String, Object>> dataMap = mapper.getMap();Map<String, List<MergeParam>> mergeMap = getMergeMap(dataMap);List<InputStream> ins = new ArrayList<>();// 压缩包内流的文件名List<String> paths = new ArrayList<>();for (int i = 0; i < 2; i++) {// 使用 easyExcel 写到 OutputStreamString moduleName="moudle_"+System.currentTimeMillis();ins.add(writeExcel6(mergeMap, dataMap,moduleName));paths.add(moduleName+".xlsx");}// 保存的 zip 文件名File zipFile = new File("E:\\excel\\noModelWrite.zip");ZipUtils.zip(zipFile, paths, ins);return dataMap;}/***  自适应合并居中,接list数据 对象固定*  1,长度,宽度无变化**  数据为  map*  head为可变类型* @param map* @param map1*/public static InputStream writeExcel6(Map<String, List<MergeParam>> map, List<Map<String, Object>> map1,String module) {// 使用 easyExcel 写到 OutputStreamOutputStream out = new ByteArrayOutputStream();//这里自定义一个单元格的格式(标黄的行高亮显示)ExcelWriter excelWriter = EasyExcel.write(out).excelType(ExcelTypeEnum.XLSX).build();List<List<Object>> dataList = new ArrayList<List<Object>>();List<XxglFieldDefine> fList = getXxglFieldDefines();String[] arry = new String[fList.size()];for(int i=0; i<fList.size();i++){arry[i] = fList.get(i).getFieldKey();}//设置导出的数据内容for (Map<String, Object> m : map1) {List<Object> data = new ArrayList<Object>();for (int i = 0; i < arry.length; i++) {data.add(m.get(arry[i]));}dataList.add(data);}// 写sheet的时候注册相应的自定义合并单元格策略WriteSheet writeSheet = EasyExcel.writerSheet(module).head(createHeadByFields(head1())).registerWriteHandler(new BizMergeStrategy( map)).registerWriteHandler(new CustomCellWriteWeightStrategy()).registerWriteHandler(new CustomCellWriteHeightStrategy()).registerWriteHandler(getStyleStrategy()).build();excelWriter.write(dataList, writeSheet);excelWriter.finish();return outputStream2InputStream(out);}/*** 输出流转输入流;数据量过大请使用其他方法** @param out* @return*/private static ByteArrayInputStream outputStream2InputStream(OutputStream out) {Objects.requireNonNull(out);ByteArrayOutputStream bos;bos = (ByteArrayOutputStream) out;return new ByteArrayInputStream(bos.toByteArray());}/*** 动态头 列设置* @return*/private static  List<String> head1() {List<String> head0 = new ArrayList<String>();head0.add("范围1" );head0.add("范围2" );head0.add("范围3" );head0.add("时间" );head0.add("值" );head0.add("排序" );head0.add("主键id" );return head0;}//设置样式 去除默认表头样式及设置内容居中public static HorizontalCellStyleStrategy getStyleStrategy(){//内容样式策略WriteCellStyle contentWriteCellStyle = new WriteCellStyle();//垂直居中,水平居中contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);contentWriteCellStyle.setBorderLeft(BorderStyle.THIN);contentWriteCellStyle.setBorderTop(BorderStyle.THIN);contentWriteCellStyle.setBorderRight(BorderStyle.THIN);contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);//设置 自动换行contentWriteCellStyle.setWrapped(true);// 字体策略WriteFont contentWriteFont = new WriteFont();// 字体大小contentWriteFont.setFontHeightInPoints((short) 12);contentWriteCellStyle.setWriteFont(contentWriteFont);//头策略使用默认WriteCellStyle headWriteCellStyle = new WriteCellStyle();headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());return new HorizontalCellStyleStrategy(headWriteCellStyle, contentWriteCellStyle);}private static List<List<String>> createHeadByFields(List<String> headList) {return headList.stream().map(Collections::singletonList).collect(Collectors.toList());}/*** 查询的数据对应的key,记住 顺序和设置动态头的顺序一定要一致* @return*/private static List<XxglFieldDefine> getXxglFieldDefines() {List<XxglFieldDefine> fList  = new ArrayList<XxglFieldDefine>();XxglFieldDefine x = new XxglFieldDefine();x.setFieldName("范围1");x.setFieldKey("column1");fList.add(x);XxglFieldDefine x1 = new XxglFieldDefine();x1.setFieldName("范围2");x1.setFieldKey("column2");fList.add(x1);XxglFieldDefine x2 = new XxglFieldDefine();x2.setFieldName("范围3");x2.setFieldKey("column3");fList.add(x2);XxglFieldDefine x3 = new XxglFieldDefine();x3.setFieldName("date");x3.setFieldKey("date");fList.add(x3);XxglFieldDefine x4 = new XxglFieldDefine();x4.setFieldName("value");x4.setFieldKey("value");fList.add(x4);XxglFieldDefine x5 = new XxglFieldDefine();x5.setFieldName("sort");x5.setFieldKey("sort");fList.add(x5);XxglFieldDefine x6 = new XxglFieldDefine();x6.setFieldName("id");x6.setFieldKey("id");fList.add(x6);return fList;}/*** 获取范围1 范围2 范围3 合并数据* @param dataMap* @return*/private Map<String, List<MergeParam>> getMergeMap(List<Map<String, Object>> dataMap) {Map<String, List<MergeParam>> map = new HashMap<>();//确定合并的字段有几个Map<Object, Integer> column1Map = new LinkedHashMap<>();Map<Object, Integer> column2Map = new LinkedHashMap<>();Map<Object, Integer> column3Map = new LinkedHashMap<>();List<MergeParam> column1List = new ArrayList<>();List<MergeParam> column2List = new ArrayList<>();List<MergeParam> column3List = new ArrayList<>();Boolean firstBool = true;int start = 0;for (Map<String, Object> stringObjectMap : dataMap) {start++;if (stringObjectMap.containsKey(MergeColumnEnum.MERGE_COLUMN1.getMergeColumn())) {Object column1Obj = stringObjectMap.get(MergeColumnEnum.MERGE_COLUMN1.getMergeColumn());if (column1Map.containsKey(column1Obj)) {//说明已经存进去了column1Map.put(column1Obj, column1Map.get(column1Obj) + 1);if (stringObjectMap.containsKey(MergeColumnEnum.MERGE_COLUMN2.getMergeColumn())) {Object column2Obj = stringObjectMap.get(MergeColumnEnum.MERGE_COLUMN2.getMergeColumn());if (column2Map.containsKey(column2Obj)) {//说明已经存进去了column2Map.put(column2Obj, column2Map.get(column2Obj) + 1);if (stringObjectMap.containsKey(MergeColumnEnum.MERGE_COLUMN3.getMergeColumn())) {Object o = stringObjectMap.get(MergeColumnEnum.MERGE_COLUMN3.getMergeColumn());if (column3Map.containsKey(o)) {//说明已经存进去了column3Map.put(o, column3Map.get(o) + 1);} else {column3Map.put(o, 1);}}} else {//说明合并字段等级2的已经结束,需要处理生成合并字段等级3的合并数据column2Map.put(column2Obj, 1);//开始处理column3List.addAll(getMergeParamList(column3Map, start));column3Map.clear();//初始化合并字段等级3if (stringObjectMap.containsKey(MergeColumnEnum.MERGE_COLUMN3.getMergeColumn())) {Object column3Obj = stringObjectMap.get(MergeColumnEnum.MERGE_COLUMN3.getMergeColumn());column3Map.put(column3Obj, 1);}}}} else {if (firstBool) {//说明第一次firstBool = false;} else {//说明某一个合并字段等级结束 也是新的合并字段等级开始//开始处理数据//1,处理合并column1Map 的数据column1List.addAll(getMergeParamList(column1Map, start));//2,处理合并column1Map 的数据column2List.addAll(getMergeParamList(column2Map, start));//3,处理合并column1Map 的数据column3List.addAll(getMergeParamList(column3Map, start));//4,清空所有的Mapcolumn1Map.clear();column2Map.clear();column3Map.clear();}//初始化mapcolumn1Map.put(column1Obj, 1);if (stringObjectMap.containsKey(MergeColumnEnum.MERGE_COLUMN2.getMergeColumn())) {Object column2Obj = stringObjectMap.get(MergeColumnEnum.MERGE_COLUMN2.getMergeColumn());column2Map.put(column2Obj, 1);}if (stringObjectMap.containsKey(MergeColumnEnum.MERGE_COLUMN3.getMergeColumn())) {Object column3Obj = stringObjectMap.get(MergeColumnEnum.MERGE_COLUMN3.getMergeColumn());column3Map.put(column3Obj, 1);}}}}//1,处理合并column1Map 的数据column1List.addAll(getMergeParamList(column1Map, start + 1));//2,处理合并column1Map 的数据column2List.addAll(getMergeParamList(column2Map, start + 1));//3,处理合并column1Map 的数据column3List.addAll(getMergeParamList(column3Map, start + 1));map.put("0", column1List);map.put("1", column2List);map.put("2", column3List);return map;}private List<MergeParam> getMergeParamList(Map<Object, Integer> columnMap, int end) {List<MergeParam> mergeParamList = new ArrayList<>();if (MapUtil.isEmpty(columnMap)) {return mergeParamList;}int sum = 0;Set<Map.Entry<Object, Integer>> en = columnMap.entrySet();for (Map.Entry<Object, Integer> entry : en) {sum += entry.getValue();}int start = end - sum;for (Map.Entry<Object, Integer> entry : en) {if (entry.getValue() > 1) {MergeParam mergeParam = new MergeParam();mergeParam.setStart(start);mergeParam.setEnd(start + entry.getValue() - 1);start = start + entry.getValue();mergeParamList.add(mergeParam);} else {start++;}}return mergeParamList;}

测试数据

用的pg数据库
Mapper

public interface DataDbMapper {List<Map<String,Object>> getMap();
}

xml

<mapper namespace="com.yueyang.demo1.mapper.DataDbMapper"><select id="getMap" resultType="java.util.Map">select *from t_module_testorder by sort asc</select>
</mapper>

数据

CREATE TABLE "public"."t_module_test" ("id" serial4,"column1" varchar(50) ,"column2" varchar(50) ,"column3" varchar(50) ,"date" varchar(50) ,"value" varchar(50) ,"sort" int8)
;
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (1, '范围1', '范围1-1', '范围1-2', '今天', '12.11', 1);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (3, '范围1', '范围1-1', '范围1-2-1', '今天', '12.11', 3);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (4, '范围1', '范围1-1', '范围1-2-1', '今天', '12.11', 4);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (5, '范围1', '范围1-2', '范围1-2-2', '今天', '12.11', 5);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (6, '范围1', '范围1-2', '范围1-2-2', '今天', '12.11', 6);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (7, '范围1', '范围1-2', '范围1-2-2', '今天', '12.11', 7);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (8, '范围1', '范围1-2', '范围1-2-2', '今天', '12.11', 8);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (25, '范围2', '范围2-1', '范围2-2', '今天', '12.11', 9);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (26, '范围2', '范围2-1', '范围2-2-1', '今天', '12.11', 10);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (27, '范围2', '范围2-1', '范围2-2-1', '今天', '12.11', 11);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (28, '范围2', '范围2-1', '范围2-2-1', '今天', '12.11', 12);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (29, '范围2', '范围2-2', '范围2-2-2', '今天', '12.11', 13);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (30, '范围2', '范围2-2', '范围2-2-2', '今天', '12.11', 14);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (31, '范围2', '范围2-2', '范围2-2-2', '今天', '12.11', 15);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (32, '范围2', '范围2-2', '范围2-2-2', '今天', '12.11', 16);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (33, '范围3', '范围3-1', '范围3-2', '今天', '12.11', 17);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (34, '范围3', '范围3-1', '范围3-2-1', '今天', '12.11', 18);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (35, '范围3', '范围3-1', '范围3-2-1', '今天', '12.11', 19);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (36, '范围3', '范围3-1', '范围3-2-1', '今天', '12.11', 20);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (37, '范围3', '范围3-2', '范围3-2-2', '今天', '12.11', 21);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (38, '范围3', '范围3-2', '范围3-2-2', '今天', '12.11', 22);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (39, '范围3', '范围3-2', '范围3-2-2', '今天', '12.11', 23);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (40, '范围3', '范围3-2', '范围3-2-2', '今天', '12.11', 24);
INSERT INTO "public"."t_module_test"("id", "column1", "column2", "column3", "date", "value", "sort") VALUES (2, '范围1', '范围1-1', '范围1-2', '今天', '12.11', 2);

EasyExcel生成多个exel文件并zip压缩相关推荐

  1. Python将Pandas中Dataframe数据保存为gzip/zip文件:gzip压缩文件、zip压缩文件

    Python将Pandas中Dataframe数据保存为gzip/zip文件:gzip压缩文件.zip压缩文件 目录 Python将Pandas中Dataframe数据保存为gzip/zip文件:gz ...

  2. php使用ZipArchive扩展实现文件的zip压缩与zip解压

    ZipArchive 是PHP自带的zip扩展类,可以实现对文件或目录实现ZIP文件的压缩和解压,使用前首先要确保PHP ZipArchive扩展已经开启,以下代码亲测可用,但对中文命名的文件不兼容 ...

  3. linux 压缩根目录文件,Linux操作系统下如何压缩文件? zip压缩命令使用

    Linux zip命令用于压缩文件. zip是个使用广泛的压缩程序,文件经它压缩后会另外产生具有".zip"扩展名的压缩文件. 在linux操作系统中,使用zip命令进行文件压缩时 ...

  4. python 实现文件的批量压缩为.zip格式+.zip格式文件的解析

    python 实现文件的批量压缩为.zip格式+.zip格式文件的解析 python 实现文件的批量压缩为.zip格式 Python解析.zip文件的常见函数 python 实现文件的批量压缩为.zi ...

  5. Linux的压缩/解压缩文件命令 zip 和 tar

    Linux的压缩/解压缩命令详解及实例 压缩服务器上当前目录的内容为xxx.zip文件 zip -r xxx.zip ./* 解压zip文件到当前目录 unzip filename.zip 另:有些服 ...

  6. Java 的zip压缩和解压缩

    Java 的zip压缩和解压缩 好久没有来这写东西了,今天中秋节,有个东西想拿出来分享,一来是工作中遇到的问题,一来是和csdn问候一下,下面就分享一个Java中的zip压缩技术,代码实现比较简单,代 ...

  7. linux压缩指定时间的文件,Linux下压缩某个文件夹(文件夹打包)

    tar -zcvf /home/xahot.tar.gz /xahot tar -zcvf 打包后生成的文件名全路径 要打包的目录 例子:把/xahot文件夹打包后生成一个/home/xahot.ta ...

  8. Java Zip压缩实现(亲测)

    最近在自学javaWeb,先复习一下java,把还给老师的东西再找回来(知识如果不用很快就会忘记啊).. 今天看到了zip压缩,决定要整理一下. java将有关zip压缩的内容都封装在java.uti ...

  9. linux好压iso压缩文件,好压压缩文件管理器新手指南

    好压压缩文件管理器:下载地址 好压HaoZip的控制台 一.ZIP.7Z与 TAR 格式      好压软件 可以创建三种不同的压缩文件格式: ZIP.7Z 和 TAR.下面是每一种格式的优点叙述 : ...

最新文章

  1. 利用矩阵奇异值分解(SVD)进行降维
  2. 输入参数_MyBatis中的输入/输出参数
  3. python 日期格式和字符串格式的转化
  4. linux shell if 参数
  5. Python面试题(三)(爬虫方面)
  6. GDCM:gdcm::Validate的测试程序
  7. Atom飞行手册翻译: 2.11 Atom中的版本控制
  8. JS魔法堂之实战:纯前端的图片预览
  9. 论文的事情终于可以告一段落了
  10. redis 常用配置文件配置
  11. 数字城市新型基础设施——打造以“运营与安全并重”为特色的新型数字空间
  12. 数藏2.0故事中,元境开启“元宇宙丝绸之路”
  13. 迪文屏程序制作。通讯
  14. 纤维水泥板及配件建筑材料英国UKCA认证—EN 492
  15. pb中数据窗口函数小结
  16. 街霸 隆(Ryu)升龙拳(Syoryuken)动画(四)制作过程中几个版本动画比较一下
  17. 邬贺铨院士:5G技术影响智联网的关键点
  18. windows10系统桌面图标小盾牌去除方法
  19. php 如何执行top命令,技术|如何在批处理模式下运行 top 命令
  20. 口袋网咖已有服务器在使用怎么注销,口袋网咖怎么登录_口袋网咖登录方法介绍_游戏吧...

热门文章

  1. 关于ADS1292测心率心电的一些学习总结
  2. UiBot 邮件群发
  3. [NXP.iMX6UL] 驱动开发
  4. 冠军联赛:当火焰变成焰火 海水变成泪水
  5. 编码中关于二义性的解释
  6. Linux之ubuntu离线安装软件包
  7. 超详细如何配置NAT
  8. 【榜单公布】新星计划第二季落幕,快看你有没有上榜?
  9. 【品牌DTC增长力】私域,你做的可能是“假的”
  10. xss绕过字符过滤_xss绕过过滤之方法