welcome to xlongwei.com

欢迎大家一起学习、交流、分享


QQ:9167702333 邮箱:admin@xlongwei.com

doc2fill文档模板填充接口


分类 Java   关键字 分享   标签 java   web   algorithm   发布 hongwei  1445585170675
注意 转载须保留原文链接,译文链接,作者译者等信息。  
doc2fill接口支持doc和docx文档模板填充,内容变量格式{var},demo地址:http://cms.xlongwei.com/open/doc2fill.html

  • doc2fill,doc2fill(doc|docx, file, replaces, tables),处理文档模板的变量替换和表格填充
  • read(doc), readx(docx),读取doc或docx文档,得到的是不同的java对象
  • replace(doc, replaces), replacex(docx, replaces),执行变量替换
  • tables(doc, tables), tablesx(docx, tables),执行表格填充
  • write(doc, file), writex(docx, file),文档写入文件

doc和docx文档分开处理,对应的是poi的不同的包
public static boolean doc2fill(File template, File target, Map<String, String> replaces, List<List<Map<String, String>>> tables) {
try {
if(template.getName().toLowerCase().endsWith(".docx")) {
XWPFDocument docx = readx(template);
replacex(docx, replaces);
tablesx(docx, replaces);
tablesx(docx, tables);
writex(docx, target);
}else {
HWPFDocument doc = read(template);
replace(doc, replaces);
tables(doc, tables);
write(doc, target);
}
return true;
}catch(Exception e) {
logger.warn("fail to doc2fill doc file: " + template.getAbsolutePath(), e);
}
return false;
}

doc文档的处理见:WordUtil,这里介绍一下docx的处理

变量替换代码:
public static boolean replacex(XWPFDocument docx, Map<String, String> replaces) {
if (replaces != null && replaces.size() > 0) {
List<XWPFParagraph> paragraphs = docx.getParagraphs();
replace(paragraphs, replaces); //段落变量替换
logger.info("replace docx file ok");
return true;
}else {
logger.info("nothing to replace cause of empty replaces");
return false;
}
}
public static void tablex(XWPFTable table, Map<String, String> replaces) {
List<XWPFTableRow> rows = table.getRows();
for (int r=0,rl=rows.size()-1; r < rl; r++) {
XWPFTableRow row = rows.get(r+1);
List<XWPFTableCell> cells = row.getTableCells(); //表格单元变量替换,单元格还是包含段落
for(int c=0,cl=cells.size(); c < cl; c++) {
List<XWPFParagraph> paragraphs = cells.get(c).getParagraphs();
replace(paragraphs, replaces);
}
}
}
private static void replace(List<XWPFParagraph> paragraphs, Map<String, String> params) {
if(paragraphs==null || paragraphs.size()==0) return;
for(XWPFParagraph paragraph : paragraphs) {
List<XWPFRun> runs = paragraph.getRuns();
for(int i=0,len=runs.size(); i<len; i++) {
String var = runs.get(i).toString();
String text = StringUtil.replace(var, params);
if(!var.equals(text)) {
String fontFamily = runs.get(i).getFontFamily();
int fontSize = runs.get(i).getFontSize();
paragraph.removeRun(i); //这里得先remove在insert,因为setText会导致文本附加在后面,原来的文本还在
XWPFRun newRun = paragraph.insertNewRun(i);
newRun.setText(text);
newRun.setFontFamily(fontFamily); //这里可能恢复更多样式,目前只处理了字体和字号
if(fontSize>0) newRun.setFontSize(fontSize); //fontSize可能为-1导致单元格撑大了
}
}
}
}

表格填充代码:
public static void tablex(XWPFTable table, List<Map<String, String>> data) {
List<XWPFTableRow> rows = table.getRows();
int tableRows = rows.size()-1, dataRows = data.size(), handleRows = tableRows>=dataRows?tableRows:dataRows;
List<String> lastRow = new ArrayList<>();
for(XWPFTableCell cell : rows.get(tableRows).getTableCells()) {
lastRow.add(cell.getText()); //记住表格最后一行,以便根据数据扩展,例如{name} {mobile},增加行时这些变量要保留才能替换成实际的值
}
for (int r = 0; r < handleRows; r++) {
if(r>=dataRows) {
table.removeRow(r); //多余的行删除
}else {
XWPFTableRow row = r>=tableRows ? table.createRow() : rows.get(r+1);
Map<String, String> map = data.get(r);

List<XWPFTableCell> cells = row.getTableCells();
for(int c=0,len=cells.size(); c < len; c++) {
if(r>=tableRows) {
String var = lastRow.get(c);
String text = StringUtil.replace(var, map); //替换{var}为实际的值
cells.get(c).setText(text); //增加的单元格直接赋值即可
}else {
List<XWPFParagraph> paragraphs = cells.get(c).getParagraphs();
replace(paragraphs, map); //老的单元格执行替换逻辑
}
}
}
}
}

demo地址:http://cms.xlongwei.com/open/doc2fill.html