要件:Android側でデータを元に単語を生成し、ローカルに保存する
情報を確認したところ、基本的にJava APIとApache POIで実装されているAndroid向けの公式の単語操作ライブラリはないようですが、このバージョンではは Android との互換性が高くなります。 , 落とし穴がたくさんあります.
ここで、レーダーチャート、折れ線グラフ、ヒストグラムなどを操作するには単語が必要です. POI4 が必要です. ...), を使用する方法はありません3.x バージョン、チャートについて話しましょう...
1.gradleはPOIに依存します
app ディレクトリ build.gradle に、完全な依存関係を追加します。
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. 新しい段落を追加する
/**
* 添加段落内容
*
* @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. 新しいフォームを追加する
- document.createTable(1, 2);
1 行 2 列のテーブルを作成します
table.getRow(0).getCell(0).setText()
table.getRow(0).getCell(1).setText() - document.createTable();
デフォルトで 1 行 1 列を作成
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);
}
セル プロパティを設定し
、水平方向のセンタリングに注意してください: これはちょっとした落とし穴で、さらに悪いことです. すべて ctTc.getPList().get(0).addNewPPr().addNewJc().setVal(STJc) です.CENTER);、バージョンの問題を ctTc.getPArray()[0].addNewPPr().addNewJc().setVal(STJc.CENTER); に変更する必要があるため、コンパイルはエラーを報告せず、メソッドはキーコードをクリックすると、この方法があります...
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. テンプレートに従って新しい単語を生成する
テンプレートを assets ディレクトリに置き、フィールドに $ が含まれているかどうかを判断し、必要なものに置き換えます。
4.1 段落の置き換え
/**
* 替换段落文本
*
* @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 代替フォーム
/**
* 替换表格对象方法
*
* @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. 完全なツール コード
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. テスト
空白の単語を作成し、タイトルの段落、表を書きます
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);
実行結果
テンプレートに従って新しい単語を生成する
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();
}
テンプレート:
置き換え後: