前段时间应需求写了一个将PDF输出为Excel的小程序,希望通过这篇博客给有同样需求的人一些思路。
首先用到的语言是Java,其中引入了一些对PDF和Excel进行操作的包,主要思路就是先将PDF输出为txt文件,然后再爬取txt中的关键字和数据,输出到Excel中。
pdfbox-2.0.3.jar:http://apache.fayea.com/pdfbox/2.0.3/pdfbox-2.0.3.jar
(满足一般的PDF操作需求)
pdfbox-app-2.0.3.jar:http://apache.fayea.com/pdfbox/2.0.3/pdfbox-app-2.0.3.jar
(PDFbox的多个命令行的工具包)
fontbox-2.0.3.jar:http://apache.fayea.com/pdfbox/2.0.3/fontbox-2.0.3.jar
(PDF使用的字库包)
*为了方便一些对eclipse操作不熟练的同学,我简要介绍一下如何引入所需要的依赖包,大神可跳过。
右键项目->Build Path->Configure Build Path…->Add External JARs…
然后将你下好的jar包引入就可以了
话不多说直接上代码
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
//将pdf文件输出为txt
public static void PDFtoTXT(File pdf) {
PDDocument pd;
BufferedWriter wr;
try {
File input = pdf;
// The PDF file from where
// you would like to
// extract
File output = new File(pdf.getName().split("\\.")[0] + ".txt");
// The text file where
// you are going to
// store the
// extracted data
pd = PDDocument.load(input);
pd.save("CopyOf" + pdf.getName().split("\\.")[0] + ".pdf"); // Creates a copy called
// "CopyOfInvoice.pdf"
PDFTextStripper stripper = new PDFTextStripper();
wr = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(output)));
stripper.writeText(pd, wr);
if (pd != null) {
pd.close();
}
// I use close() to flush the stream.
wr.close();
} catch (Exception e) {
e.printStackTrace();
}
}
上述方法实现了将PDF文件输出为txt文件的功能
下面我们考虑如何从txt文件中抓出想要的关键字并输出到Excel中
这里需要引入另一个依赖包,这里可以选择的有jxl和POI
简要分析jxl和poi的优缺点:(数据来源:http://blog.csdn.net/jarvis_java/article/details/4924099)
优点:
-Jxl对中文支持非常好,操作简单,方法看名知意。
-Jxl是纯javaAPI,在跨平台上表现的非常完美,代码可以再windows或者Linux上运行而无需重新编写
-支持Excel 95-2000的所有版本(网上说目前可以支持Excel2007了,还没有尝试过)
-生成Excel 2000标准格式
-支持字体、数字、日期操作
-能够修饰单元格属性
-支持图像和图表,但是这套API对图形和图表的支持很有限,而且仅仅识别PNG格式。
缺点:效率低,图片支持不完善,对格式的支持不如POI强大
优点:
-效率高
-支持公式,宏,一些企业应用上会非常实用
-能够修饰单元格属性
-支持字体、数字、日期操作
缺点:不成熟,代码不能跨平台,貌似不少同行在使用工程中还碰到让人郁闷的BUG(最近的项目中也是遇到了一些bug,不过目前没有查出来是代码的问题还是POI的问题,总之问题很诡异,数据替代参数总有失败的。关于不能跨平台这一说,我也没有试验过,不过Java不是跨平台吗?POI是JAVA的一个组件,怎么就不能跨平台了呢,总之这些问题还需要在以后的项目中多多实践,才能比较出区别之处。)
这里我选择的是jxl,所以以jxl为例
http://jaist.dl.sourceforge.net/project/jexcelapi/jexcelapi/2.6.12/jexcelapi_2_6_12.zip
下载完成后解压里面的jxl.jar
记得在项目中引入包,方法同上
import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import jxl.write.WriteException;
import jxl.write.biff.RowsExceededException;
//初始化excel
public static WritableWorkbook wwb = null;
public static WritableSheet ws;
public static void initExcel(){
try {
//首先要使用Workbook类的工厂方法创建一个可写入的工作薄(Workbook)对象
wwb = Workbook.createWorkbook(new File("excel.xlsx"));
if(wwb != null){
//创建一个可写入的工作表
//Workbook的createSheet方法有两个参数,第一个是工作表的名称,第二个是工作表在工作薄中的位置
ws = wwb.createSheet("sheet1", 0);
//下面开始添加单元格
//这里需要注意的是,在Excel中,第一个参数表示列,第二个表示行
ws.addCell(new Label(0, 0, "公司名")); //将生成的单元格添加到工作表中
ws.addCell(new Label(1, 0, "财报时间"));
ws.addCell(new Label(2, 0, "创新"));
ws.addCell(new Label(3, 0, "财政补贴"));
ws.addCell(new Label(4, 0, "优惠"));
ws.addCell(new Label(5, 0, "税收优惠"));
ws.addCell(new Label(6, 0, "递延所得税费用"));
ws.setColumnView(0, 30);
ws.setColumnView(1, 10);
ws.setColumnView(3, 14);
ws.setColumnView(6, 15);
}
} catch (IOException e) {
e.printStackTrace();
} catch (RowsExceededException e) {
e.printStackTrace();
} catch (WriteException e) {
e.printStackTrace();
}
}
//爬取目录下的txt文件中关键字并输出到excel文件中
public static boolean isMain = false;
public static boolean isYear = false;
public static String name = null;
public static String time = null;
public static void TXTtoEXCEL(File txt) {
isMain = true;
isYear = true;
name = null;
time = null;
try {
BufferedReader br = new BufferedReader(new FileReader(txt));
System.out.println(txt.getName());
String line = "";
while((line = br.readLine()) != null) {
Pattern p0 = Pattern.compile("\\s*(([()]|[\u4E00-\u9FA5])*(股份有限公司))");
Matcher m0 = p0.matcher(line);
if (m0.find() && true == isMain) {
System.out.println(line);
System.out.println("公司名=" + m0.group(1));
name = m0.group(1);
isMain = false;
continue;
}
Pattern p1 = Pattern.compile("\\s*(([一二三四五六七八九十〇○]|[0-9])*\\s*年)");
Matcher m1 = p1.matcher(line);
if(m1.find() && true == isYear) {
System.out.println(line.replaceAll("○", "〇"));
System.out.println("财报时间=" + m1.group(1).replaceAll("○", "〇"));
time = m1.group(1).replaceAll("○", "〇");
isYear = false;
continue;
}
if(name != null && time != null) {
break;
}
}
while((line = br.readLine()) != null) {
Pattern p2 = Pattern.compile("\\s*(创新)(\\s*)(--\\s)?((-*)(\\d*,)*(\\d*\\.\\d*))");
Matcher m2 = p2.matcher(line);
if(m2.find()) {
System.out.println(line);
System.out.println("创新=" + m2.group(4));
System.out.println(count);
ws.addCell(new Label(0, count, name));
ws.addCell(new Label(1, count, time));
ws.addCell(new Label(2, count, m2.group(4)));
count ++;
continue;
}
Pattern p3 = Pattern.compile("\\s*(政府补助|财政补贴)(\\s*)(--\\s)?((-*)(\\d*,)*(\\d*\\.\\d*))");
Matcher m3 = p3.matcher(line);
if(m3.find()) {
System.out.println(line);
System.out.println("政府补贴=" + m3.group(4));
System.out.println(count);
ws.addCell(new Label(0, count, name));
ws.addCell(new Label(1, count, time));
ws.addCell(new Label(3, count, m3.group(4)));
count ++;
continue;
}
Pattern p4 = Pattern.compile("\\s*(优惠)(\\s*)(--\\s)?((-*)(\\d*,)*(\\d*\\.\\d*))");
Matcher m4 = p4.matcher(line);
if(m4.find()) {
System.out.println(line);
System.out.println("优惠=" + m4.group(4));
System.out.println(count);
ws.addCell(new Label(0, count, name));
ws.addCell(new Label(1, count, time));
ws.addCell(new Label(4, count, m4.group(4)));
count ++;
continue;
}
Pattern p5 = Pattern.compile("\\s*(税收优惠)(\\s*)(--\\s)?((-*)(\\d*,)*(\\d*\\.\\d*))");
Matcher m5 = p5.matcher(line);
if(m5.find()) {
System.out.println(line);
System.out.println("税收优惠=" + m5.group(4));
System.out.println(count);
ws.addCell(new Label(0, count, name));
ws.addCell(new Label(1, count, time));
ws.addCell(new Label(5, count, m5.group(4)));
count ++;
continue;
}
Pattern p6 = Pattern.compile("\\s*(递延所得税费用|递延所得税资产)(\\s*)(--\\s)?((-*)(\\d*,)*(\\d*\\.\\d*))");
Matcher m6 = p6.matcher(line);
if(m6.find()) {
System.out.println(line);
System.out.println("递延所得税费用=" + m6.group(4));
System.out.println(count);
ws.addCell(new Label(0, count, name));
ws.addCell(new Label(1, count, time));
ws.addCell(new Label(6, count, m6.group(4)));
count ++;
continue;
}
}
if(br != null) {
br.close();
br = null;
}
} catch (IOException e) {
e.printStackTrace();
} catch (RowsExceededException e) {
e.printStackTrace();
} catch (WriteException e) {
e.printStackTrace();
}
}
最后加上main方法,批量处理目录下的pdf文件
public static void main(String[] args) {
//将当前目录下的pdf文件转成txt文件
File f = new File(System.getProperty("user.dir")); //获得当前路径
File[] files = f.listFiles();
for(File pdf : files) {
//对pdf文件进行操作
if(pdf.getName().matches(".*\\.pdf$")) {
PDFtoTXT(pdf);
}
}
files = f.listFiles(); //重新获得当前目录下的文件
initExcel();
for(File txt : files) {
//对txt文件进行操作
if(txt.getName().matches(".*\\.txt$")) {
TXTtoEXCEL(txt);
}
}
try {
//从内存中写入文件中
wwb.write();
//关闭资源,释放内存
wwb.close();
} catch (IOException e) {
e.printStackTrace();
} catch (WriteException e) {
e.printStackTrace();
}
// 删除产生的txt文件
for(File file : files) {
if(file.getName().matches(".*\\.pdf$")) {
new File(file.getName().split("\\.")[0] + ".txt").delete();
}
}
}