Android word document poi form paragraph usage records

Requirements: Based on the data, the Android side generates a word and saves it locally.
After checking some information, it seems that Android does not have a formal word operation library, which is basically implemented with Java API and Apache POI, but this version is more compatible with Android. , There are a lot of pitfalls...
Here, you need word to operate radar charts, line charts, histograms, etc., you need POI4. ...), there is no way to use the 3.x version, let's talk about the chart...

1.gradle depends on POI

app directory build.gradle, add complete dependencies:


dependencies {
    
    
	...
    implementation group: 'org.apache.poi', name: 'poi-ooxml', version: '3.17'
    implementation group: 'org.apache.xmlbeans', name: 'xmlbeans', version: '3.1.0'
    implementation 'javax.xml.stream:stax-api:1.0'
    implementation 'com.fasterxml:aalto-xml:1.2.2'
    ...
    }
2. Add a new paragraph
		/**
     * 添加段落内容
     *
     * @param document   word文档对象 XWPFDocument document = new XWPFDocument()
     * @param fontSize   字体大小
     * @param fontFamily 字体类型
     * @param text       标题
     */
    public static void addParagraph(XWPFDocument document, int fontSize, String fontFamily, String text) {
    
    
    	//创建空白word文档
		//XWPFDocument document = new XWPFDocument()
        XWPFParagraph paragraph = document.createParagraph();
        //内容左对齐
        paragraph.setAlignment(ParagraphAlignment.valueOf(STJc.INT_LEFT));
        XWPFRun run = paragraph.createRun();
        run.setFontSize(13);
        run.setFontFamily("黑体");
        run.addTab();
        run.setText(text);
        run.addBreak();
    }
3. Add a new form
  • document.createTable(1, 2);
    Create a table with 1 row and 2 columns
    table.getRow(0).getCell(0).setText()
    table.getRow(0).getCell(1).setText()
  • document.createTable();
    Create 1 row and 1 column by default
    table.getRow(0).getCell(0).setText()
    table.getRow(0).addNewTableCell().setText()

 /**
     * 添加表格
     * XWPFDocument document = new XWPFDocument()
     *
     * @param document word文档对象.
     */
    public static void addTable(XWPFDocument document) {
    
    
        //创建表格 1行  list.size 列
        //XWPFTable table = document.createTable(1, 2);
        XWPFTable table = document.createTable();

        CTTbl tTbl = table.getCTTbl();
        CTTblPr tTblPr = tTbl.getTblPr() == null ? tTbl.addNewTblPr() : tTbl.getTblPr();
        CTTblWidth tblWidth = tTblPr.isSetTblW() ? tTblPr.getTblW() : tTblPr.addNewTblW();

        //设置表格宽度
        tblWidth.setType(STTblWidth.DXA);
        tblWidth.setW(new BigInteger("8000"));

        table.getRow(0).setHeight(1000);
        //第一列
        setCellStr(table.getRow(0).getCell(0), "主题一", 3000);
        //setCellStr(table.getRow(0).getCell(1), "孤勇者-陈奕迅", 5000);
        //第二列
        setCellStr(table.getRow(0).addNewTableCell(), "孤勇者-陈奕迅", 5000);

        XWPFTableRow row_1 = table.createRow();
        row_1.setHeight(1000);
        setCellStr(row_1.getCell(0), "主题二", 3000);
        setCellStr(row_1.getCell(1), "再回首-岩贵|再回首恍然如梦", 5000);

        XWPFTableRow row_2 = table.createRow();
        row_2.setHeight(1000);
        setCellStr(row_2.getCell(0), "主题三", 3000);
        setCellStr(row_2.getCell(1), "光辉岁月-黄家驹", 5000);
    }

Set the cell properties
and pay attention to horizontal centering: this is a bit of a pit, and it is much worse. It is all ctTc.getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);, because the version problem needs to be changed into ctTc.getPArray()[0].addNewPPr().addNewJc().setVal(STJc.CENTER);, the compilation does not report an error, and the method cannot be found once it is run. You click on the key code and there is this method...

private static void setCellStr(XWPFTableCell cell, String str, int w) {
    
    

        CTTc ctTc = cell.getCTTc();
        CTTcPr ctTcPr = ctTc.addNewTcPr();
        ctTcPr.addNewTcW().setW(BigInteger.valueOf(w));
        //上下居中
        cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
        //水平居中
        //ctTc.getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);
        ctTc.getPArray()[0].addNewPPr().addNewJc().setVal(STJc.CENTER);
        cell.setText(str);
    }
4. Generate a new word according to the template

I put the template in the assets directory, and then judge whether the field contains $. Then replace it with what we need.
insert image description here

4.1 Replacing paragraphs
/**
     * 替换段落文本
     *
     * @param document docx解析对象
     * @param textMap  需要替换的信息集合
     */
    public static void changeText(XWPFDocument document, Map<String, String> textMap) {
    
    
        //获取段落集合
        List<XWPFParagraph> paragraphs = document.getParagraphs();

        for (XWPFParagraph paragraph : paragraphs) {
    
    
            //判断此段落时候需要进行替换
            String text = paragraph.getText();
            Log.i(TAG, "changeText:行 " + text);
            if (text.contains("$")) {
    
    
                List<XWPFRun> runs = paragraph.getRuns();
                for (XWPFRun run : runs) {
    
    
                    //替换模板原来位置
                    Log.i(TAG, "changeText:行内 " + run.getText(run.getTextPosition()));
                    run.setText(changeValue(run.toString(), textMap), 0);
                }
            }
        }

    }
4.2 Substitution Form
  /**
     * 替换表格对象方法
     *
     * @param document docx解析对象
     * @param textMap  需要替换的信息集合
     */
    public static void changeTable(XWPFDocument document, Map<String, String> textMap) {
    
    
        //获取表格对象集合
        List<XWPFTable> tables = document.getTables();

        for (int i = 0; i < tables.size(); i++) {
    
    
            Log.i(TAG, "changeTable: 1" + tables.get(i).getText());
            //只处理行数大于等于2的表格,且不循环表头
            XWPFTable table = tables.get(i);
            if (table.getRows().size() > 1) {
    
    
                //判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
                if (table.getText().contains("$")) {
    
    
                    List<XWPFTableRow> rows = table.getRows();
                    //遍历表格,并替换模板
                    eachTable(rows, textMap);
                }
            }
        }
    }
5. Complete tool code
public class PoiWordUtils {
    
    

    private static final String TAG = "";

    /**
     * 添加段落标题
     *
     * @param document   word文档对象 XWPFDocument document = new XWPFDocument()
     * @param fontSize   字体大小
     * @param fontFamily 字体类型
     * @param isBreak    是否换行
     * @param title      标题
     */
    public static void addParagraphTitle(XWPFDocument document, int fontSize, String fontFamily, boolean isBreak, int gravity, String title) {
    
    
        XWPFParagraph paragraph = document.createParagraph();
        //设置段落居中 / STJc.INT_LEFT - STJc.INT_RIGHT
        paragraph.setAlignment(ParagraphAlignment.valueOf(gravity));
        //行间距
        //paragraph.setSpacingBefore(1);
        XWPFRun run = paragraph.createRun();
        run.setFontSize(fontSize);
        run.setFontFamily("宋体");
        run.setBold(true);
        run.setText(title);
        //换行
        if (isBreak)
            run.addBreak();

        run.addTab();
    }

    /**
     * 添加段落内容
     *
     * @param document   word文档对象 XWPFDocument document = new XWPFDocument()
     * @param fontSize   字体大小
     * @param fontFamily 字体类型
     * @param text       标题
     */
    public static void addParagraph(XWPFDocument document, int fontSize, String fontFamily, String text) {
    
    

        XWPFParagraph paragraph = document.createParagraph();
        //内容左对齐
        paragraph.setAlignment(ParagraphAlignment.valueOf(STJc.INT_LEFT));
        XWPFRun run = paragraph.createRun();
        run.setFontSize(13);
        run.setFontFamily("黑体");
        run.addTab();
        run.setText(text);
        run.addBreak();
    }


    /**
     * 添加表格
     * XWPFDocument document = new XWPFDocument()
     *
     * @param document word文档对象.
     */
    public static void addTable(XWPFDocument document) {
    
    
        //创建表格 1行  list.size 列
        //XWPFTable table = document.createTable(1, 2);
        XWPFTable table = document.createTable();

        CTTbl tTbl = table.getCTTbl();
        CTTblPr tTblPr = tTbl.getTblPr() == null ? tTbl.addNewTblPr() : tTbl.getTblPr();
        CTTblWidth tblWidth = tTblPr.isSetTblW() ? tTblPr.getTblW() : tTblPr.addNewTblW();

        //设置表格宽度
        tblWidth.setType(STTblWidth.DXA);
        tblWidth.setW(new BigInteger("8000"));


        table.getRow(0).setHeight(1000);
        //第一列
        setCellStr(table.getRow(0).getCell(0), "主题一", 3000);
        //第二列
        //setCellStr(table.getRow(0).getCell(1), "孤勇者-陈奕迅", 5000);
        setCellStr(table.getRow(0).addNewTableCell(), "孤勇者-陈奕迅", 5000);

        XWPFTableRow row_1 = table.createRow();
        row_1.setHeight(1000);
        setCellStr(row_1.getCell(0), "主题二", 3000);
        setCellStr(row_1.getCell(1), "再回首-岩贵|再回首恍然如梦", 5000);

        XWPFTableRow row_2 = table.createRow();
        row_2.setHeight(1000);
        setCellStr(row_2.getCell(0), "主题三", 3000);
        setCellStr(row_2.getCell(1), "光辉岁月-黄家驹", 5000);
    }


