使用工具类简单快速导出复杂的Excel,以及下载Excel 模板

Gitee 地址如下:

https://gitee.com/xia-lijun/export-Excel.giticon-default.png?t=N7T8https://gitee.com/xia-lijun/export-Excel.git

一:首先引入pom.xml 依赖

        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-web</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>eu.bitwalker</groupId>
            <artifactId>UserAgentUtils</artifactId>
            <version>1.21</version>
        </dependency>
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>2.0</version>
        </dependency>
        <dependency>
			<groupId>org.jsoup</groupId>
			<artifactId>jsoup</artifactId>
			<version>1.12.1</version>
		</dependency>

二:添加工具类

接口

1.ExportedFileNameFactory

public interface ExportedFileNameFactory {
    String getName(Map<String, Object> dataSource);
}

2.TemplateRenderer

public interface TemplateRenderer {
    Writable render(Map<String, Object> dataSource) throws Throwable;
}

3.Writable


public interface Writable {
    void write(OutputStream outputStream) throws IOException;
}
实现类:
AbsExporter
package com.example.demo.demos.exportUtils;



import com.example.demo.demos.exportUtils.interfaceUtils.TemplateRenderer;
import com.example.demo.demos.exportUtils.interfaceUtils.Writable;

import java.io.File;
import java.io.FileOutputStream;
import java.util.Map;

/**
 * @Author 
 * @Date Created in  2024/3/15 16:58
 * @DESCRIPTION:
 * @Version V1.0
 */

public abstract class AbsExporter implements TemplateRenderer {

    public void doExport(Map<String, Object> dataSource, File exportedFile) throws Throwable {
        try(FileOutputStream fos = new FileOutputStream(exportedFile)) {
            Writable writable = this.render(dataSource);
            writable.write(fos);
        }
    }

    public abstract String getTargetFileSuffix();

    public void afterExport() {}

}
ExcelTemplateExporter
package com.example.demo.demos.exportUtils;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import com.example.demo.demos.exportUtils.interfaceUtils.Writable;
import org.apache.poi.ss.usermodel.Workbook;

import java.util.Map;
import java.util.function.Function;

/**
 * @Author 
 * @Date Created in  2024/3/15 17:13
 * @DESCRIPTION:
 * @Version V1.0
 */

public class ExcelTemplateExporter extends AbsExporter{
   private TemplateExportParams templateExportParams;

   private Function<Workbook, Workbook> afterRender;

   public ExcelTemplateExporter(String templateFilename) {
      this(templateFilename, null);
   }

   public ExcelTemplateExporter(String templateFilename, Function<Workbook, Workbook> afterRender) {
      this.templateExportParams = new TemplateExportParams("file/excelTemp/" + templateFilename + ".xlsx");
      this.afterRender = afterRender;
   }

   @Override
   public Writable render(Map<String, Object> dataSource) {
      Workbook workbook = ExcelExportUtil.exportExcel(this.templateExportParams, dataSource);
      if (null == workbook) {
         throw new NullPointerException("workbook 为 null");
      }
      if (this.afterRender != null) {
         workbook = this.afterRender.apply(workbook);
      }
      return new WorkbookWrapper(workbook);
   }

   @Override
   public String getTargetFileSuffix() {
      return ".xlsx";
   }

}
ExportProcess
package com.example.demo.demos.exportUtils;


import com.example.demo.demos.exportUtils.interfaceUtils.ExportedFileNameFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.zip.ZipOutputStream;

/**
 * @Author 
 * @Date Created in  2024/3/15 17:00
 * @DESCRIPTION:
 * @Version V1.0
 */

public class ExportProcess {
    private static final Logger LOGGER = LoggerFactory.getLogger(ExportProcess.class);

    /**
     * 要导出的数据源
     */
    private List<Map<String, Object>> dataSourceList = new ArrayList<>();

    /**
     * 是否为多文件导出
     */
    private boolean multiFile;

    /**
     * 导出器
     */
    private AbsExporter exporter;

    /**
     * 导出文件名
     */
    private String exportedFilename;

    /**
     * 导出为多文件时的文件名命名工厂
     */
    private ExportedFileNameFactory nameFactory;

    private ExportProcess(Map<String, Object> dataSource, AbsExporter exporter, String exportedFilename) {
        this.dataSourceList.add(dataSource);
        this.multiFile = false;
        this.exporter = exporter;
        this.exportedFilename = exportedFilename;
    }

    private ExportProcess(List<Map<String, Object>> dataSourceList, AbsExporter exporter, String exportedFilename, ExportedFileNameFactory nameFactory) {
        this.dataSourceList.addAll(dataSourceList);
        this.multiFile = true;
        this.exporter = exporter;
        this.exportedFilename = exportedFilename;
        this.nameFactory = nameFactory;
    }

    public static ExportProcess newProcess(Map<String, Object> dataSource, AbsExporter exporter, String exportedFilename) {
        return new ExportProcess(dataSource, exporter, exportedFilename);
    }

    public static ExportProcess newProcess(List<Map<String, Object>> dataSourceList, AbsExporter exporter, String exportedFilename, ExportedFileNameFactory nameFactory) {
        return new ExportProcess(dataSourceList, exporter, exportedFilename, nameFactory);
    }

    public ExportResult export() {
        ExportResult exportResult = new ExportResult(this.multiFile ? exportAsZipFile() : exportAsSingleFile());
        this.exporter.afterExport();
        return exportResult;
    }

    /**
     * 导出为单文件
     * @return 导出结果
     */
    private File exportAsSingleFile() {
        Map<String, Object> dataSource = this.dataSourceList.get(0);
        // 导出文件所在目录路径
        String exportedFileDirPath = FileUtils.filePathJoin(FileUtils.TEMP_FILE_PATH, "exportedFileDir" + UUID.randomUUID().toString());
        // 创建导出文件所在目录
        File exportedFileDir = FileUtils.createDir(exportedFileDirPath);
        String exportedFilePath = FileUtils.filePathJoin(exportedFileDirPath, this.exportedFilename + this.exporter.getTargetFileSuffix());
        File exportedFile = new File(exportedFilePath);
        try {
            this.exporter.doExport(dataSource, exportedFile);
            return exportedFile;
        } catch (Throwable t) {
            LOGGER.error(t.getMessage(), t);
            FileUtils.deleteDir(exportedFileDir);
        }
        return null;
    }

    /**
     * 导出为压缩文件
     * @return 导出结果
     */
    private File exportAsZipFile() {
        String tempFileDirPath = FileUtils.filePathJoin(FileUtils.TEMP_FILE_PATH, "tempFile" + UUID.randomUUID().toString());
        File tempFileDir = FileUtils.createDir(tempFileDirPath);
        // 导出文件所在目录路径
        String exportedFileDirPath = FileUtils.filePathJoin(FileUtils.TEMP_FILE_PATH, "exportedFileDir" + UUID.randomUUID().toString());
        // 创建导出文件所在目录
        File exportedFileDir = FileUtils.createDir(exportedFileDirPath);
        File exportedFile = new File(FileUtils.filePathJoin(exportedFileDirPath, this.exportedFilename + ".zip"));
        try {
            for (Map<String, Object> dataSource : this.dataSourceList) {
                this.exporter.doExport(dataSource, new File(FileUtils.filePathJoin(tempFileDirPath, this.nameFactory.getName(dataSource) + this.exporter.getTargetFileSuffix())));
            }
            try (ZipOutputStream out = new ZipOutputStream(new FileOutputStream(exportedFile));
                 BufferedOutputStream bos = new BufferedOutputStream(out)) {
                FileUtils.zipDir(tempFileDirPath, out, bos);
            }
            return exportedFile;
        } catch (Throwable t) {
            LOGGER.error(t.getMessage(), t);
            FileUtils.deleteDir(exportedFileDir);
        } finally {
            FileUtils.deleteDir(tempFileDir);
        }
        return null;
    }
}
ExportResult
package com.example.demo.demos.exportUtils;


import eu.bitwalker.useragentutils.Browser;
import eu.bitwalker.useragentutils.UserAgent;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;

public class ExportResult {

    private static final Logger LOGGER = LoggerFactory.getLogger(ExportResult.class);

    private File exportedFile;

    ExportResult(File exportedFile) {
        this.exportedFile = exportedFile;
    }

    public File getExportedFile() {
        if (null == this.exportedFile) {
            throw new NullPointerException("exportedFile 为 null");
        }
        return exportedFile;
    }

    public void download(HttpServletRequest request, HttpServletResponse response) {
        File exportedFile = getExportedFile();
        // 用于清除首部的空白行
        response.reset();
        response.setContentType("application/x-download; charset=utf-8");
        setFileDownloadHeader(request, response, this.exportedFile.getName());
        doDownload(response, exportedFile);
    }

