1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > Java准确获取Word/Excel/PPT/PDF的页数(附Word页数读不准的处理办法)

Java准确获取Word/Excel/PPT/PDF的页数(附Word页数读不准的处理办法)

时间:2021-02-19 21:29:31

相关推荐

Java准确获取Word/Excel/PPT/PDF的页数(附Word页数读不准的处理办法)

Java准确获取Word/Excel/PPT/PDF的页数(附Word页数读不准的处理办法)

1.需求背景2.环境准备工作2.1 JACOB介绍及安装2.2 Microsoft Office Word的设置 3.代码3.1 代码示例3.1.1 pom.xml3.1.2 主要功能实现3.1.3 Main方法3.1.4 运行结果 3.2 注意事项3.2.1 获取Excel页数的注意事项3.2.2 获取Word页数的注意事项3.2.3 获取PPT页数的注意事项

1.需求背景

前两天接了个小需求,就是用Java准确地判断出Word(.doc和.docx)、Excel(.xls和.xlsx)、PPT(.ppt和.pptx)还有PDF的页数。开始觉得很简单,想都没想就用了Apache的POI,但后来发现个大问题:

Apache POI对于.doc(Office Word 1997- 的版本)后缀的word文件,页数读取不准!

度娘了一下,发现大家普遍都有这个问题,解决办法也是五花八门,有用POI的,有用JACOB将Word转PDF的,还有用第三方工具比如PageOffice/OpenOffice的,但是感觉都不是特别简洁。所以结合这些博客的经验及我自己的摸索,我终于找到了较为简单准确的解决方式,下面完整地分享给大家。

2.环境准备工作

2.1 JACOB介绍及安装

我的思路还是使用JACOB来操作Word,因为对于Office Word 97-03这种远古版本,除了软件自身提供的宏,似乎没有什么能对它进行直接的操作,而在Windows平台为了解决这种软件缺乏通用API的问题,推出了COM的解决方案。

而想通过Java来操作DOM,我们就需要一个JACOB(Java-COM Bridge)这样的桥梁。JACOB 开源项目提供的是一个 JVM 独立的自动化服务器实现,其核心是基于 JNI 技术实现的 Variant, Dispatch 等接口,从而调用Windows的COM(Component Object Model组对象模型)。

JACOB下载地址为:/projects/jacob-project/

如下图:

点击Download,然后解压,将其中的jacob-1.19-x64.dll复制到System32文件夹下,如下图:

2.2 Microsoft Office Word的设置

因为是调用的Word Application自身,所以环境里必须得安装有Office Word,这个就不赘述。

Word里需要做如下两项设置,如下图:

原因是如果使用高版本的Office Word打开.doc文件,默认是预览视图,而不是编辑视图,这个预览视图会影响后面要介绍的方法的判断准确性,如下图:

3.代码

3.1 代码示例

3.1.1 pom.xml

<dependencies><dependency><groupId>net.java.dev.jna</groupId><artifactId>jna-platform</artifactId><version>4.1.0</version></dependency><dependency><groupId>org.apache.poi</groupId><artifactId>poi-scratchpad</artifactId><version>3.8</version></dependency><!--用于操作Office系列--><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>3.8</version></dependency><!--用于操作Word--><!-- /artifact/net.sf.jacob-project/jacob --><dependency><groupId>net.sf.jacob-project</groupId><artifactId>jacob</artifactId><version>1.14.3</version></dependency><!--用于操作PDF--><!-- /artifact/com.lowagie/itext --><dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.0.6</version></dependency></dependencies>

3.1.2 主要功能实现

