说明:上一篇文章使用poi对.doc格式的word文档进行了读取和更改,但很多情况下还需要在word文档中插入图片,这时就需要对.docx格式的word进行操作了。

1.制作文书

文书在源代码中可以直接看到,简单说明一下:文书有普通字段、表格、特定位置的图片,又在页眉页脚中加了普通字段和表格,基本满足对于word操作的所有情况。

android 在线帮助文档 android docx_android 在线帮助文档

2.导包

还是上篇中poi-3.9压缩资源包中的jar包,对.docx格式文档的操作用到XWPFDocument方法,使用到所有ooxml相关的jar包。

android 在线帮助文档 android docx_android 在线帮助文档_02

3.build配置

这次的build配置有点特殊,特别拿出来截图一下。就像上一篇说的一样,apache的很多配置在安卓是跑不通的,这次导包后,你会遇到方法过多,文件重复,基于jdk1.6以上版本的变异保存等一系列问题,可以按照下面的方法处理。当然不同的android studio版本可能也会有不同的处理方法,可以百度一下。

android 在线帮助文档 android docx_向word中的特定位置插入图片_03

4.权限还是储存权限,直接上代码吧,注解的也很详细

public class MainActivity extends AppCompatActivity {
    //创建生成的文件地址
    private static final String newPath = "/storage/emulated/0/test.docx";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            ActivityCompat.requestPermissions(this, new String[]{
                    Manifest.permission.WRITE_EXTERNAL_STORAGE,
                    Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
        }
        Button go = (Button) findViewById(R.id.go);
        go.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                initData();
            }
        });
    }

    private void initData() {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("$TITLE$", "标题");//$TITLE$只是个标识符,你也可以用${},[]等等
        map.put("$TXT1$", "表格第一行");
        map.put("$CONTENT1$", "第一行内容");
        map.put("$TXT2$", "表格第二行");
        map.put("$CONTENT2$", "第二行内容");
        map.put("$CONTENT3$", "页脚中的内容");
        map.put("$TXT4$", "页脚表格第一行");
        map.put("$CONTENT4$", "页脚第一行内容");
        map.put("$TXT5$", "页脚表格第二行");
        map.put("$CONTENT5$", "页脚第二行内容");
        try {
            //读取示例文书
            InputStream is = getAssets().open("test.docx");
            //自定义的XWPFDocument,解决官方版图片不显示问题
            CustomXWPFDocument document = new CustomXWPFDocument(is);
            //读取段落(一般段落,页眉页脚没办法读取)
            List<XWPFParagraph> listParagraphs = document.getParagraphs();
            processParagraphs(listParagraphs, map);

            //读取页脚
            List<XWPFFooter> footerList = document.getFooterList();
            processParagraph(footerList, map);

            //处理表格
            Iterator<XWPFTable> it = document.getTablesIterator();
            while (it.hasNext()) {//循环操作表格
                XWPFTable table = it.next();
                List<XWPFTableRow> rows = table.getRows();
                for (XWPFTableRow row : rows) {//取得表格的行
                    List<XWPFTableCell> cells = row.getTableCells();
                    for (XWPFTableCell cell : cells) {//取得单元格
                        if ("$IMG$".equals(cell.getText())) {
                            //直接插入图片会在文档的最底端,所以要插在固定位置,要把图片放在表格里
                            //所以使用判断单元格,并清除单元格放置图片的方式来实现图片定位
                            cell.removeParagraph(0);
                            XWPFParagraph pargraph = cell.addParagraph();
                            document.addPictureData(getAssets().open("1.png"), XWPFDocument.PICTURE_TYPE_PNG);
                            document.createPicture(document.getAllPictures().size() - 1, 120, 120, pargraph);
                        }
                        List<XWPFParagraph> paragraphListTable = cell.getParagraphs();
                        processParagraphs(paragraphListTable, map);
                    }
                }
            }
            FileOutputStream fopts = new FileOutputStream(newPath);
            document.write(fopts);
            if (fopts != null) {
                fopts.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //处理页脚中的段落,其实就是用方法读取了下页脚中的内容,然后也会当做一般段落处理
    private void processParagraph(List<XWPFFooter> footerList, Map<String, Object> map) {
        if (footerList != null && footerList.size() > 0) {
            for (XWPFFooter footer : footerList) {
                //读取一般段落
                List<XWPFParagraph> paragraphs = footer.getParagraphs();
                processParagraphs(paragraphs, map);
                //处理表格
                List<XWPFTable> tables = footer.getTables();
                for (int i = 0; i < tables.size(); i++) {
                    XWPFTable xwpfTable = tables.get(i);
                    List<XWPFTableRow> rows = xwpfTable.getRows();
                    for (XWPFTableRow row : rows) {//取得表格的行
                        List<XWPFTableCell> cells = row.getTableCells();
                        for (XWPFTableCell cell : cells) {//取得单元格
                            List<XWPFParagraph> paragraphListTable = cell.getParagraphs();
                            processParagraphs(paragraphListTable, map);
                        }
                    }
                }
            }
        }
    }

    //处理段落
    public static void processParagraphs(List<XWPFParagraph> paragraphList, Map<String, Object> param) {
        if (paragraphList != null && paragraphList.size() > 0) {
            for (XWPFParagraph paragraph : paragraphList) {
                List<XWPFRun> runs = paragraph.getRuns();
                for (XWPFRun run : runs) {
                    String text = run.getText(0);
                    if (text != null) {
                        boolean isSetText = false;
                        for (Map.Entry<String, Object> entry : param.entrySet()) {
                            String key = entry.getKey();
                            if (text.indexOf(key) != -1) {
                                isSetText = true;
                                Object value = entry.getValue();
                                if (value instanceof String) {//文本替换
                                    text = text.replace(key, value.toString());
                                }
                            }
                        }
                        if (isSetText) {
                            run.setText(text, 0);
                        }
                    }
                }
            }
        }
    }
}

5.效果展示

android 在线帮助文档 android docx_android 在线帮助文档_04

6.源码

点我下载。