    private static void setCellStr(XWPFTableCell cell, String str, int w) {
    
    

        CTTc ctTc = cell.getCTTc();
        CTTcPr ctTcPr = ctTc.addNewTcPr();
        ctTcPr.addNewTcW().setW(BigInteger.valueOf(w));
        //上下居中
        cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
        //水平居中
        //ctTc.getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);
        ctTc.getPArray()[0].addNewPPr().addNewJc().setVal(STJc.CENTER);
        cell.setText(str);
    }


/**-----------------------------------------模版相关---------------------------------------------**/


    /**
     * 根据模板生成新word文档
     * 判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
     *
     * @param inputUrl  模板存放地址
     * @param outputUrl 新文档存放地址
     * @param textMap   需要替换的信息集合
     * @return 成功返回true, 失败返回false
     */
    public static boolean changWord(String inputUrl, String outputUrl,
                                    Map<String, String> textMap) {
    
    

        //模板转换默认成功
        boolean changeFlag = true;
        try {
    
    
            //获取docx解析对象
            XWPFDocument document = new XWPFDocument(POIXMLDocument.openPackage(inputUrl));
            //解析替换文本段落对象
            changeText(document, textMap);
            //解析替换表格对象
            changeTable(document, textMap);
            //生成新的word
            File file = new File(outputUrl);
            FileOutputStream stream = new FileOutputStream(file);
            document.write(stream);
            stream.close();

        } catch (IOException e) {
    
    
            e.printStackTrace();
            changeFlag = false;
        }

        return changeFlag;

    }


    public static boolean changWord(InputStream is, String outputUrl,
                                    Map<String, String> textMap) {
    
    

        //模板转换默认成功
        boolean changeFlag = true;
        try {
    
    
            //获取docx解析对象
            XWPFDocument document = new XWPFDocument(is);
            //解析替换文本段落对象
            changeText(document, textMap);
            //解析替换表格对象
            changeTable(document, textMap);
            //生成新的word
            File file = new File(outputUrl);
            FileOutputStream stream = new FileOutputStream(file);
            document.write(stream);
            stream.close();

        } catch (IOException e) {
    
    
            e.printStackTrace();
            changeFlag = false;
        }

        return changeFlag;

    }


    /**
     * 替换段落文本
     *
     * @param document docx解析对象
     * @param textMap  需要替换的信息集合
     */
    public static void changeText(XWPFDocument document, Map<String, String> textMap) {
    
    
        //获取段落集合
        List<XWPFParagraph> paragraphs = document.getParagraphs();

        for (XWPFParagraph paragraph : paragraphs) {
    
    
            //判断此段落时候需要进行替换
            String text = paragraph.getText();
            Log.i(TAG, "changeText:行 " + text);
            if (text.contains("$")) {
    
    
                List<XWPFRun> runs = paragraph.getRuns();
                for (XWPFRun run : runs) {
    
    
                    //替换模板原来位置
                    Log.i(TAG, "changeText:行内 " + run.getText(run.getTextPosition()));
                    run.setText(changeValue(run.toString(), textMap), 0);
                }
            }
        }

    }

    /**
     * 替换表格对象方法
     *
     * @param document docx解析对象
     * @param textMap  需要替换的信息集合
     */
    public static void changeTable(XWPFDocument document, Map<String, String> textMap) {
    
    
        //获取表格对象集合
        List<XWPFTable> tables = document.getTables();

        for (int i = 0; i < tables.size(); i++) {
    
    
            Log.i(TAG, "changeTable: 1" + tables.get(i).getText());
            //只处理行数大于等于2的表格,且不循环表头
            XWPFTable table = tables.get(i);
            if (table.getRows().size() > 1) {
    
    
                //判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
                if (table.getText().contains("$")) {
    
    
                    List<XWPFTableRow> rows = table.getRows();
                    //遍历表格,并替换模板
                    eachTable(rows, textMap);
                }
            }
        }
    }


    /**
     * 遍历表格
     *
     * @param rows    表格行对象
     * @param textMap 需要替换的信息集合
     */
    public static void eachTable(List<XWPFTableRow> rows, Map<String, String> textMap) {
    
    
        for (XWPFTableRow row : rows) {
    
    
            List<XWPFTableCell> cells = row.getTableCells();
            for (XWPFTableCell cell : cells) {
    
    
                Log.i(TAG, "eachTable: 2 " + cell.getText());
                //判断单元格是否需要替换
                if (cell.getText().contains("$")) {
    
    
                    List<XWPFParagraph> paragraphs = cell.getParagraphs();
                    for (XWPFParagraph paragraph : paragraphs) {
    
    
                        Log.i(TAG, "eachTable: 3" + paragraph.getText());
                        List<XWPFRun> runs = paragraph.getRuns();
                        for (XWPFRun run : runs) {
    
    
                            Log.i(TAG, "eachTable: 4 " + run.getText(run.getTextPosition()));
                            run.setText(changeValue(run.toString(), textMap), 0);
                        }
                    }
                }
            }
        }
    }