    private void setFileDownloadHeader(HttpServletRequest request, HttpServletResponse response, String filename) {
        //获取浏览器信息
        String ua = request.getHeader("USER-AGENT");
        //转成UserAgent对象
        UserAgent userAgent = UserAgent.parseUserAgentString(ua);
        //获取浏览器信息
        Browser browser = userAgent.getBrowser();
        //浏览器名称
        String browserName = browser.getName();
        String encodedFilename;
        try {
            encodedFilename = URLEncoder.encode(filename, "UTF8");
            if (StringUtils.contains(browserName, "Internet Explorer")) {
                response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFilename + "\"");
            } else if (StringUtils.contains(browserName, "Chrome") || StringUtils.contains(browserName, "Firefox")) {
                response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedFilename);
            } else {// 其他浏览器
                response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedFilename + "\"");
            }
        } catch (UnsupportedEncodingException e) {
            LOGGER.error(e.getMessage(), e);
        }
    }

    private void doDownload(HttpServletResponse response, File exportedFile) {
        OutputStream os = null;
        byte[] buffer = new byte[1024];
        BufferedInputStream bis = null;
        FileInputStream exportedFileInputStream = null;
        try {
            exportedFileInputStream = new FileInputStream(exportedFile);
            response.addHeader("content-length", exportedFileInputStream.available() + "");
            os = response.getOutputStream();
            bis = new BufferedInputStream(exportedFileInputStream);
            int i = bis.read(buffer);
            while (i != -1) {
                os.write(buffer, 0, i);
                i = bis.read(buffer);
            }
            os.flush();
        } catch (IOException e) {
            LOGGER.error(e.getMessage(), e);
        } finally {
            if (exportedFileInputStream != null) {
                try {
                    exportedFileInputStream.close();
                } catch (IOException e) {
                    LOGGER.error(e.getMessage(), e);
                }
            }
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    LOGGER.error(e.getMessage(), e);
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    LOGGER.error(e.getMessage(), e);
                }
            }
            // 下载完成后删除临时文件
            if (exportedFile.exists()) {
                File exportedFileDir = exportedFile.getParentFile();
                FileUtils.deleteDir(exportedFileDir);
            }
        }
    }
}
FileUtils
package com.example.demo.demos.exportUtils;

import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @Author 
 * @Date Created in  2024/3/15 17:02
 * @DESCRIPTION:
 * @Version V1.0
 */

public class FileUtils {
    static {
        // 当文件系统中没有nhtemp文件夹的时候,创建
        File sf = new File(FileUtils.filePathJoin(System.getProperty("java.io.tmpdir"), "nhtemp"));
        if (!sf.exists()) {
            sf.mkdirs();
        }
    }

    /**
     * 临时文件夹,在临时文件夹中创建nhtemp,用来保存所有使用本工具类创建的文件,以便于统一清空临时文件夹,并且已经包含了文件分割符号,请注意
     */
    public static final String TEMP_FILE_PATH = FileUtils.filePathJoin(System.getProperty("java.io.tmpdir"), "nhtemp");

    /**
     * 向文件写入数据
     *
     * @param is
     * @param file
     * @throws IOException
     */
    public static void writeToFile(InputStream is, File file) throws IOException {
        FileOutputStream fs = null;
        try {
            fs = new FileOutputStream(file);
            byte[] buffer = new byte[1024];
            int byteread = 0;
            while ((byteread = is.read(buffer)) != -1) {
                fs.write(buffer, 0, byteread);
            }
        } catch (IOException e) {
            throw e;
        } finally {
            if (fs != null) {
                fs.close();
            }
            is.close();
        }
    }

    /**
     * 删除文件夹(会删除文件夹下所有的文件)
     *
     * @param dir
     * @return
     */
    public static boolean deleteDir(File dir) {
        if (dir.isDirectory()) {
            String[] children = dir.list();
            //递归删除目录中的子目录下
            for (int i = 0; i < children.length; i++) {
                boolean success = deleteDir(new File(dir, children[i]));
                if (!success) {
                    return false;
                }
            }
        }
        // 目录此时为空,可以删除
        return dir.delete();
    }

    public static File createDir(String dirPath) {
        File dir = new File(dirPath);
        //如果文件夹不存在
        if (!dir.exists()) {
            //创建文件夹
            dir.mkdir();
        }
        return dir;
    }

