easyExcel 导入、导出Excel 封装公共的方法

文档包含三部分功能

1、easyExcel 公共导出list<对象>方法,可以自定义excel中第一行和样式
2、easyExcel 导入逻辑,结合spring Validator 验证导入数据是否符合规范
3、easyExcel 自定义导出 list<map> 、 list<对象> (可优化),可把sql.date,sql.time在excel转换正常显示

1、easyExcel 公共导出方法

1)依赖:

<!-- hutool -->
<!-- 阿里开源的excel处理包 -->
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>easyexcel</artifactId>
	<version>3.3.3</version>
</dependency>
<!-- poi -->
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi</artifactId>
	<version>5.0.0</version>
</dependency>
<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi-ooxml</artifactId>
	<version>5.0.0</version>
</dependency>

 2)封装的公共导出方法:

# 其中 templateBool 代表第一行是否为标题行
# 其中 firstRowContent 代码第一行写入的内容
FileUtil.exportExcel(response, "导出应用表列表", "sheet1", App.class, appList, templateBool,firstRowContent);

其中 App.class 实体类属性添加 @ExcelIgnore 忽略导出,@ExcelProperty("*excel列明") 指出导出列表

@ExcelIgnore
@ExcelProperty("*excel列明")

导出代码参考 

easyExcel自定义导入头实现icon-default.png?t=N7T8https://www.cnblogs.com/Dog1363786601/p/17352096.html

3)实现easyExcel 导入导出依赖公共文件方法

import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;

import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.util.IOUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 项目名称:base
 *
 * <p>功能: 功能描述。</p>
 *
 * @author:yht
 * @version:V1.0 2023/5/30
 */
@Slf4j
public class FileUtil {
    

    /**
     * 设置导出为excel 的 Response 中的描述
     *
     * @param response    响应结果对象
     * @param rawFileName 文件名
     */
    public static void setExcelResponse(HttpServletResponse response, String rawFileName) {
        //设置响应格式
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8"); // 设置字符编码
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = Base64.encode(rawFileName, Charset.defaultCharset());
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
    }

    /**
     * MultipartFile对象转成File对象
     *
     * @param multipartFile
     * @return
     */
    public static File transferToFile(MultipartFile multipartFile) {
//        选择用缓冲区来实现这个转换即使用java 创建的临时文件 使用 MultipartFile.transferto()方法 。
        File file = null;
        try {
            String originalFilename = multipartFile.getOriginalFilename();
            String[] filename = originalFilename.split("\\.");
            file = File.createTempFile(filename[0], filename[1] + ".");
            multipartFile.transferTo(file);
            file.deleteOnExit();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return file;
    }

    /**
     * 断面数据导出Excel
     * <a href="https://www.cnblogs.com/Dog1363786601/p/17352096.html">EasyExcelSheetWriteHandler 参考:包含map导出样例</a>
     *
     * @param response:response
     * @param fileName:文件名
     * @param sheetName:sheet              页签名称
     * @param targetClass:目标对象Class
     * @param dateList:对象数据
     * @param firstRowDocBool:第一行是不是填写文档说明
     * @param firstRowContent:第一行的内容
     */
    public static void exportExcel(HttpServletResponse response, String fileName, String sheetName,
                                   Class<?> targetClass, List<?> dateList, Boolean firstRowDocBool, String firstRowContent) throws IOException {
        if (StrUtil.isBlank(fileName)) {
            //当前日期
            fileName = DateUtil.format(new DateTime(), DatePattern.CHINESE_DATE_TIME_FORMATTER);
        }

        setExcelResponse(response, fileName);

        // 设置表头字体样式
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        WriteFont headWriteFont = new WriteFont();
        headWriteFont.setFontHeightInPoints((short) 12); // 设置字体大小为16
        headWriteCellStyle.setWriteFont(headWriteFont);
        headWriteCellStyle.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex());

        // 设置表头 和内容样式
        HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(headWriteCellStyle, (List<WriteCellStyle>) null);

        ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), targetClass)
                .registerWriteHandler(new EasyExcelSheetWriteHandler(firstRowDocBool, firstRowContent))
                .registerWriteHandler(horizontalCellStyleStrategy)
                .relativeHeadRowIndex(1)
                .excelType(ExcelTypeEnum.XLSX)
                .build();

        WriteSheet writeSheet = EasyExcel.writerSheet(0, sheetName).build();

        excelWriter.write(dateList, writeSheet);
        excelWriter.finish();
    }
}

 4)其中自定导入第一行 导入内容依赖类