package com.docreader;import com.itextpdf.text.pdf.PdfReader;import com.jacob.activeX.ActiveXComponent;import .Dispatch;import .Variant;import org.apache.poi.POIXMLDocument;import org.apache.poi.hslf.HSLFSlideShow;import org.apache.poi.hslf.usermodel.SlideShow;import org.apache.poi.hssf.usermodel.HSSFWorkbook;import org.apache.poi.xslf.usermodel.XMLSlideShow;import org.apache.poi.xssf.usermodel.XSSFWorkbook;import org.apache.poi.xwpf.usermodel.XWPFDocument;import java.io.FileInputStream;import java.io.IOException;public class reader {/*** description: 静态方法,用于判断文件类型,并返回页数* @param filePath 文件完整路径*/public static int getFilePageNum(String filePath) throws IOException {int pageNum = 0;String lowerFilePath = filePath.toLowerCase();if (lowerFilePath.endsWith(".xls")) {HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(lowerFilePath));Integer sheetNums = workbook.getNumberOfSheets();if (sheetNums > 0) {pageNum = workbook.getSheetAt(0).getRowBreaks().length + 1;}} else if (lowerFilePath.endsWith(".xlsx")) {XSSFWorkbook xwb = new XSSFWorkbook(lowerFilePath);Integer sheetNums = xwb.getNumberOfSheets();if (sheetNums > 0) {pageNum = xwb.getSheetAt(0).getRowBreaks().length + 1;}} else if (lowerFilePath.endsWith(".docx")) {XWPFDocument docx = new XWPFDocument(POIXMLDocument.openPackage(lowerFilePath));pageNum = docx.getProperties().getExtendedProperties().getUnderlyingProperties().getPages();} else if (lowerFilePath.endsWith(".doc")) {//下方的方法不好使,经常只统计出一页// HWPFDocument wordDoc = new HWPFDocument(new FileInputStream(lowerFilePath));// pageNum = wordDoc.getSummaryInformation().getPageCount();//采用如下方法pageNum = getDocPageNum(lowerFilePath);} else if (lowerFilePath.endsWith(".ppt")) {HSLFSlideShow document = new HSLFSlideShow(new FileInputStream(lowerFilePath));SlideShow slideShow = new SlideShow(document);pageNum = slideShow.getSlides().length;} else if (lowerFilePath.endsWith(".pptx")) {XMLSlideShow xslideShow = new XMLSlideShow(new FileInputStream(lowerFilePath));pageNum = xslideShow.getSlides().length + 1;} else if (lowerFilePath.endsWith(".pdf")){PdfReader reader = new PdfReader(filePath);pageNum = reader.getNumberOfPages();}return pageNum;}/*** description: 静态方法,专门用于判断Office 版本之前的Word(格式为.doc)的页数* @param filePath 文件完整路径*/private static int getDocPageNum(String filePath) {int pageNum = 0;try{// 建立ActiveX部件ActiveXComponent wordCom = new ActiveXComponent("Word.Application");//word应用程序不可见wordCom.setProperty("Visible", false);// 返回wrdCom.Documents的DispatchDispatch wrdDocs = wordCom.getProperty("Documents").toDispatch();//Documents表示word的所有文档窗口(word是多文档应用程序)// 调用wrdCom.Documents.Open方法打开指定的word文档,返回wordDocDispatch wordDoc = Dispatch.call(wrdDocs, "Open", filePath, false, true, false).toDispatch();Dispatch selection = Dispatch.get(wordCom, "Selection").toDispatch();pageNum = Integer.parseInt(Dispatch.call(selection,"information",4).toString());//总页数 //显示修订内容的最终状态//关闭文档且不保存Dispatch.call(wordDoc, "Close", new Variant(false));//退出进程对象wordCom.invoke("Quit", new Variant[] {});} catch (Exception e) {e.printStackTrace();}return pageNum;}}

3.1.3 Main方法

import com.docreader.reader;import javax.imageio.ImageIO;import java.awt.*;import java.awt.event.KeyEvent;import java.awt.image.BufferedImage;import java.io.File;public class Main {public static void main(String[] args) {try{int xlsNum = reader.getFilePageNum("E:\\workspace\\DocumentReader\\src\\main\\resources\\5 pages.xls");System.out.println("Office之前版本的Excel:5 pages.xls 的页数为:" + xlsNum);int xlsxNum = reader.getFilePageNum("E:\\workspace\\DocumentReader\\src\\main\\resources\\8 pages.xlsx");System.out.println("Office之后版本的Excel:8 pages.xlsx 的页数为:" + xlsxNum);int docNum = reader.getFilePageNum("E:\\workspace\\DocumentReader\\src\\main\\resources\\30 pages.doc");System.out.println("Office之前版本的Word:30 pages.doc 的页数为:" + docNum);int docxNum = reader.getFilePageNum("E:\\workspace\\DocumentReader\\src\\main\\resources\\133 pages.docx");System.out.println("Office之后版本的Word:133 pages.docx 的页数为:" + docxNum);int pptNum = reader.getFilePageNum("E:\\workspace\\DocumentReader\\src\\main\\resources\\35 pages.ppt");System.out.println("Office之前版本的PPT:35 pages.ppt 的页数为:" + pptNum);int pptxNum = reader.getFilePageNum("E:\\workspace\\DocumentReader\\src\\main\\resources\\95 pages.pptx");System.out.println("Office之后版本的PPT:95 pages.pptx 的页数为:" + pptxNum);int pdfNum = reader.getFilePageNum("E:\\workspace\\DocumentReader\\src\\main\\resources\\30 pages.pdf");System.out.println("PDF:30 pages.pdf 的页数为:" + pdfNum);} catch (Exception e){e.printStackTrace();}}}

3.1.4 运行结果

3.2 注意事项

3.2.1 获取Excel页数的注意事项

if (lowerFilePath.endsWith(".xls")) {HSSFWorkbook workbook = new HSSFWorkbook(new FileInputStream(lowerFilePath));Integer sheetNums = workbook.getNumberOfSheets();if (sheetNums > 0) {pageNum = workbook.getSheetAt(0).getRowBreaks().length + 1;}} else if (lowerFilePath.endsWith(".xlsx")) {XSSFWorkbook xwb = new XSSFWorkbook(lowerFilePath);Integer sheetNums = xwb.getNumberOfSheets();if (sheetNums > 0) {pageNum = xwb.getSheetAt(0).getRowBreaks().length + 1;}}

仔细看代码,这里的:

getRowBreaks().length + 1

指的是Excel中的分页符的数量,如下图:

如果Excel中插入了7个分页符,那么总共可打印的页数就是7+1 = 8页,如下图:

注意,我看有的教程里,页数 = workbook.getNumberOfSheets(),这就错得太离谱了,这是sheet的数量,根本不是页数。

3.2.2 获取Word页数的注意事项

/*** description: 静态方法,专门用于判断Office 版本之前的Word(格式为.doc)的页数* @param filePath 文件完整路径*/private static int getDocPageNum(String filePath) {int pageNum = 0;try{// 建立ActiveX部件ActiveXComponent wordCom = new ActiveXComponent("Word.Application");//word应用程序不可见wordCom.setProperty("Visible", false);// 返回wrdCom.Documents的DispatchDispatch wrdDocs = wordCom.getProperty("Documents").toDispatch();//Documents表示word的所有文档窗口(word是多文档应用程序)// 调用wrdCom.Documents.Open方法打开指定的word文档,返回wordDocDispatch wordDoc = Dispatch.call(wrdDocs, "Open", filePath, false, true, false).toDispatch();Dispatch selection = Dispatch.get(wordCom, "Selection").toDispatch();pageNum = Integer.parseInt(Dispatch.call(selection,"information",4).toString());//总页数 //显示修订内容的最终状态//关闭文档且不保存Dispatch.call(wordDoc, "Close", new Variant(false));//退出进程对象wordCom.invoke("Quit", new Variant[] {});} catch (Exception e) {e.printStackTrace();}return pageNum;}

这里的:

//word应用程序不可见wordCom.setProperty("Visible", false);

如果设置成true,则会打开可见的Word应用,并打开指定的Word文档,对于调试时会有很大帮助。

3.2.3 获取PPT页数的注意事项

else if (lowerFilePath.endsWith(".pptx")) {XMLSlideShow xslideShow = new XMLSlideShow(new FileInputStream(lowerFilePath));pageNum = xslideShow.getSlides().length + 1;}

仔细看代码,这里需要+1。具体原因未知,但是我经过多次测试,结果是准确的。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。