• POI批量生成Word文档表格


      前言

      当我们在写设计文档,或者是其他涉及到数据架构、表结构时,可以用POI来批量生成表格,例如下面的表格

     

      代码编写

      引入POI依赖

            <!-- 引入apache poi -->
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi</artifactId>
                <version>4.0.1</version>
            </dependency>
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi-ooxml</artifactId>
                <version>4.0.1</version>
            </dependency>


      封装两个工具类
      ExcelUtil,POI操作Excel工具类

    import org.apache.poi.hssf.usermodel.*;
    import org.apache.poi.ss.usermodel.*;
    import org.apache.poi.ss.util.CellRangeAddress;
    import org.apache.poi.xssf.usermodel.XSSFRow;
    import org.apache.poi.xssf.usermodel.XSSFSheet;
    import org.apache.poi.xssf.usermodel.XSSFWorkbook;
    import org.springframework.util.StringUtils;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.text.DecimalFormat;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    /**
     * POI操作Excel工具类
     */
    public class ExcelUtil {
    
        /**
         * 读取指定Sheet页的数据
         */
        public static List<Map<String,String>> readExcel3(File file, int sheetIndex) throws Exception {
            try (FileInputStream fs = new FileInputStream(file)) {
                XSSFWorkbook hw = new XSSFWorkbook(fs);
                XSSFSheet sheet = hw.getSheetAt(sheetIndex);
    
                ArrayList<Map<String,String>> list = new ArrayList<>();
    
                //读取表头
                List<String> headerList = new ArrayList<String>();
                XSSFRow headerRow = sheet.getRow(0);
                for (int j = 0; j < headerRow.getLastCellNum(); j++) {
                    String val = getCellValue(headerRow,headerRow.getCell(j));
    
                    //数据为空
                    if (StringUtils.isEmpty(val)) {
                        continue;
                    }
    
                    headerList.add(val);
                }
    
                //读取数据
                for (int i = 1; i < sheet.getPhysicalNumberOfRows(); i++) {
                    XSSFRow dataRow = sheet.getRow(i);
    
                    if (dataRow == null) {
                        continue;
                    }
    
                    HashMap<String, String> map = new HashMap<>();
                    for (int j = 0; j < headerList.size(); j++) {
                        String header = headerList.get(j);
                        String val = getCellValue(dataRow,dataRow.getCell(j));
                        map.put(header, val);
                    }
                    list.add(map);
                }
                return list;
            }
        }
    
        /**
         * 获取单元格内容
         */
        private static String getCellValue(XSSFRow dataRow, Cell cell){
            String cellvalue = "";
            if (cell!=null) {
                switch (cell.getCellType()) {
                    case BOOLEAN:
                        cellvalue = String.valueOf(cell.getBooleanCellValue());
                        break;
                    case NUMERIC:
                        cellvalue = String.valueOf(cell.getNumericCellValue()).split("\.")[0];
                        if(cellvalue.toLowerCase().contains("e")){
                            cellvalue = new DecimalFormat("#").format(cell.getNumericCellValue());
                            if(cellvalue.toLowerCase().contains("e")){
                                throw new RuntimeException(dataRow.getCell(4) + "/数值带E!!!");
                            }
                        }
                        break;
                    case STRING:
                        cellvalue = cell.getStringCellValue();
                        break;
                    case BLANK:
                        break;
                    case ERROR:
                        cellvalue = String.valueOf(cell.getErrorCellValue());
                        break;
                    case FORMULA:
                        try {
                            cellvalue = String.valueOf(cell.getNumericCellValue());
                        } catch (IllegalStateException e) {
                            if (e.getMessage().contains("from a STRING cell")) {
                                try {
                                    cellvalue = String.valueOf(cell.getStringCellValue());
                                } catch (IllegalStateException e2) {
                                    throw new RuntimeException("公式计算出错");
                                }
                            }
                        }
                        break;
                    default:
                        cellvalue = String.valueOf(cell.getBooleanCellValue());
                        break;
                }
            }
            return cellvalue;
        }
    
    
        /**
         * 只支持一级表头
         *
         * @param file   文件
         * @param titleName   表标题
         * @param columnNames 列名集合,key是用来设置填充数据时对应单元格的值,label就是对应的列名,生成Excel表时,
         *                    第一维数组下标0对应值为Excel表最左边的列的列名 例:{ { key,label },{ key,label } }
         * @param dataLists   数据集合,key对应的是列名集合的key,value是要填充到单元格的值 例:ArrayList<HashMap<String key, String vaule>>
         */
        public static String createExcelFile(File file,String titleName, String[][] columnNames, ArrayList<HashMap<String, String>> dataLists) {
    
            //创建HSSFWorkbook对象(excel的文档对象)
            HSSFWorkbook wb = new HSSFWorkbook();
            //建立新的sheet对象(excel的表单)
            HSSFSheet sheet = wb.createSheet(titleName);//设置表单名
    
            //1、标题名
            //创建标题行,参数为行索引(excel的行),可以是0~65535之间的任何一个
            HSSFRow row1 = sheet.createRow(0);
    
            createCell(row1, 0, titleName);
            //合并单元格CellRangeAddress构造参数依次表示起始行,截至行,起始列, 截至列
            sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, columnNames.length - 1));
    
            //2、列名
            //创建列名行
            HSSFRow row2 = sheet.createRow(1);
            for (int i = 0; i < columnNames.length; i++) {
                //单元格宽度
                sheet.setColumnWidth(i, 20 * 256);
                createCell(row2, i, columnNames[i][1]);//例:[[key,label],[key,label]] 取label
            }
    
            //3、填充数据
            int index = 2;//标题行、列名行,所以数据行默认从第三行开始
            for (HashMap<String, String> map : dataLists) {
                //创建内容行
                HSSFRow row3 = sheet.createRow(index);
                for (int i = 0; i < columnNames.length; i++) {
                    String val = map.get(columnNames[i][0]);
                    createCell(row3, i, val == null ? "" : val);//例:[[key,label],[key,label]] 取key
                }
                index++;
            }
    
            try(FileOutputStream outputStream = new FileOutputStream(file)) {
                wb.write(outputStream);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            return file.getName()+" 创建成功";
        }
    
        /**
         * 创建一个单元格
         */
        private static void createCell(Row row, int column, String text) {
            Cell cell = row.createCell(column);  // 创建单元格
            cell.setCellValue(text);  // 设置值
        }
    }


      WordUtil,POI操作Word工具类

    import org.apache.poi.xwpf.usermodel.*;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
    
    import java.math.BigInteger;
    import java.util.List;
    import java.util.Map;
    
    /**
     * POI操作Word工具类
     */
    public class WordUtil {
    
        /**
         * 简单表格生成
         * @param xdoc XWPFDocument对象
         * @param titles 表头表头
         * @param values 表内容
         */
        public static void createSimpleTable(XWPFDocument xdoc,String[] titles,List<Map<String, String>> values){
            //行高
            int rowHeight = 300;
    
            //开始创建表格(默认有一行一列)
            XWPFTable xTable = xdoc.createTable();
            CTTbl ctTbl = xTable.getCTTbl();
            CTTblPr tblPr = ctTbl.getTblPr() == null ? ctTbl.addNewTblPr() : ctTbl.getTblPr();
            CTTblWidth tblWidth = tblPr.isSetTblW() ? tblPr.getTblW() : tblPr.addNewTblW();
            tblWidth.setType(STTblWidth.DXA);
            tblWidth.setW(new BigInteger("8600"));//表格宽度
    
            // 创建表头数据
            XWPFTableRow titleRow = xTable.getRow(0);
            titleRow.setHeight(rowHeight);
            for (int i = 0; i < titles.length; i++) {
                setCellText(i == 0 ? titleRow.getCell(0) :titleRow.createCell(), titles[i]);
            }
    
            // 创建表格内容
            for (int i = 0; i < values.size(); i++) {
                Map<String, String> stringStringMap = values.get(i);
    
                //设置列内容
                XWPFTableRow row = xTable.insertNewTableRow(i + 1);
                row.setHeight(rowHeight);
                for (String title : titles) {
                    setCellText(row.createCell(), stringStringMap.get(title));
                }
            }
        }
    
        /**
         * 设置列内容
         */
        private static void setCellText(XWPFTableCell cell,String text) {
            CTTc cttc = cell.getCTTc();
            CTTcPr cellPr = cttc.addNewTcPr();
            cellPr.addNewTcW().setW(new BigInteger("2100"));
            cell.setColor("FFFFFF");
            cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
            CTTcPr ctPr = cttc.addNewTcPr();
            ctPr.addNewVAlign().setVal(STVerticalJc.CENTER);
            cttc.getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);
            cell.setText(text);
        }
    }

      首先写sql脚本,查出所有表结构信息(表名称、表注释、表字段数据等)

        -- mysql查询表名、表注释、表字段数据
        SELECT
            t.table_name AS '表名称',
            t.table_comment AS '表注释',
            c.column_name AS '字段名称',
            c.column_type AS '数据类型',
            c.column_comment AS '字段注释',
            c.column_key AS '是否主键',
            c.is_nullable AS '是否允许NULL'
        FROM
            information_schema.COLUMNS c
            JOIN information_schema.TABLES t ON c.table_name = t.table_name
        WHERE
            c.table_schema = (
        SELECT DATABASE
            ());

      把结果集拷贝到Excel中

      前期工作准备完毕,接下来开始干正事

    import org.apache.poi.xwpf.usermodel.XWPFDocument;
    import org.apache.poi.xwpf.usermodel.XWPFParagraph;
    import org.apache.poi.xwpf.usermodel.XWPFRun;
    
    import java.io.File;
    import java.io.FileOutputStream;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    public class Test {
    
        private static void tables(){
            try {
                XWPFDocument xdoc = new XWPFDocument();
                HashMap<String, List<Map<String, String>>> hashMap = new HashMap<>();
    
                //获取数据
                /*
                    -- mysql查询表名、表注释、表字段数据
                    SELECT
                        t.table_name AS '表名称',
                        t.table_comment AS '表注释',
                        c.column_name AS '字段名称',
                        c.column_type AS '数据类型',
                        c.column_comment AS '字段注释',
                        c.column_key AS '是否主键',
                        c.is_nullable AS '是否允许NULL'
                    FROM
                        information_schema.COLUMNS c
                        JOIN information_schema.TABLES t ON c.table_name = t.table_name
                    WHERE
                        c.table_schema = (
                    SELECT DATABASE
                        ());
                 */
                File file = new File("E:\TestExcel01.xlsx");
                List<Map<String, String>> list = ExcelUtil.readExcel3(file, 0);
    
                //处理数据,调整成下面的格式
                /*
                    [
                        {"表名称":[
                            {},//一条条字段信息
                            {},//一条条字段信息
                            {},//一条条字段信息
                        ]}
                    ]
                 */
                ArrayList<Map<String, String>> arrayList = new ArrayList<>();
                String tableName = "";
                for (int i = 0; i < list.size(); i++) {
                    Map<String, String> map = list.get(i);
                    String tName = String.valueOf(map.get("表名称"));
                    if(tableName.equals(tName)){
                        arrayList.add(map);
                    }else{
                        hashMap.put(tableName,arrayList);
                        tableName = tName;
                        arrayList = new ArrayList<>();
                        arrayList.add(map);
                    }
    
                    if(list.size() - i == 1){
                        hashMap.put(tableName,arrayList);
                    }
                }
    
    
                //生成内容
                for (String tName : hashMap.keySet()) {
                    if("".equals(tName)){
                        continue;
                    }
                    List<Map<String, String>> maps = hashMap.get(tName);
                    String tZs = String.valueOf(maps.get(0).get("表注释"));
    
                    //设置文字,对表格进行描述
                    XWPFParagraph xp = xdoc.createParagraph();
                    xp.setSpacingBefore(0);
                    XWPFRun r1 = xp.createRun();
                    r1.setFontFamily("宋体");
                    r1.setFontSize(12);
                    r1.setTextPosition(0);
    
                    r1.addBreak(); // 换行
                    r1.setText("表名称:"+tName);
                    r1.addBreak(); // 换行
                    r1.setText("表注释:"+tZs);
    
    
                    //表格标题
                    String[] titles = {
                            "字段名称",
                            "字段类型",
                            "字段注释",
                            "允许空值",
                    };
    
                    //表格内容
                    List<Map<String, String>> values = new ArrayList<>();
                    for (Map<String, String> stringStringMap : maps) {
                        String cName = stringStringMap.get("字段名称");
                        String cType = stringStringMap.get("数据类型");
                        String cZs = stringStringMap.get("字段注释");
                        String isPri = stringStringMap.get("是否主键");
                        String isNull = stringStringMap.get("是否允许NULL");
    
                        //按照表格标题格式进行封装
                        HashMap<String, String> stringStringHashMap = new HashMap<>();
                        stringStringHashMap.put("字段名称",cName);
                        stringStringHashMap.put("字段类型",cType);
                        stringStringHashMap.put("字段注释",cZs);
                        stringStringHashMap.put("允许空值",isNull);
    
                        values.add(stringStringHashMap);
                    }
    
    
                    WordUtil.createSimpleTable(xdoc, titles, values);
                }
    
                //保存word文件
                FileOutputStream fos = new FileOutputStream("E:\Test1.doc");
                xdoc.write(fos);
                fos.close();
    
                System.out.println("操作完成!");
    
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            tables();
        }
    }


      运行main进行测试

        public static void main(String[] args) {
            tables();
        }

      效果

       后记

      通过使用POI,批量生成表格,方便快捷、省心高效,项目经理用了都说好!

    版权声明

    作者:huanzi-qch
    若标题中有“转载”字样,则本文版权归原作者所有。若无转载字样,本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利.


    捐献、打赏

    请注意:作者五行缺钱,如果喜欢这篇文章,请随意打赏!

    支付宝

    微信


    QQ群交流群

    QQ群交流群
    有事请加群,有问题进群大家一起交流!

  • 相关阅读:
    Opencv3.4:显示一张图片
    Windows编译Opencv
    FFmpeg4.0笔记:rtsp2rtmp
    FFmpeg4.0笔记:file2rtmp
    Ubuntu编译安装crtmp-server
    python笔记:#014#综合应用
    python笔记:#012#函数
    Python学习--利用scapy库实现ARP欺骗
    metasploit——(三)渗透攻击之旅
    metasploit——(一)情报收集篇
  • 原文地址:https://www.cnblogs.com/huanzi-qch/p/14959221.html
Copyright © 2020-2023  润新知