import com.alibaba.excel.write.handler.SheetWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;

public class EasyExcelSheetWriteHandler implements SheetWriteHandler {

    /**
     * 首行是否为文档
     */
    private final Boolean firstRowDocBool;

    /**
     * 填写文件说明
     */
    private final String firstRowContent;

    public EasyExcelSheetWriteHandler(Boolean firstRowDocBool, String firstRowContent) {
        this.firstRowDocBool = firstRowDocBool;
        this.firstRowContent = firstRowContent;
    }

    @Override
    public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
        Workbook workbook = writeWorkbookHolder.getWorkbook();
        //Sheet sheet = workbook.getSheetAt(0);
        Sheet sheet = workbook.getSheet(writeSheetHolder.getSheetName());

        Row row1 = sheet.getRow(0);
        if (row1 == null) {
            row1 = sheet.createRow(0);
        }
        row1.setHeight((short) 500);//25*20   实际行高*20
        Cell cell1 = row1.getCell(0);
        if (cell1 == null) {
            cell1 = row1.createCell(0);
        }
        cell1.setCellValue(firstRowContent);

        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setVerticalAlignment(VerticalAlignment.BOTTOM);
        cellStyle.setFillBackgroundColor(IndexedColors.WHITE.getIndex());
        cellStyle.setBorderTop(BorderStyle.NONE);
        cellStyle.setBorderBottom(BorderStyle.NONE);
        cellStyle.setBorderLeft(BorderStyle.NONE);
        cellStyle.setBorderRight(BorderStyle.NONE);

        if (Boolean.TRUE.equals(firstRowDocBool)) {
            cellStyle.setAlignment(HorizontalAlignment.LEFT);
        } else {
            cellStyle.setAlignment(HorizontalAlignment.CENTER);
        }

        Font font = workbook.createFont();
        font.setBold(false);
        if (Boolean.TRUE.equals(firstRowDocBool)) {
            font.setFontName("宋体");
            font.setFontHeight((short) 220);//11*20   实际字号(字高)*20

        } else {
            font.setFontHeight((short) 360);//18*20   实际字号(字高)*20
            font.setFontName("黑体");
        }
        cellStyle.setFont(font);

        cell1.setCellStyle(cellStyle);
        sheet.addMergedRegionUnsafe(new CellRangeAddress(0, 0, 0, 15));
    }
}

2、easyExcel 导入逻辑

1)依赖于 fileutil,将  MultipartFile 转为file

File file = FileUtil.transferToFile(multipartFile);

2)拿到文件以后,导入实现逻辑如下 

EasyExcel.read(file, App.class, new ReadListener<App>() {
                        //临时存储数据对象
                        private final List<App> cachedDataList = ListUtils.newArrayList();

                        @Override
                        public void invoke(App data, AnalysisContext context) {
                            cachedDataList.add(data);
                        }

                        @Transactional
                        @Override
                        public void doAfterAllAnalysed(AnalysisContext context) {
                            StringBuffer errorCheckMsg = new StringBuffer();
                            AtomicBoolean isPass = new AtomicBoolean(true);

                            if (CollUtil.isEmpty(cachedDataList)) {
                                throw new CommonException("导入Excel列表为空");
                            }

                            //数据行是从第三行开始
                            AtomicInteger rowIndex = new AtomicInteger(3);
                            cachedDataList.forEach((app) -> {
                                //spring validator 验证每行数据是否合规
                                BindingResult result = new BeanPropertyBindingResult(app, "app");
                                validator.validate(app, result);
                                if (result.hasErrors()) {
                                    isPass.set(false);
                                    // 处理验证错误,例如返回错误消息
                                    errorCheckMsg.append("第").append(rowIndex).append("行:");
                                    StringBuilder sb = new StringBuilder();
                                    for (ObjectError error : result.getAllErrors()) {
                                        sb.append(error.getDefaultMessage()).append(";");
                                    }
                                    errorCheckMsg.append(sb).append("\n");
                                }
                                rowIndex.getAndIncrement();
                            });

                            if (isPass.get()) {
                                //mybatis 插入数据方法
                                saveBatch(cachedDataList);
                            }

                            if (!StrUtil.isEmpty(errorCheckMsg.toString())) {
                                throw new CommonException(errorCheckMsg.toString());
                            }
                        }
                    }).sheet()
                    .headRowNumber(2)//设置标题行的行号
                    .doRead();

