package com.aomen.java;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Iterator;
import java.util.List;

public class FileTools {

    public static void main(String[] args) {
        FileInputStream in = null;//载入文档
        try {
            // 处理docx格式 即office2007以后版本
            //word 2007 图片不会被读取, 表格中的数据会被放在字符串的最后
            in = new FileInputStream("C:\\work\\test.docx");
            //得到word文档的信息
            XWPFDocument docx = new XWPFDocument(in);
            // 循环所有段落(循环[除表格和图片外的]每一行数据)
            List<XWPFParagraph> paragraphs = docx.getParagraphs();
            for (int i = 0; i < paragraphs.size(); i++) {
                // 插入段落
                insertParagraphs(docx, paragraphs.get(i), "插入的字符串信息");
                // 插入表格
                insertTables(docx, paragraphs.get(i));
                // 插入图片
                insertImages(docx, paragraphs.get(i));
            }
            // 将修改后的文件保存到新的文件内
            FileOutputStream fos = new FileOutputStream("C:\\tes.docx");
            docx.write(fos);
            fos.flush();
            fos.close();
            docx.close();
            in.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 插入图片
     *
     * @param docx
     * @param paragraph
     */
    public static void insertImages(XWPFDocument docx, XWPFParagraph paragraph) {
        String text = paragraph.getText();
        //插入图片
//        判断文档中新增图片的占位符,在此占位符下插入新的图片
        if (text.equals("${mark_newPicture}")) {
            try {
                XmlCursor cursor = paragraph.getCTP().newCursor();
                XWPFParagraph newPara = docx.insertNewParagraph(cursor);
                newPara.setAlignment(ParagraphAlignment.CENTER);//居中
                XWPFRun newParaRun = newPara.createRun();
                newParaRun.addPicture(new FileInputStream("./doc/bus.png"),
                        XWPFDocument.PICTURE_TYPE_PNG, "bus.png,",
                        Units.toEMU(200), Units.toEMU(200));
                docx.removeBodyElement(docx.getPosOfParagraph(paragraph));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (InvalidFormatException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 插入表格
     *
     * @param docx
     * @param paragraph
     */
    public static void insertTables(XWPFDocument docx, XWPFParagraph paragraph) {
        String text = paragraph.getText();
        //插入表格
//        判断文档中新增表格的占位符,在此占位符下插入新的表格
        if (text.equals("${mark_newTable}")) {
            XmlCursor cursor = paragraph.getCTP().newCursor();

            XWPFTable table = docx.insertNewTbl(cursor);
            XWPFTableRow row_0 = table.getRow(0);
            row_0.getCell(0).setText("姓名");
            row_0.addNewTableCell().setText("年龄");

            XWPFTableRow row_1 = table.createRow();
            row_1.getCell(0).setText("隔壁老王");
            row_1.getCell(1).setText("48");

            setTableLocation(table, "center");
            setCellLocation(table, "CENTER", "center");
            docx.removeBodyElement(docx.getPosOfParagraph(paragraph));
        }
    }

    /**
     * 插入段落
     *
     * @param docx
     * @param paragraph
     * @param message   需要插入的内容
     */
    public static void insertParagraphs(XWPFDocument docx, XWPFParagraph paragraph, String message) {
        String text = paragraph.getText();
        //插入段落
//        判断文档中新增段落的占位符,在此占位符下插入新的段落
        if (text.equals("${mark_newParagraph}")) {
            XmlCursor cursor = paragraph.getCTP().newCursor();
            XWPFParagraph newPara = docx.insertNewParagraph(cursor);
            newPara.setAlignment(ParagraphAlignment.BOTH);//两端对齐
            newPara.setIndentationFirstLine(480);//首行缩进24磅
            XWPFRun newParaRun = newPara.createRun();
            newParaRun.setText(message);
            newParaRun.setFontFamily("宋体");
            newParaRun.setFontSize(12);
            newParaRun.setBold(false);
            docx.removeBodyElement(docx.getPosOfParagraph(paragraph));
        }
    }

    /**
     * 指定位置插入(段落/表格/图片)
     * @param docx
     */
    public void insertIndex(XWPFDocument docx){
        XmlCursor cursor = docx.getDocument().getBody().getPArray(0).newCursor();
        // 段落
        XWPFParagraph cP = docx.insertNewParagraph(cursor);
        // 表格
//        XWPFTable table = docx.insertNewTbl(cursor);
        // 图片
//        XWPFParagraph newPara = docx.insertNewParagraph(cursor);
    }

    /**
     * 删除某个表格
     *
     * @param table
     */
    public void deleteTable(XWPFTable table) {
        List<XWPFTableRow> rows = table.getRows();
        // 删除所有行 倒叙删除
        for (int i = rows.size(); i >= 0; i--) {
            System.out.println("table.getRows() " + table.getRows().size());
            table.removeRow(i);
        }
    }

    /**
     * 设置表格的风格样式
     * @param table
     */
    public void editTableStyle(XWPFTable table){
        CTTblPr tblPr1 = table.getCTTbl().getTblPr();
        CTString styleStr = tblPr1.addNewTblStyle();
        // 表格默认为Normal风格
        styleStr.setVal("StyledTable");
    }

    /**
     * 设置表格的宽度
     * @param table
     */
    public void editTableWidth(XWPFTable table){
        CTTblPr tblPr = table.getCTTbl().getTblPr();
//        默认TblW的type属性为STTblWidth.AUTO,即自动伸缩。所以要调整为指定类型:STTblWidth.DXA
        tblPr.getTblW().setType(STTblWidth.DXA);
        // 设置表格的宽度
        tblPr.getTblW().setW(new BigInteger("7000"));
    }

    /**
     * 设置表格行高
     * @param row
     */
    public void editRowHeight(XWPFTableRow row){
        CTTrPr trPr = row.getCtRow().addNewTrPr();
        CTHeight ht = trPr.addNewTrHeight();
//        设置行高
        ht.setVal(BigInteger.valueOf(360));
    }

    /**
     * 设置单元格颜色
     * @param cell
     */
    public void editCellColor(XWPFTableCell cell){
        CTTcPr tcpr = cell.getCTTc().addNewTcPr();
        CTShd ctshd = tcpr.addNewShd();
        ctshd.setColor("auto");
        ctshd.setVal(STShd.CLEAR);
//        设置颜色
        ctshd.setFill("A7BFDE");
    }

    /**
     * 设置单元格内容垂直居中
     * @param cell
     */
    public void editCellCenter(XWPFTableCell cell){
        CTTcPr tcpr = cell.getCTTc().addNewTcPr();
        CTVerticalJc va = tcpr.addNewVAlign();
//        设置垂直居中
        va.setVal(STVerticalJc.CENTER);
    }

    /**
     * 设置单元格的宽度
     * @param cell
     */
    public void editCellWidth(XWPFTableCell cell){
        CTTcPr tcpr = cell.getCTTc().addNewTcPr();
        CTTblWidth cellw = tcpr.addNewTcW();
//        默认type属性为STTblWidth.AUTO,即自动伸缩。所以要调整为指定类型:STTblWidth.DXA
        cellw.setType(STTblWidth.DXA);
        // 设置单元格宽度
        cellw.setW(BigInteger.valueOf(360*5));
    }

    /**
     * 获取所有表格
     * @param docx
     */
    public void getTables(XWPFDocument docx) {
        Iterator<XWPFTable> tables = docx.getTablesIterator();
        while (tables.hasNext()) {
            XWPFTable table = tables.next();
//            获取当前表格所有行
            List<XWPFTableRow> rows = table.getRows();
//            获取当前行的所有列
            List<XWPFTableCell> tableCells = rows.get(0).getTableCells();
        }
    }

    /**
     * 获取所有段落
     * @param docx
     */
    public void getParagraphs(XWPFDocument docx) {
        List<XWPFParagraph> paragraphs = docx.getParagraphs();
//        使用增强for循环会获取不到段落对象
        for (int i = 0; i < paragraphs.size(); i++) {
//            打印当前段落的字符串
            System.out.println(paragraphs.get(i).getText());
        }
    }

    /**
     * 设置单元格水平位置和垂直位置
     *
     * @param xwpfTable
     * @param verticalLoction    单元格中内容垂直上TOP,下BOTTOM,居中CENTER,BOTH两端对齐
     * @param horizontalLocation 单元格中内容水平居中center,left居左,right居右,both两端对齐
     */
    public static void setCellLocation(XWPFTable xwpfTable, String verticalLoction, String horizontalLocation) {
        List<XWPFTableRow> rows = xwpfTable.getRows();
        for (XWPFTableRow row : rows) {
            List<XWPFTableCell> cells = row.getTableCells();
            for (XWPFTableCell cell : cells) {
                CTTc cttc = cell.getCTTc();
                CTP ctp = cttc.getPList().get(0);
                CTPPr ctppr = ctp.getPPr();
                if (ctppr == null) {
                    ctppr = ctp.addNewPPr();
                }
                CTJc ctjc = ctppr.getJc();
                if (ctjc == null) {
                    ctjc = ctppr.addNewJc();
                }
                ctjc.setVal(STJc.Enum.forString(horizontalLocation)); //水平居中
                cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.valueOf(verticalLoction));//垂直居中
            }
        }
    }

    /**
     * 设置表格位置
     *
     * @param xwpfTable
     * @param location  整个表格居中center,left居左,right居右,both两端对齐
     */
    public static void setTableLocation(XWPFTable xwpfTable, String location) {
        CTTbl cttbl = xwpfTable.getCTTbl();
        CTTblPr tblpr = cttbl.getTblPr() == null ? cttbl.addNewTblPr() : cttbl.getTblPr();
        CTJc cTJc = tblpr.addNewJc();
        cTJc.setVal(STJc.Enum.forString(location));
    }

}

作者:怒吼的萝卜