    public static void zipDir(String directoryName, ZipOutputStream zos, BufferedOutputStream bos) {
        File file = new File(directoryName);
        if (file.exists()) {
            File[] fileList = file.listFiles();
            assert fileList != null;
            for (File f : fileList) {
                // 压缩单个文件到 zos
                String zipName = f.getName();
                try {
                    zos.putNextEntry(new ZipEntry(zipName));
                    int len;
                    FileInputStream is = new FileInputStream(f);
                    BufferedInputStream bis = new BufferedInputStream(is);
                    byte[] bytes = new byte[1024];
                    while ((len = bis.read(bytes)) != -1) {
                        bos.write(bytes, 0, len);

                    }
                    bos.flush();
                    zos.flush();

//                    结束当前压缩文件的添加
                    bis.close();
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();

                }

            }

        }
    }

    /**
     * 路径拼接工具方法
     * @param filePath 文件路径
     * @return 拼接结果
     */
    public static String filePathJoin(String... filePath) {
        return StringUtils.join(filePath, File.separator);
    }

}
VelocityTemplateExporter
package com.example.demo.demos.exportUtils;

import cn.afterturn.easypoi.excel.ExcelXorHtmlUtil;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import com.example.demo.demos.exportUtils.interfaceUtils.Writable;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;

/**
 * @Author 
 * @Date Created in  2024/3/15 17:08
 * @DESCRIPTION:
 * @Version V1.0
 */

public class VelocityTemplateExporter extends AbsExporter{
    private static final Logger LOGGER = LoggerFactory.getLogger(VelocityTemplateExporter.class);

    private String templateFilename;

    public VelocityTemplateExporter(String templateFilename) {
        this.templateFilename = templateFilename;
    }

    @Override
    public String getTargetFileSuffix() {
        return ".xlsx";
    }

    @Override
    public Writable render(Map<String, Object> dataSource) {
        String html = VelocityUtils.render(this.templateFilename + ".vm", dataSource);
        LOGGER.trace("渲染的html为:\n{}", html);
        Workbook workbook = ExcelXorHtmlUtil.htmlToExcel(html, ExcelType.XSSF);
        if (null == workbook) {
            throw new NullPointerException("workbook 为 null");
        }
        return new WorkbookWrapper(workbook);
    }

}
VelocityUtils
package com.example.demo.demos.exportUtils;

import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.exception.VelocityException;

import java.io.StringWriter;
import java.util.Map;
import java.util.Properties;

/**
 * @Author 
 * @Date Created in  2024/3/15 17:09
 * @DESCRIPTION:
 * @Version V1.0
 */

public class VelocityUtils {
    /**
     * 模板文件所在目录
     */
    private static final String TEMPLATE_FILE_DIR = FileUtils.filePathJoin("file", "velocityTemp");

    static {
        //初始化参数
        Properties properties = new Properties();
        //设置 velocity 资源加载方式为 class
        properties.setProperty("resource.loader", "class");
        //设置 velocity 资源加载方式为 class 时的处理类
        properties.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
        // 执行初始化
        Velocity.init(properties);
    }

    /**
     * 渲染对应模板,并输出渲染结果
     * @param templateFileName 模板文件名
     * @param velocityContext 上下文对象,即渲染使用的数据源
     * @return 渲染结果
     */
    public static String render(String templateFileName, VelocityContext velocityContext) throws VelocityException {
        StringWriter writer = new StringWriter();
        Velocity.mergeTemplate(FileUtils.filePathJoin(TEMPLATE_FILE_DIR, templateFileName), "UTF-8", velocityContext, writer);
        return writer.toString();
    }

    /**
     * 渲染对应模板,并输出渲染结果
     * @param templateFileName 模板文件名
     * @param renderDataSource 渲染使用的数据源
     * @return 渲染结果
     */
    public static String render(String templateFileName, Map<String, Object> renderDataSource) throws VelocityException {
        VelocityContext velocityContext = new VelocityContext(renderDataSource);
        return render(templateFileName, velocityContext);
    }

}
WordTemplateExporter
package com.example.demo.demos.exportUtils;

import cn.afterturn.easypoi.word.WordExportUtil;
import com.example.demo.demos.exportUtils.interfaceUtils.Writable;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

import java.util.Map;

/**
 * @Author 
 * @Date Created in  2024/3/15 17:16
 * @DESCRIPTION:
 * @Version V1.0
 */