    /**
     * 匹配传入信息集合与模板
     *
     * @param value   模板需要替换的区域
     * @param textMap 传入信息集合
     * @return 模板需要替换区域信息集合对应值
     */
    public static String changeValue(String value, Map<String, String> textMap) {
    
    
        Set<Map.Entry<String, String>> textSets = textMap.entrySet();
        for (Map.Entry<String, String> textSet : textSets) {
    
    
            //匹配模板与替换值 格式${key}
            String key = "${" + textSet.getKey() + "}";
            if (value.contains(key)) {
    
    
                value = textSet.getValue();
            }
        }
        //模板未匹配到区域替换为空
        if (value.contains("$")) {
    
    
            value = "";
        }
        return value;
    }
}

6. Test

Create blank word, write title paragraphs, tables

String path = FileUtils.getAppRootPth(this) + File.separator + "word"
                + File.separator + "测试3.100.docx";

        try (XWPFDocument document = new XWPFDocument(); FileOutputStream fos = new FileOutputStream(path)) {
    
    
            //标题
            PoiWordUtils.addParagraphTitle(document, 20, null,true,STJc.INT_CENTER, "POI段落标题");
            //小标题
            PoiWordUtils.addParagraphTitle(document, 15, null,false,STJc.INT_LEFT, "一丶内容示例");
            //段落
            PoiWordUtils.addParagraph(document, -1, null, "POI是Apache软件" +
                    "基金会用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程序对Microsoft" +
                    " Office格式档案读和写的功能。POI为“Poor Obfuscation Implementation”的首字母缩写," +
                    "意为“简洁版的模糊实现”。\n" +
                    "所以POI的主要功能是可以用Java操作Microsoft Office的相关文件,但是一般我们都是用来操作" +
                    "Excel相关文件。");
            PoiWordUtils.addParagraph(document, -1, null, "POI是Apache软件" +
                    "基金会用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程序对Microsoft" +
                    " Office格式档案读和写的功能。POI为“Poor Obfuscation Implementation”的首字母缩写," +
                    "意为“简洁版的模糊实现”。\n" +
                    "所以POI的主要功能是可以用Java操作Microsoft Office的相关文件,但是一般我们都是用来操作" +
                    "Excel相关文件。");
            PoiWordUtils.addParagraphTitle(document, 15, null,false,STJc.INT_LEFT, "二丶内容示例");
            PoiWordUtils.addParagraph(document, -1, null, "POI是Apache软件" +
                    "基金会用Java编写的免费开源的跨平台的 Java API,Apache POI提供API给Java程序对Microsoft" +
                    " Office格式档案读和写的功能。POI为“Poor Obfuscation Implementation”的首字母缩写," +
                    "意为“简洁版的模糊实现”。\n" +
                    "所以POI的主要功能是可以用Java操作Microsoft Office的相关文件,但是一般我们都是用来操作" +
                    "Excel相关文件。");
            PoiWordUtils.addTable(document);
            //写入本地
            document.write(fos);

Running result.
insert image description here
Generate a new word according to the template

Map<String, String> testMap = new HashMap<>();
        testMap.put("Title", "POI模版替换");
        testMap.put("FirstHeading", "规则说明");
        testMap.put("FirstHeadingContent", "1.玩家同一场景,以个人为单位进行战斗.\n2.可以对其他玩家进行攻击\n3.一场游戏时间为10分钟");
        testMap.put("SecondHeading", "奖励说明");
        testMap.put("A", "主题A");
        testMap.put("a", "主题A详情");
        testMap.put("B", "主题B");
        testMap.put("b", "主题B详情");
        testMap.put("C", "主题C");
        testMap.put("c", "主题C详情");
        try {
    
    
            InputStream is = getAssets().open("谈话结果主题摘要模板.docx");
            //InputStream is = getAssets().open("阶段性风险评估报告模版.docx");
            String path = FileUtils.getAppRootPth(this) + File.separator + "word" + File.separator + "测试24.docx";
            //boolean b = WordUtils.changWord(is, path, testMap, testList);
            boolean b = WordUtils.changWord(is, path, testMap);
            Log.i(TAG, "testWord: " + b);
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }

Template:
insert image description here
After replacing:
insert image description here

Guess you like

Origin blog.csdn.net/qq_35193677/article/details/129489801