最近,甲方要求我们对word里的每个表格,计算每个表格所在的页码,虽然直接获取word某个表格在多少页很难(POI没有提供相应的api或者不准确),但是我们想到将word转化为pdf,获取pdf的页数是很简单的。
1)对word生成一个pdf,获取一下页数
2)获取完页数后,就删除一个表格,然后生成一个新的word
3)循环往复知道所有表格被遍历完
注意:word转换pdf、获取pdf的方法我这里没有提供,因为我转pdf的方法挺复杂的,怕贴出来影响大家的效率。如果大家没有找到更好的方法,可以尝试我的方法,在我的另一篇博客:获取word页数中有讲~
调用顺序:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
public class WordTablePages2 {
public static void main(String[] args) throws Exception {
String sourceFile = "E:/nctcFile/报告/dengji.docx";
String targetFile = "E:/nctcFile/报告/result.docx";
// mergeColumeAndRow(sourceFile, targetFile);
// setPageOfTable();
// setWordTotalPage(null,null);
// mergeColumeAndRow(sourceFile, targetFile);
setPagesInTable(sourceFile, targetFile);
// getRepeatTableHeader(sourceFile);
}
/*
* 设置文档中的表格占页
*/
public static void setPagesInTable(String sourceFile, String targetFile) {
//获取每个表格的占页信息,存到一个map中
Map pageMap = new HashMap();
pageMap = WordTablePages2.getPagesInTable(sourceFile, targetFile);
/*
* 从后往前,开始赋值
* 然后生成最后的目标文件
*/
try {
XWPFDocument doc = new XWPFDocument(new FileInputStream(sourceFile));
List doctables = doc.getTables();
for(int i = doctables.size() -1; i >=0; i--) {
for(XWPFTableCell cell : doctables.get(i).getRow(0).getTableCells()) {
if(cell.getText().contains("第table") && cell.getText().contains("页")) {//找到“第table几页”
int start = cell.getText().indexOf("第");
int end = cell.getText().indexOf("页");
String tableIndexTag = cell.getText().substring(start+1, end);//表格索引标志,留下比如:“table3”
//比如table3占的页数为1页,那么就修改“第table3页”为“第1页”
cell = WordTablePages2.replaceCell(cell, tableIndexTag, pageMap.get(tableIndexTag).toString());
// pageMap.put(tableIndexTag, (int)pageMap.get(tableIndexTag) - 1);//“第几页”的页数-1
}
// else if(cell.getText().contains("共ttable") && cell.getText().contains("页")) {//找到“共table几页”
// int start = cell.getText().indexOf("共");
// int end = cell.getText().indexOf("页");
// String tableIndexTag = cell.getText().substring(start+1, end);//表格索引标志,留下比如:“ttable3”
// //比如ttable3占的页数为2页,那么就修改“共table3页”为“共2页”
// cell = WordTablePages.replaceCell(cell, tableIndexTag, pageMap.get(tableIndexTag).toString());
// }
}
}
FileOutputStream fos = new FileOutputStream(targetFile);
doc.write(fos);
doc.close();
fos.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
/*
* 获取测试登记测试报告的表格占页数
* 1)每获取一次页数,就删除一个表格,然后生成一个word(直到表格删除完)
* 2)然后生成一个pdf,获取一下页数
*/
public static Map getPagesInTable(String sourceFile, String targetFile) {
XWPFDocument doc;
int tableNums = 0;
String preName = "";
List filesToDelete = new ArrayList();//要删除的文件
//获取初始页数、复制出一个初始缓存文件
try {
doc = new XWPFDocument(new FileInputStream(sourceFile));
List doctables = doc.getTables();
tableNums = doctables.size();
System.out.println("tableNums:" + tableNums);
preName = targetFile.replace(".docx", "");
// System.out.println("preName:" + preName);
FileOutputStream fos = new FileOutputStream(preName +"-表格个数-" + tableNums + ".docx");
filesToDelete.add(preName +"-表格个数-" + tableNums + ".docx");
doc.write(fos);
fos.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
/*
* 开始循环获取页数、删除表格
*/
Map pageMap = new HashMap();
String tempSourceFile = "";//临时产生的缓存文件,会被删除掉的
String tempTargetFile = "";//缓存文件
for(int i = tableNums; i>=1 && i >5; i--) {//i不用那么小,因为前面的表格不需要计算页数
tempSourceFile = preName +"-表格个数-" + i + ".docx";
tempTargetFile = preName +"-表格个数-" + (i -1) + ".docx";
Map resultMap = new HashMap();
resultMap = WordTablePages2.getPageThenDeleteTable(tempSourceFile, tempTargetFile);
pageMap.putAll(resultMap);
// if(resultMap.get("tableOrder1") != null) {//标记1:第table几页
// String onetablePage = resultMap.get("tableOrder1").toString();// 第table几页
// if(pageMap.get(onetablePage) == null) {
// pageMap.put(onetablePage, 1);// 记录为第1页
// } else {//如果已经有第一页了,则页数+1
// pageMap.put(onetablePage, ((int) pageMap.get(onetablePage) + 1));
// }
// }
// if(resultMap.get("tableOrder2") != null) {//标记2:共table几页
// String tableSumPage = resultMap.get("tableOrder2").toString();//共table几页
// if(pageMap.get(tableSumPage) == null ) {
// pageMap.put(tableSumPage, 1);// 记录为占1页
// } else {//如果已经占页了,则页数+1
// pageMap.put(tableSumPage, ((int) pageMap.get(tableSumPage) + 1));
// }
// }
// System.out.println("要删除的pdf:" + tempTargetFile.replace(".docx", ".pdf"));
filesToDelete.add(tempTargetFile.replace(".docx", ".pdf"));//要删除的文件
filesToDelete.add(tempTargetFile);
}
WordTablePages2.deleteFiles(filesToDelete);
System.out.println("testPagesInTable的pageMap:" + pageMap);
return pageMap;
}
/*
* 子方法: 获取当前总页数,并删除最后一个表格
*/
public static Map getPageThenDeleteTable(String sourceFile, String targetFile) {
XWPFDocument doc;
Map map = new HashMap();
/*
* 1.1)获取总页数
* 读者可以随便找一种能将word转化为pdf的方法,然后获取pdf的总页数。
*/
int totalPage = WordPdfUtils.getTotalPageByToPdf(sourceFile);
try {
doc = new XWPFDocument(new FileInputStream(sourceFile));
List doctables = doc.getTables();
//1.2) 获取最后一个表格的标记:第“table几”页,共“table几”页
XWPFTable lastTable = doctables.get(doctables.size()-1);
for(XWPFTableRow row :lastTable.getRows()) {
for(XWPFTableCell cell : row.getTableCells()) {
if(cell.getText().contains("第table")) {
System.out.println("捕获到:" + cell.getText());
int start = cell.getText().indexOf("第");
int end = cell.getText().indexOf("页");
map.put(cell.getText().substring(start+1, end), totalPage);//留下比如:“table3 : 5”
System.out.println(String.format("放入一个单元格的数据%s : %s" ,
cell.getText().substring(start+1, end), totalPage));
}
}
}
//1.3)开始删除表格
int lastTableIndex = doctables.size() -1;
int pos = doc.getPosOfTable(doctables.get(lastTableIndex));
doc.removeBodyElement(pos);
// System.out.println("getPageThenDeleteTable方法的map:" + map);
// System.out.println("获取完总页数,删一个表格\n\n");
FileOutputStream fos = new FileOutputStream(targetFile);
doc.write(fos);
fos.close();
return map;
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
return null;
}
}
/*
* 删除List中的文件
*/
public static void deleteFiles(List files) {
for(String file : files) {
try {
File f = new File(file);
if(f.exists() && !f.isDirectory()) {
f.delete();
System.out.println("删除了文件:" + f);
}
} catch(Exception e) {
System.out.println("删除登记测试报告的页码缓存文件时出错,程序继续");
}
}
System.out.println("删除完所有缓存文件");
}
/*
* 替换单元格中的值
*/
public static XWPFTableCell replaceCell(XWPFTableCell cell, String oldString, String newString) {
for (XWPFParagraph p : cell.getParagraphs()) {
for (XWPFRun r : p.getRuns()) {
String text = r.getText(0);
if (text != null && text.contains(oldString)) {
text = text.replace(oldString, newString);
r.setText(text,0);
}
}
}
System.out.println(String.format("将旧值 %s 替换为新值 : %s", oldString, newString));
return cell;
}
// //测试重复表头能否被获取到
// public static void getRepeatTableHeader(String sourceFile) {
// XWPFDocument doc;
// try {
// doc = new XWPFDocument(new FileInputStream(sourceFile));
// List tables = doc.getTables();
// for (int i =tables.size()-1 ; i>= 0 ; i--) {
// for(XWPFTableRow row : tables.get(i).getRows()) {//每一行
// for(XWPFTableCell cell :row.getTableCells()) {
// if(cell.getText().contains("第table3页")) {
// System.out.println("捕获到第table3页");
// }
// }
// }
// }
// doc.close();
// } catch (IOException e) {
// // TODO 自动生成的 catch 块
// e.printStackTrace();
// }
// }
}
其实利用这个方法,稍微修改代码,还可以获取相同标题的表格,一共占了几页,大体是利用比如“tttable几”出现在了几页里来定,具体代码我就不在这里写啦