public class WordTemplateExporter extends AbsExporter{
    private String templateFilePath;

    public WordTemplateExporter(String templateFilename) {
        this.templateFilePath = "file/excelTemp/" + templateFilename + ".docx";
    }

    @Override
    public String getTargetFileSuffix() {
        return ".docx";
    }

    @Override
    public Writable render(Map<String, Object> dataSource) throws Exception {
        XWPFDocument xwpfDocument = WordExportUtil.exportWord07(templateFilePath, dataSource);
        XWPFDocumentWrapper xwpfDocumentWrapper = new XWPFDocumentWrapper(xwpfDocument);
        return xwpfDocumentWrapper;
    }

}
WorkbookWrapper
package com.example.demo.demos.exportUtils;


import com.example.demo.demos.exportUtils.interfaceUtils.Writable;
import org.apache.poi.ss.usermodel.Workbook;

import java.io.IOException;
import java.io.OutputStream;

/**
 * @Author 
 * @Date Created in  2024/3/15 17:12
 * @DESCRIPTION:
 * @Version V1.0
 */

public class WorkbookWrapper implements Writable {
    private Workbook workbook;

    public WorkbookWrapper(Workbook workbook) {
        this.workbook = workbook;
    }

    @Override
    public void write(OutputStream outputStream) throws IOException {
        this.workbook.write(outputStream);
    }

}
XWPFDocumentWrapper
package com.example.demo.demos.exportUtils;


import com.example.demo.demos.exportUtils.interfaceUtils.Writable;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

import java.io.IOException;
import java.io.OutputStream;


/**
 * @Author 
 * @Date Created in  2024/3/15 17:14
 * @DESCRIPTION:
 * @Version V1.0
 */

public class XWPFDocumentWrapper implements Writable {
    private XWPFDocument xwpfDocument;

    public XWPFDocumentWrapper(XWPFDocument xwpfDocument) {
        this.xwpfDocument = xwpfDocument;
    }

    @Override
    public void write(OutputStream outputStream) throws IOException {
        this.xwpfDocument.write(outputStream);
    }

}
注意:

 

vm 文件(自己画Excel  表格)

示例:

遍历:

## 各个列的样式,主要是加上边框
#set($style = 'style="border: 1; height:50;width:12"')
## 方法,如果存在则显示否则显示空
#macro(displayValue $value)
    #if($value)
        $value
    #else
    #end
#end

## sheetName 必须存在
<table sheetName="学生信息">
    <tr>
        <th $style>学号</th>
        <th $style>姓名</th>
        <th $style>年龄</th>
    </tr>
    #foreach($record in $maplist)
        <tr>
            <th $style>$record.xm</th>
            <th $style>$record.xb</th>
            <th $style>$record.age</th>
        </tr>
    #end
</table>

普通的方法:

## 各个列的样式,主要是加上边框
#set($style = 'style="border: 1; height:50;width:12"')
#set($height = 'style="height:30;font-size:9"')
#set($fontSize = 'style="font-size: 20;"')
## 方法,如果存在则显示否则显示空
#macro(displayValue $value)
    #if($value)
        $value
    #else
    #end
#end

## sheetName 必须存在
<table sheetName="2024第一污水处理厂再生水回用年报">
    <tr>
        <th $style colspan="8">日照市污水处理厂再生水供水年报</th>
    </tr>
    <tr>
        <th $style colspan="8">单位:第一污水处理厂       2024</th>
    </tr>
    <tr>
        <th $style>项目</th>
        <th $style rowspan="2">供水量(吨)</th>
        <th $style colspan="5">供水方向</th>
        <th $style rowspan="2">备注</th>
    </tr>
    <tr>
        <th $style>日期</th>
        <th $style>结晶集团</th>
        <th $style>香店河</th>
        <th $style>园林</th>
        <th $style>环卫</th>
        <th $style>其它</th>
    </tr>
    <tr>
        <th $style>1月</th>
        <th $style>$xm</th>
        <th $style>$yx</th>
    </tr>
    <tr>
        <th $style>2月</th>
        <th $style>$xb</th>
    </tr>
    <tr>
        <th $style>3月</th>
        <th $style>$age</th>
    </tr>
    <tr>
        <th $style>4月</th>
        <th $style>$xmm</th>
    </tr>

</table>

三:测试代码

package com.example.demo.demos.controller;