3、easyExcel 自定义 list<map> 导出

1)导出工具类的使用

/**
     * 导出采购订单列表
     */
    @PreAuthorize("@ss.hasPermi('mes:ec:purorder:export')")
    @Log(title = "采购订单", businessType = BusinessType.EXPORT)
    @PostMapping("acsEnvMonitHis/export")
    public void export(BaseEntity baseEntity, HttpServletResponse response) throws IOException {
        String[][] headMap = {{"AA"}, {"BB"}
                , {"CC"}, {"DD"}};
        String[] dataStrMap = {"CC", "EE"};

        int[] witdhMap = {15, 20};
        List<Map<String, Object>> listDatas = 获取数据的service方法
        
        NoModelWriteData nmwDate = new NoModelWriteData();
        nmwDate.setFileName("历史生产数据");
        nmwDate.setHeadMap(headMap);
        nmwDate.setDataStrMap(dataStrMap);
        nmwDate.setWitdhArray(witdhMap);
        nmwDate.setDataList(listDatas);

        EasyExcelUtils.noModleExportExcel(nmwDate, response);
    }

2)依赖工具类:EasyExcelUtils

package com.hy.common.utils.poi;

import cn.hutool.core.util.ArrayUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.converters.ConverterKeyBuild;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import org.apache.poi.util.IOUtils;
import org.springframework.web.bind.annotation.RequestBody;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class EasyExcelUtils {

    //不创建对象的导出
    public static void noModleExportExcel(@RequestBody NoModelWriteData data, HttpServletResponse response) throws IOException {

        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode(data.getFileName(), "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");

        OutputStream out = null;
        try {
            out = response.getOutputStream();
            // 这里需要设置不关闭流
            ExcelWriter excelWriter = EasyExcel.write(out).charset(StandardCharsets.UTF_8).build();

            SqlDateConverter converterSqlDate = new SqlDateConverter();
            excelWriter.writeContext().currentWriteHolder().converterMap().put(ConverterKeyBuild.buildKey(converterSqlDate.supportJavaTypeKey()), converterSqlDate);
            excelWriter.writeContext().currentWriteHolder().converterMap().put(ConverterKeyBuild.buildKey(converterSqlDate.supportJavaTypeKey(), converterSqlDate.supportExcelTypeKey()), converterSqlDate);

            ExcelWriterSheetBuilder writerSheetBuilder = EasyExcel.writerSheet();
            writerSheetBuilder.registerConverter(new SqlDateConverter());
            writerSheetBuilder.registerConverter(new SqlTimeConverter());
            if (ArrayUtil.isNotEmpty(data.getWitdhArray())) {
                writerSheetBuilder.registerWriteHandler(new ColumnWidthStyleStrategy(data.getWitdhArray()));
            }

            WriteSheet writeSheet = writerSheetBuilder.build();
            writeSheet.setHead(head(data.getHeadMap()));
            writeSheet.setSheetName(data.getFileName());

            excelWriter.write(dataList(data.getDataList(), data.getDataStrMap()), writeSheet);
            excelWriter.finish();
        } catch (Exception e) {
            throw e;
        } finally {
            IOUtils.closeQuietly(out);
        }
    }

    //创建对象的导出
    public <T> void simpleWrite(@RequestBody SimpleWriteData data, Class<T> clazz, HttpServletResponse response) throws IOException {
        // 这里注意 有同学反应使用swagger 会导致各种问题,请直接用浏览器或者用postman
        //response.setContentType("application/vnd.ms-excel");
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode(data.getFileName(), "UTF-8");
        response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), clazz).sheet(data.getFileName()).doWrite(data.getDataList());
    }

    //设置表头
    private static List<List<String>> head(String[][] headMap) {
        List<List<String>> list = new ArrayList<List<String>>();
        for (String[] headArray : headMap) {
            List<String> headList = new ArrayList<String>();
            for (String headStr : headArray) {
                headList.add(headStr);
            }
            list.add(headList);
        }
        return list;
    }

    //设置导出的数据内容
    private static List<List<Object>> dataList(List<Map<String, Object>> dataList, String[] dataStrMap) {
        List<List<Object>> list = new ArrayList<List<Object>>();
        for (Map<String, Object> map : dataList) {
            List<Object> data = new ArrayList<Object>();
            for (int i = 0; i < dataStrMap.length; i++) {
                data.add(map.get(dataStrMap[i]));
            }
            list.add(data);
        }
        return list;
    }
}

