说明:上一篇文章使用poi对.doc格式的word文档进行了读取和更改,但很多情况下还需要在word文档中插入图片,这时就需要对.docx格式的word进行操作了。
1.制作文书
文书在源代码中可以直接看到,简单说明一下:文书有普通字段、表格、特定位置的图片,又在页眉页脚中加了普通字段和表格,基本满足对于word操作的所有情况。
2.导包
还是上篇中poi-3.9压缩资源包中的jar包,对.docx格式文档的操作用到XWPFDocument方法,使用到所有ooxml相关的jar包。
3.build配置
这次的build配置有点特殊,特别拿出来截图一下。就像上一篇说的一样,apache的很多配置在安卓是跑不通的,这次导包后,你会遇到方法过多,文件重复,基于jdk1.6以上版本的变异保存等一系列问题,可以按照下面的方法处理。当然不同的android studio版本可能也会有不同的处理方法,可以百度一下。
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.效果展示
6.源码
点我下载。