import com.example.demo.demos.exportUtils.ExcelTemplateExporter;
import com.example.demo.demos.exportUtils.ExportProcess;
import com.example.demo.demos.exportUtils.VelocityTemplateExporter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author 
 * @Date Created in  2024/3/15 17:22
 * @DESCRIPTION:
 * @Version V1.0
 */
@RestController
public class ExportController {

    @GetMapping("/test")
    public void exportDownload(HttpServletRequest request, HttpServletResponse response){
        List<Map<String,Object>> list = new ArrayList<>();
        Map<String, Object> map1 = new HashMap<>();
        Map<String, Object> map2 = new HashMap<>();
        Map<String, Object> map3 = new HashMap<>();
        map1.put("yf","1月");
        map1.put("xm","100");
        map1.put("xb","99");
        map1.put("age","33");
        map1.put("yx","33");
        map1.put("bj","33");
        map1.put("qs","33");
        map1.put("cs","33");

        map2.put("yf","2月");
        map2.put("xm","100000");
        map2.put("xb","200000");
        map2.put("age","300000");
        map2.put("yx","300000");
        map2.put("bj","300000");
        map2.put("qs","300000");
        map2.put("cs","300000");

        map3.put("yf","3月");
        map3.put("xm","1");
        map3.put("xb","2");
        map3.put("age","3");
        map3.put("yx","4");
        map3.put("bj","5");
        map3.put("qs","6");
        map3.put("cs","7");

        list.add(map1);
        list.add(map2);
        list.add(map3);
        Map<String, Object> map = new HashMap<>();
        map.put("maplist",list);
        ExportProcess.newProcess(map,new ExcelTemplateExporter("2024第一污水处理厂再生水回用年报"),
                "2024第一污水处理厂再生水回用年报").export().download(request,response);
//        ExportProcess.newProcess(map,new VelocityTemplateExporter("2024第一污水处理厂再生水回用年报"),
//                "2024第一污水处理厂再生水回用年报").export().download(request,response);
    }

    @GetMapping("/exportDownloadTwo")
    public void exportDownloadTwo(HttpServletRequest request, HttpServletResponse response){
        List<Map<String,Object>> list = new ArrayList<>();
        Map<String, Object> map1 = new HashMap<>();
        Map<String, Object> map2 = new HashMap<>();
        Map<String, Object> map3 = new HashMap<>();
        map1.put("xm","100");
        map1.put("xb","99");
        map1.put("age","33");

        map2.put("xm","100000");
        map2.put("xb","200000");
        map2.put("age","300000");

        map3.put("xm","1");
        map3.put("xb","2");
        map3.put("age","3");

        list.add(map1);
        list.add(map2);
        list.add(map3);
        Map<String, Object> map = new HashMap<>();
        map.put("maplist",list);
//        ExportProcess.newProcess(map,new ExcelTemplateExporter("2024第一污水处理厂再生水回用年报"),
//                "2024第一污水处理厂再生水回用年报").export().download(request,response);
        ExportProcess.newProcess(map,new ExcelTemplateExporter("学生"),
                "学生").export().download(request,response);
    }
    @GetMapping("/exportDownloadTTT")
    public void exportDownloadTTT(HttpServletRequest request, HttpServletResponse response){
        List<Map<String,Object>> list = new ArrayList<>();
        Map<String, Object> map1 = new HashMap<>();
        Map<String, Object> map2 = new HashMap<>();
        Map<String, Object> map3 = new HashMap<>();
        map1.put("xm","100");
        map1.put("xb","99");
        map1.put("age","33");

        map2.put("xm","100000");
        map2.put("xb","200000");
        map2.put("age","300000");

        map3.put("xm","1");
        map3.put("xb","2");
        map3.put("age","3");

        list.add(map1);
        list.add(map2);
        list.add(map3);
        Map<String, Object> map = new HashMap<>();
        map.put("maplist",list);
//        ExportProcess.newProcess(map,new ExcelTemplateExporter("2024第一污水处理厂再生水回用年报"),
//                "2024第一污水处理厂再生水回用年报").export().download(request,response);
        ExportProcess.newProcess(map,new VelocityTemplateExporter("2024第一污水处理厂再生水回用年报"),
                "2024第一污水处理厂再生水回用年报").export().download(request,response);
    }
}
第一种测试方法:

表格模板:

导出结果:

 

第二种测试方法:

(简单的这种,还是推荐使用EasyExcel 毕竟代码量少) 

