shikeying
2024-01-11 3b67e947e36133e2a40eb2737b15ea375e157ea0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package com.walker.di.excel;
 
import com.alibaba.excel.EasyExcelFactory;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.builder.ExcelWriterBuilder;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.walker.di.AbstractTemplateGenerator;
import com.walker.di.Constants;
import com.walker.di.TemplateException;
import com.walker.infrastructure.utils.FileCopyUtils;
import com.walker.infrastructure.utils.StringUtils;
 
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
 
/**
 * EasyExcel 实现的(导入)模板生成器对象。
 * @author 时克英
 * @date 2023-02-10
 */
public abstract class ExcelTemplateGenerator extends AbstractTemplateGenerator<File> {
 
    @Override
    protected File writeContent(List<Map<String, String>> data, Object option) throws TemplateException {
        logger.debug(data.toString());
        logger.debug(option.toString());
        String templatePath = this.acquireWriteFilePath(option);
        if(StringUtils.isEmpty(templatePath)){
            throw new TemplateException("无法获取模板写入路径: acquireWriteFilePath() = null!", null);
        }
        File templateFile = new File(templatePath);
        logger.info("生成的模板文件:" + templateFile.getAbsolutePath());
 
        InputStream templateFileStream = this.getClass().getClassLoader().getResourceAsStream(Constants.IMPORT_ERROR_FILE_TEMPLATE);
        OutputStream outputStream = null;
        try {
            outputStream = new BufferedOutputStream(new FileOutputStream(templateFile));
            // 根据已有 Excel 模板文件,生成一个新导入模板,这样单元格都是已设置为文本。
            FileCopyUtils.copy(templateFileStream, outputStream);
            // 这里拷贝完模板后,outputStream 已自动关闭,所以需要重新创建新输出流供写入
            outputStream = new BufferedOutputStream(new FileOutputStream(templateFile));
            ExcelWriterBuilder writer = EasyExcelFactory.write(outputStream);
 
            WriteSheet writeSheet = new WriteSheet();
            writeSheet.setSheetName(Constants.EXCEL_SHEET_NAME);
 
            // 仅写入标题头,没有其他内容,data中只有一行数据
            List<List<String>> header = this.getHeader(data);
            writer.head(header);
 
            ExcelWriter excelWriter = writer.build();
 
            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//            List<List<String>> content = new ArrayList<>();
//            List<String> testRow = new ArrayList<>();
//            // 2023-02-07 data集合是每个字段信息,map中只有一个字段:字段id -> 描述
//            for(int i=0; i< data.size(); i++){
//                testRow.add(StringUtils.EMPTY_STRING);
//                logger.debug("写入空列一次:");
//            }
//            logger.debug("data.get(0) = {}", data.get(0));
//            content.add(testRow);
////            content.add(StringUtils.asList(new String[]{"123","shikeying","1233889746596"}));
            // 写入测试数据,否则文档为空。
            excelWriter.write(this.getEmptyRow(data), writeSheet);
 
            // 关闭文件
            excelWriter.finish();
            excelWriter.close();
 
            return templateFile;
 
        } catch (Exception ex){
            throw new TemplateException("写入模板内容错误:" + ex.getMessage() + ", templatePath=" + templatePath, ex);
        } finally {
            if(outputStream != null){
                try {
                    outputStream.close();
                    logger.debug("outputStream 已关闭");
                } catch (IOException e) {}
            }
        }
 
    }
 
    /**
     * 写入一行空数据,否则不能触发Excel写入动作,会导致生成的Excel文件是空的。
     * @param headers
     * @date 2023-02-08
     * @return
     */
    private List<List<String>> getEmptyRow(List<Map<String, String>> headers){
        List<List<String>> content = new ArrayList<>();
        List<String> testRow = new ArrayList<>();
        // 2023-02-07 data集合是每个字段信息,map中只有一个字段:字段id -> 描述
        for(int i=0; i< headers.size(); i++){
            testRow.add(StringUtils.EMPTY_STRING);
//            logger.debug("写入空列一次:");
        }
//        logger.debug("data.get(0) = {}", headers.get(0));
        content.add(testRow);
        return content;
    }
 
    /**
     * 目前仅支持list中第一条数据写入表头,其他行暂不支持。
     * <pre>
     *     1)List 中是多个字段集合
     *     2)Map 中只有一个字段信息,如: id --> 人员编号
     * </pre>
     * @param headers 提供的原始列名称集合
     * @return 返回 EasyExcel 需要用的列集合格式
     */
    private List<List<String>> getHeader(List<Map<String, String>> headers){
//        Map<String, String> map = headers.get(0);
        List<List<String>> headerList = new ArrayList<>();
//        for(Map.Entry<String, String> entry : map.entrySet()){
//            headers.add(StringUtils.asList(new String[]{entry.getValue(), entry.getKey()}));
//        }
        for(Map<String, String> oneFieldInfo : headers){
            // 每个map中只有一个字段
            for(Map.Entry<String, String> entry : oneFieldInfo.entrySet()){
                headerList.add(StringUtils.asList(new String[]{entry.getValue(), entry.getKey()}));
            }
        }
        return headerList;
    }
 
    /**
     * 获取要写入模板文件的具体路径,如: d:/demo/template/123.xlsx
     * @param option
     * @return
     */
    protected abstract String acquireWriteFilePath(Object option);
}