3)导出工具类、共依赖5个类,有不同作用,可根据实际情况删减

依赖3个类:2种参数,1个列宽策略

NoModelWriteData :导出数据,类型为List<MAP>
SimpleWriteData:导出数据,类型为List<对象>
ColumnWidthStyleStrategy:导出的列样式宽度策略

其中解决显示异常的数据类型依赖于2个类

SqlDateConverter :sqldate显示异常
SqlTimeConverter:sqltime显示异常
类1:NoModelWriteData :导出的第1种参数
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class NoModelWriteData implements Serializable {
    /** 文件名 **/
    private String fileName;
    /** 表头数组 **/
    private String[][] headMap;
    /** 对应数据字段数组 **/
    private String[] dataStrMap;
    /** 列宽数组 **/
    private int[] witdhArray;

    /** 数据集合 **/
    private List<Map<String, Object>> dataList;

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String[][] getHeadMap() {
        return headMap;
    }

    public void setHeadMap(String[][] headMap) {
        this.headMap = headMap;
    }

    public String[] getDataStrMap() {
        return dataStrMap;
    }

    public void setDataStrMap(String[] dataStrMap) {
        this.dataStrMap = dataStrMap;
    }

    public int[] getWitdhArray() {
        return witdhArray;
    }

    public void setWitdhArray(int[] witdhArray) {
        this.witdhArray = witdhArray;
    }

    public List<Map<String, Object>> getDataList() {
        return dataList;
    }

    public void setDataList(List<Map<String, Object>> dataList) {
        this.dataList = dataList;
    }

    @Override
    public String toString() {
        return "NoModelWriteData{" +
                "fileName='" + fileName + '\'' +
                ", headMap=" + Arrays.toString(headMap) +
                ", dataStrMap=" + Arrays.toString(dataStrMap) +
                ", witdhArray=" + Arrays.toString(witdhArray) +
                ", dataList=" + dataList +
                '}';
    }
}
类2:SimpleWriteData,导出的第2种参数
import java.io.Serializable;
import java.util.List;

public class SimpleWriteData implements Serializable {
    /** 文件名 **/
    private String fileName;
    /** 数据列表 **/
    private List<?> dataList;

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public List<?> getDataList() {
        return dataList;
    }

    public void setDataList(List<?> dataList) {
        this.dataList = dataList;
    }

    @Override
    public String toString() {
        return "SimpleWriteData{" +
                "fileName='" + fileName + '\'' +
                ", dataList=" + dataList +
                '}';
    }
}
 类3:ColumnWidthStyleStrategy :列宽度策略设置
import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.write.style.column.AbstractHeadColumnWidthStyleStrategy;

import java.util.HashMap;
import java.util.Map;

public class ColumnWidthStyleStrategy extends AbstractHeadColumnWidthStyleStrategy {

    private Map<Integer,Integer> columnWidth = new HashMap<>();

    public ColumnWidthStyleStrategy() {
    }

    public ColumnWidthStyleStrategy(int[] widthArray) {
        for (int i = 0; i < widthArray.length; i++) {
            columnWidth.put(i,widthArray[i]);
        }
    }

    @Override
    protected Integer columnWidth(Head head, Integer columnIndex) {
        return columnWidth.getOrDefault(columnIndex,25);
    }
}
 类四:SqlDateConverter:为了 sql.date 类型在excel中显示正常
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;

import java.math.BigDecimal;
import java.sql.Date;
import java.text.ParseException;

/**
 * Date and string converter
 *
 * @author Jiaju Zhuang
 */
public class SqlDateConverter implements Converter<Date> {
    @Override
    public Class<?> supportJavaTypeKey() {
        return Date.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }

    @Override
    public Date convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty,
        GlobalConfiguration globalConfiguration) throws ParseException {
        switch (cellData.getType()) {
            case NUMBER:
                BigDecimal numberValue = cellData.getNumberValue();
                return new Date(numberValue.longValue());
            case STRING:
                String stringValue = cellData.getStringValue();
                if (StrUtil.isBlank(stringValue) || "NA".equals(stringValue)) {
                    return null;
                }
                try {
                    return new Date(DateUtil.parse(cellData.getStringValue()).getTime());
                } catch (NumberFormatException e) {
                    return null;
                }
            default:
                return null;
        }
    }

    @Override
    public WriteCellData<?> convertToExcelData(Date value, ExcelContentProperty contentProperty,
        GlobalConfiguration globalConfiguration) {
        if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) {
            return new WriteCellData<>(DateUtil.formatDate(value));
        } else {
            return new WriteCellData<>(DateUtil.format(value, contentProperty.getDateTimeFormatProperty().getFormat()));
        }
    }
}
类五:SqlTimeConverter :为了 sql.time 类型在excel中显示正常
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.converters.Converter;
import com.alibaba.excel.enums.CellDataTypeEnum;
import com.alibaba.excel.metadata.GlobalConfiguration;
import com.alibaba.excel.metadata.data.ReadCellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.metadata.property.ExcelContentProperty;

import java.math.BigDecimal;
import java.sql.Time;
import java.text.ParseException;

/**
 * Date and string converter
 *
 * @author Jiaju Zhuang
 */
public class SqlTimeConverter implements Converter<Time> {
    @Override
    public Class<?> supportJavaTypeKey() {
        return Time.class;
    }

    @Override
    public CellDataTypeEnum supportExcelTypeKey() {
        return CellDataTypeEnum.STRING;
    }

    @Override
    public Time convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty,
        GlobalConfiguration globalConfiguration) throws ParseException {
        switch (cellData.getType()) {
            case NUMBER:
                BigDecimal numberValue = cellData.getNumberValue();
                return new Time(numberValue.longValue());
            case STRING:
                String stringValue = cellData.getStringValue();
                if (StrUtil.isBlank(stringValue) || "NA".equals(stringValue)) {
                    return null;
                }
                try {
                    return new Time(DateUtil.parseTime(cellData.getStringValue()).getTime());
                } catch (NumberFormatException e) {
                    return null;
                }
            default:
                return null;
        }
    }

    @Override
    public WriteCellData<?> convertToExcelData(Time value, ExcelContentProperty contentProperty,
        GlobalConfiguration globalConfiguration) {
        if (contentProperty == null || contentProperty.getDateTimeFormatProperty() == null) {
            return new WriteCellData<>(DateUtil.formatTime(value));
        } else {
            return new WriteCellData<>(DateUtil.format(value, contentProperty.getDateTimeFormatProperty().getFormat()));
        }
    }
}

4、你可能用到其他教程

1)poi 导出自定义样式excel

