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,批量生成表格,方便快捷、省心高效,項目經理用了都說好!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM