需求


最近,甲方要求我们对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<String,Object> pageMap = new HashMap<String,Object>()
; pageMap = WordTablePages2.getPagesInTable(sourceFile, targetFile); /* *
从后往前,开始赋值 * 然后生成最后的目标文件 */ try { XWPFDocument doc = new XWPFDocument(new
FileInputStream(sourceFile)); List<XWPFTable> 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<String,Object> getPagesInTable(String sourceFile, String
targetFile) { XWPFDocument doc; int tableNums = 0; String preName = "";
List<String> filesToDelete = new ArrayList<String>();//要删除的文件
//获取初始页数、复制出一个初始缓存文件 try { doc = new XWPFDocument(new
FileInputStream(sourceFile)); List<XWPFTable> 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<String,Object> pageMap = new
HashMap<String,Object>(); String tempSourceFile = "";//临时产生的缓存文件,会被删除掉的 String
tempTargetFile ="";//缓存文件 for(int i = tableNums; i>=1 && i >5; i--)
{//i不用那么小,因为前面的表格不需要计算页数 tempSourceFile = preName +"-表格个数-" + i + ".docx";
tempTargetFile = preName +"-表格个数-" + (i -1) + ".docx"; Map<String,Object>
resultMap = new HashMap<String,Object>(); 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<String,Object>
getPageThenDeleteTable(String sourceFile, String targetFile) { XWPFDocument doc;
Map<String,Object> map = new HashMap<String,Object>(); /* * 1.1)获取总页数 *
读者可以随便找一种能将word转化为pdf的方法,然后获取pdf的总页数。 */ int totalPage = WordPdfUtils
.getTotalPageByToPdf(sourceFile); try { doc = new XWPFDocument(new
FileInputStream(sourceFile)); List<XWPFTable> 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<String> 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<XWPFTable> 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几”出现在了几页里来定,具体代码我就不在这里写啦

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信