springboot、springmvc,excel上传解析、下载excel工具类_mediatype中适合excel-CSDN博客文章浏览阅读376次。工具类共7个方法: /** * 1)对外方法:解析上传的excel,只含一个sheet kly * @example: List strArrayList = ExcelUtil.getExcelData(MultipartFile); */ /** * 2)对外方法:获取第几个sheet页的数据..._mediatype中适合excel[]>https://blog.csdn.net/qq_26408545/article/details/103713665

2)poi 导出word

POI 导出横版A4word,并设置excel宽度(固定不变形)_a4 poi 宽度设置-CSDN博客文章浏览阅读2.6k次,点赞4次,收藏8次。1.maven依赖 org.apache.poipoi3.17 &_a4 poi 宽度设置https://blog.csdn.net/qq_26408545/article/details/110669104

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/461461.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis中的缓存设计

缓存穿透 缓存穿透是指查询一个根本不存在的数据&#xff0c;缓存层和存储层都不会命中&#xff0c;通常处于容错的考虑&#xff0c;如果从存储层查不到数据则不写入缓存层。缓存穿透将导致不存在的数据每次请求都要到存储层去查询&#xff0c;失去了缓存保护后端存储的意义。…

Java两周半速成之路(第十六天)

一、网络编程 1.概述&#xff1a; 就是用来实现网络互连的不同计算机上运行的程序间可以进行数据交换 2.网络模型 3.网络参考模型图 4.网络通信三要素 4.1IP地址 InetAddress类的使用&#xff1a; 注意&#xff1a;通过API查看&#xff0c;此类没有构造方法&#xff0c;如…

精读《精通 console.log》

1 引言 本周精读的文章是 Mastering JS console.log like a Pro&#xff0c;一起来更全面的认识 console 吧&#xff01; 2 概述 & 精读 console 的功能主要在于控制台打印&#xff0c;它可以打印任何字符、对象、甚至 DOM 元素和系统信息&#xff0c;下面一一介绍。 c…

力扣-20. 有效的括号(回顾知识哈希表,栈)

给定一个只包括 ‘(’&#xff0c;‘)’&#xff0c;‘{’&#xff0c;‘}’&#xff0c;‘[’&#xff0c;‘]’ 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 每个右括号都有…

QT中dumpcpp以及dumpdoc使用

qt中调用COM的方式方法有四种&#xff0c;参考解释在 Qt 中使用 ActiveX 控件和 COM (runebook.dev) 介绍dumpcpp的使用方法Qt - dumpcpp 工具 (ActiveQt) (runebook.dev)&#xff1a; 在安装好了的qt电脑上&#xff0c;通过powershell窗口来实现&#xff0c;powershell比cmd要…

C语言从入门到熟悉------第五阶段

结构体 结构体很重要&#xff0c;一定要掌握。但是在很多C语言书籍中结构体的内容讲得非常少&#xff0c;因为从结构体开始&#xff0c;后面介绍的内容已经超出C语言基础的范畴&#xff0c;属于C高级编程部分了。仅仅具备前面的知识是远远不够的&#xff0c;因为在实际编程中&…

#QT(定时轮播电子相册)

1.IDE&#xff1a;QTCreator 2.实验&#xff1a; &#xff08;1&#xff09;使用QOBJECT的TIMER &#xff08;2&#xff09;EVENT时间 &#xff08;3&#xff09;多定时器定时溢出判断 &#xff08;4&#xff09;QLABEL填充图片 3.记录 4.代码 widget.h #ifndef WIDGET_H…

AI - 决策树模型

&#x1f914;决策树算法 决策树的思想来源可以追溯到古希腊时期&#xff0c;当时的哲学家们就已经开始使用类似于决策树的图形来表示逻辑推理过程。然而&#xff0c;决策树作为一种科学的决策分析工具&#xff0c;其发展主要发生在20世纪。 在20世纪50年代&#xff0c;美国兰…

【消息队列开发】 测试MessageFileManager(对硬盘中的消息操作)类

文章目录 &#x1f343;前言&#x1f384;测试流程&#x1f334;准备工作&#x1f332;测试创建队列功能&#x1f333;测试统计文件的读写&#x1f38b;测试将相应消息放入文件中&#x1f38d;测试读文件里的消息到内存&#x1f340;测试删除消息&#x1f60e;测试垃圾回收⭕总…

AtomoVideo:AIGC赋能下的电商视频动效生成

✍&#x1f3fb; 本文作者&#xff1a;凌潼、依竹、桅桔、逾溪 1. 概述 当今电商领域&#xff0c;内容营销的形式正日趋多样化&#xff0c;视频内容以其生动鲜明的视觉体验和迅捷高效的信息传播能力&#xff0c;为商家创造了新的机遇。消费者对视频内容的偏好驱动了视频创意供给…

Yolo系列算法-理论部分-YOLOv3

0. 写在前面 YOLO系列博客&#xff0c;紧接上一篇Yolo系列算法-理论部分-YOLOv2-CSDN博客 1. YOLOv3-定型之作 2018年&#xff0c;Redmon团队推出YOLOv3的网络模型&#xff0c;将骨干网络&#xff08;backbone&#xff09;由darknet-19替换成darknet-53网络&#xff0c;加入特…

【Python循环2/5】for循环的复杂应用

目录 序言 导入1 累加 练习 导入2 计数器 练习 导入3 if判断 总结 序言 昨天&#xff0c;我们学习了 for 循环遍历列表、字典等数据的方式。今天我们会学习&#xff0c;for 循环与“累加” 、if 判断和“计数器”的结合运用。 导入1 在前面的学习中&#xff0c;我们学…

计算机网络——物理层(数据交换方式)

计算机网络——数据交换方式 提高数据交换方式的必要性电路交换电路交换原理电路交换的阶段建立阶段通信阶段和连接拆除阶段 电路交换的优缺点报文交换什么是报文报文交换的阶段报文交换的优缺点 分组交换分组交换的阶段分组交换的优缺点 数据交换方式的选择数据报方式数据报方…

VS Code上,QT基于cmake,qmake的构建方法(非常详细)

VS Code上,QT基于cmake&#xff0c;qmake的构建方法 1 前言2 QT基于cmake的构建方法2.1 VS Code关键插件安装2.2 系统环境变量配置2.3 VS Code中&#xff0c;环境变量配置2.4 Cmake新建一个新的Porject 3 QT基于qmake的构建方法 1 前言 最近&#xff0c;由于认证了github的学生…

尺寸小又薄的整流桥IBS

1. 整流桥功能介绍 整流桥在电子领域中扮演着至关重要的角色&#xff0c;为各种电子设备和电路提供了稳定的电源。整流桥的主要作用是将交流电信号转换为直流电信号。当交流电信号通过整流桥时&#xff0c;它会使得只有一个方向的电流能够通过&#xff0c;从而实现了将交流电信…

【数据结构练习题】栈——1.括号匹配 2.逆波兰表达式求值 3.出栈入栈次序匹配 4.最小栈

♥♥♥♥♥个人主页♥♥♥♥♥ ♥♥♥♥♥数据结构练习题总结专栏♥♥♥♥♥ 文件目录 前言1.括号匹配1.1问题描述1.2解题思路1.3画图解释1.4代码实现2.逆波兰表达式求值 2.1问题描述2.2解题思路2.3画图解释2.4代码解释3.出栈入栈次序匹配 3.1问题描述3.2思路分析3.3画图解释3.…

金融知识分享系列之:MACD指标精讲

金融知识分享系列之&#xff1a;MACD指标精讲 一、MACD指标二、指标原理三、MACD指标参考用法四、MACD计算步骤五、MACD分析要素六、根据快线DIF位置判断趋势七、金叉死叉作为多空信号八、快线位置交叉信号九、指标背离判断行情反转十、差离值的正负十一、差离值的变化十二、指…

KBP210-ASEMI新能源专用整流桥KBP210

编辑&#xff1a;ll KBP210-ASEMI新能源专用整流桥KBP210 型号&#xff1a;KBP210 品牌&#xff1a;ASEMI 封装&#xff1a;KBP-4 正向电流&#xff08;Id&#xff09;&#xff1a;2A 反向耐压&#xff08;VRRM&#xff09;&#xff1a;1000V 正向浪涌电流&#xff1a;6…

中整协与成都艺星联合主办的“面部馒化修复注射技术培训班”圆满落下帷幕

在追求医疗美容学科深度的道路上&#xff0c;Yestar成都艺星再次成为行业先锋&#xff0c;近日&#xff0c;由中整协与成都艺星整形美容医院联合主办的“面部馒化修复注射技术培训班”在Yestar成都艺星圆满落下帷幕。本次培训班以其严谨的学术精神和对临床治疗思路的深入解读&a…

在idea中配置tomcat服务器,部署一个项目(下载教程加链接)

第一步&#xff1a;把Tomcat下载好 ww​​​​​​​Apache Tomcat - Welcome! 链接如上&#xff1a;进去后在左边找到Tomcat8点击进去后 找到图下内容 第二步&#xff1a; 打开这个文件点击bin进去 会出现一个黑色框框&#xff0c;也就是服务器 完成后就可以在浏览器输入…