表格模板:

导出结果:

第三种测试方法:

这种需要自己画表格(没画完)

vm 文件:

## 各个列的样式,主要是加上边框
#set($style = 'style="border: 1; height:50;width:12"')
## 方法,如果存在则显示否则显示空
#macro(displayValue $value)
    #if($value)
        $value
    #else
    #end
#end

## sheetName 必须存在
<table sheetName="学生信息">
    <tr>
        <th $style>学号</th>
        <th $style>姓名</th>
        <th $style>年龄</th>
    </tr>
    #foreach($record in $maplist)
        <tr>
            <th $style>$record.xm</th>
            <th $style>$record.xb</th>
            <th $style>$record.age</th>
        </tr>
    #end
</table>

示例:

 

第四种测试方法:

代码:

    @GetMapping("/exportDownloadTTT")
    public void exportDownloadTTT(HttpServletRequest request, HttpServletResponse response){
        Map<String, Object> map = new HashMap<>();
        ExportProcess.newProcess(map,new ExcelTemplateExporter("2024第一污水处理厂再生水回用年报"),
             
    }

导出Excel 模板

还可以导出Word 方法类似;

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

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

相关文章

Linux:Prometheus+Grafana+睿象云告警平台(3)

在上一章我进行了Prometheus和Grafana的基础搭建以及部署 Linux&#xff1a;Prometheus的源码包安装及操作&#xff08;2&#xff09;-CSDN博客https://blog.csdn.net/w14768855/article/details/136855988?spm1001.2014.3001.5501 1.注册 在监控中必不可少的就是监控告警&am…

基于深度学习的心律异常分类系统设计——算法设计

基于深度学习的心律异常分类系统——算法设计 第一章 研究背景算法流程本文研究内容 第二章 心电信号分类理论基础心电信号产生机理MIT-BIH 心律失常数据库 第三章 心电信号预处理心电信号噪声来源与特点基线漂移工频干扰肌电干扰 心电信号读取与加噪基于小波阈值去噪技术的应用…

Linux下Docker部署中间件(Mysql、Redis、Nginx等)

我的自备文件 文件传输 内网下直接上传很慢 使用scp命令将另一台服务器上的文件传输过来&#xff1b;在已有文件的服务器往没有文件的服务器传输 scp -r 传输的文件夹/文件 root要传输的地址:放置的地址 scp -r tools root172.xx.x.xxx:/data/ 安装二进制文件、脚本及各中间件…

ubuntu - 编译 linphone-sdk

业务需求需要定制sdk&#xff0c;首先声明我们需要的是在Android4.4上跑的sdk&#xff0c;因此本次编译的sdk最低支持为19&#xff08;不同版本需要的环境不一致&#xff09;&#xff0c;编译过程较容易&#xff0c;难点在于环境配置 环境准备 Ubuntu 18.04.6 android-sdk_r24.…

机器学习lgbm时间序列预测实战

完整代码&#xff1a; from sklearn import preprocessing import random from sklearn.model_selection import train_test_split from sklearn.preprocessing import MinMaxScaler from sklearn import preprocessing from datetime import datetime import time import mat…

Kafka Consumer 消费消息和 Rebalance 机制

Kafka Consumer Kafka 有消费组的概念&#xff0c;每个消费者只能消费所分配到的分区的消息&#xff0c;每一个分区只能被一个消费组中的一个消费者所消费&#xff0c;所以同一个消费组中消费者的数量如果超过了分区的数量&#xff0c;将会出现有些消费者分配不到消费的分区。消…

探索数据结构:顺序栈与链式栈的原理、实现与应用

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;数据结构与算法 贝蒂的主页&#xff1a;Betty’s blog 1. 栈的定义 栈简单来说就是一种只允许在一端进行操作(插入与删除&…

JNDI注入原理及利用IDEA漏洞复现

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java、PHP】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收…

使用Excel创建高效的库存管理表格及优化技巧

库存管理对于企业和组织来说至关重要。Excel作为一款功能强大且广泛使用的电子表格软件&#xff0c;为库存管理提供了灵活性和可定制性。本文将进一步扩展之前的内容&#xff0c;详细介绍如何使用Excel创建高效的库存管理表格&#xff0c;并提供一些优化技巧&#xff0c;帮助您…

FANUC机器人某个轴编码器损坏时进行单轴零点标定的具体方法

FANUC机器人某个轴编码器损坏时进行单轴零点标定的具体方法 前提: FANUC机器人编码器或其线路有损坏,一般先将机器人移动至零点位置,编码器相关部件更换完毕后,直接进行零点标定即可。但是对于突发的状况,这种方法显然是不行的,比如在生产过程中突然发生碰撞导致编码器相…

【Flutter学习笔记】10.2 组合现有组件

参考资料&#xff1a; 《Flutter实战第二版》 10.2 组合现有组件 在Flutter中页面UI通常都是由一些低级别组件组合而成&#xff0c;当我们需要封装一些通用组件时&#xff0c;应该首先考虑是否可以通过组合其他组件来实现&#xff0c;如果可以&#xff0c;则应优先使用组合&…

就业班 第二阶段 2401--3.19 day2 DDL DML DQL 多表查询

在mysql库里的语句 \G 竖着排列 ; \g 横着排列 数据库用户组成 双单引号单都行 -- sql的注释 创建mysql用户&#xff1a;&#xff08;兼容5.7 8.0 &#xff09; create user root% identified by Qwer123..; grant all on *.* to root%; flush privileges; mysql 5.7 grant …

ubuntu將en01變成eth0的形式

文章目录 前言一、操作步驟1、打開grub文件2、輸入更新指令3、查看結果 二、使用步骤总结 前言 一、操作步驟 1、打開grub文件 使用管理員權限打開&#xff0c;添加新內容 sudo gedit grub2、輸入更新指令 sudo update-grub3、查看結果 使用ifconfig查看是否修改成功&…

Python使用PaddleSpeech实现语音识别(ASR)、语音合成(TTS)

目录 安装 语音识别 补全标点 语音合成 参考 PaddleSpeech是百度飞桨开发的语音工具 安装 注意&#xff0c;PaddleSpeech不支持过高版本的Python&#xff0c;因为在高版本的Python中&#xff0c;飞桨不再提供paddle.fluid API。这里面我用的是Python3.7 需要通过3个pip…

第九节HarmonyOS 常用基础组件31-Toggle

1、描述 组件提供勾选框样式、状态栏样式以及开关样式。 2、子组件 仅当ToggleType为Button时可包含子组件。 3、接口 Toggle(options: { type: ToggleType , isOn?: boolean}) 4、参数 参数名 参数类型 必填 描述 type ToggleType 是 开关的样式。 isOn boole…

ajax重复请求状态为已取消

问题 点击按钮&#xff0c;打开浏览器控制台发现发出了重复请求。 分析&#xff1a; <button onclick"query()">查询</button>错误原因是在form表单中使用了button标签并且增了点击事件&#xff0c;会导致请求被重复发起。 解决办法&#xff1a; &…

Avue框架实现图表的基本知识 | 附Demo(全)

目录 前言1. 柱状图2. 折线图3. 饼图4. 刻度盘6. 仪表盘7. 象形图8. 彩蛋8.1 饼图8.2 柱状图8.3 折线图8.4 温度仪表盘8.5 进度条 前言 以下Demo&#xff0c;作为初学者来说&#xff0c;会相应给出一些代码注释&#xff0c;可相应选择你所想要的款式 对于以下Demo&#xff0c…

填补市场空白,Apache TsFile 如何重新定义时序数据管理

欢迎全球开发者参与到 Apache TsFile 项目中。 刚刚过去的 2023 年&#xff0c;国产开源技术再次获得国际认可。 2023 年 11 月 15 日&#xff0c;经全球最大的开源软件基金会 ASF 董事会投票决议&#xff0c;时序数据文件格式 TsFile 正式通过&#xff0c;直接晋升为 Apache T…

【周赛】第385场周赛

&#x1f525;博客主页&#xff1a; A_SHOWY&#x1f3a5;系列专栏&#xff1a;力扣刷题总结录 数据结构 云计算 数字图像处理 力扣每日一题_ 【1】100212.统计前后缀下标对 100212. 统计前后缀下标对 Ihttps://leetcode.cn/problems/count-prefix-and-suffix-pairs-i/ 熟…

【开源】SpringBoot框架开发知识图谱构建系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 知识图谱模块2.2 知识点模块2.3 学生测评模块2.4 学生成绩模块 三、系统展示四、核心代码4.1 查询知识点4.2 新增知识点4.3 查询知识图谱4.4 查询学生成绩4.5 查询学生成绩 五、免责说明 一、摘要 1.1 项目介绍 基于J…