java word 获取每个表格所在的页码 (利用POI+pdf)

需求

最近,甲方要求我们对word里的每个表格,计算每个表格所在的页码,虽然直接获取word某个表格在多少页很难(POI没有提供相应的api或者不准确),但是我们想到将word转化为pdf,获取pdf的页数是很简单的。

解决方法

1)对word生成一个pdf,获取一下页数
2)获取完页数后,就删除一个表格,然后生成一个新的word
3)循环往复知道所有表格被遍历完

代码

注意:word转换pdf、获取pdf的方法我这里没有提供,因为我转pdf的方法挺复杂的,怕贴出来影响大家的效率。如果大家没有找到更好的方法,可以尝试我的方法,在我的另一篇博客:获取word页数中有讲~
调用顺序:
java word 获取每个表格所在的页码 (利用POI+pdf)_第1张图片

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();
//      }
//    }
}

结果截图

java word 获取每个表格所在的页码 (利用POI+pdf)_第2张图片

java word 获取每个表格所在的页码 (利用POI+pdf)_第3张图片

更多功能

其实利用这个方法,稍微修改代码,还可以获取相同标题的表格,一共占了几页,大体是利用比如“tttable几”出现在了几页里来定,具体代码我就不在这里写啦

你可能感兴趣的:(POI,文本处理,POI,word中表格页码)