将PDF文件转为Excel(PDF文件为图表也可)
**,本文章提供两个工具类,一个是将PDF可以读取出来的工具类,一个是将pdf转成excel文件的工具类(第一次写博客,见谅着看啊)
我的需求:
公司让我将PDF文件解析成excel,然后excel有固定的模板,也就是将PDF数据掏出来,然后将数据放到excel固定的格子中,然后再将excel数据解析保存到数据库(本文章只提供解析PDF为Excel样式,将excel内容保存到数据库的文章,网上很多,再此我就不提供了)
- 解析PDF为文本数据
- 读取Excel模板,替换对应单元格中的数据
- 生成新的Excel文件,或者直接返回Sheet对象用于保存到数据库,效果一样,看需求吧
第一步:读取PDF文件
>package com.itheima.util;
import org.pdfbox.pdfparser.PDFParser;
import org.pdfbox.pdmodel.PDDocument;
import org.pdfbox.util.PDFTextStripper;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
//解析PDF文件为文本
public class ReadPdfUtil {
public static String getTextFromPDF(String pdfFilePath) {
String result = null;
FileInputStream is = null;
PDDocument document = null;
try {
is = new FileInputStream(pdfFilePath);
PDFParser parser = new PDFParser(is);
parser.parse();
document = parser.getPDDocument();
PDFTextStripper stripper = new PDFTextStripper();
result = stripper.getText(document);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (document != null) {
try {
document.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
}
这样就得到了PDF的文本数据,是不是超级简单,复制就能用.
第二步:使用excel工具类解析excel文件,可以替换内容,也可以生成新的excel文件,并且也可以返回保存到数据库的Sheet对象,超级棒
直接上工具类
package com.itheima.util;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.io.IOUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.*;
import java.util.List;
import java.util.Map;
public class ReadExcelUtil {
private Workbook workBook;
private Sheet sheet;
public ReadExcelUtil(String fileFullPath, String sheetName) {
// 解决版本问题,HSSFWorkbook是97-03版本的xls版本,XSSFWorkbook是07版本的xlsx
try {
workBook = new XSSFWorkbook(new FileInputStream(fileFullPath));
} catch (Exception e) {
try {
workBook = new HSSFWorkbook(new FileInputStream(fileFullPath));
} catch (Exception e1) {
// LOGGER.error("Excel格式不正确", e1);
throw new RuntimeException(e1);
}
}
// 进行模板的克隆(接下来的操作都是针对克隆后的sheet)
sheet = workBook.cloneSheet(0);
// 移除workbook中的模板sheet
workBook.removeSheetAt(0);
// 重命名克隆后的sheet
workBook.setSheetName(0, sheetName != null ? sheetName : "sheet");
}
/**
* 读取cell的值
*
* @param cell 需要读取的cell
* @param defaultValue 默认值
* @return
*/
public String getCellStringValue(Cell cell, String defaultValue) {
if (cell != null) {
cell.setCellType(cell.CELL_TYPE_STRING);
return cell.getStringCellValue();
}
return defaultValue;
}
/**
* 替换单元格的内容,单元格的获取位置是合并单元格之前的位置,也就是下标都是合并之前的下表
*
* @param cell 单元格
* @param value 需要设置的值
*/
public void replaceCellValue(Cell cell, Object value) {
String val = value != null ? String.valueOf(value) : "";
cell.setCellValue(val);
}
/**
* 向sheet中添加行,后面的行会向后自动移动
*
* @param startRowIndex 起始行
* @param datas 数据
* @param keys 数据中Map对应的key
*/
public void appendRows(int startRowIndex, List<Map<String, Object>> datas, String[] keys) {
// 插入行
sheet.shiftRows(startRowIndex, startRowIndex + datas.size(), datas.size(), true, false);// 第1个参数是指要开始插入的行,第2个参数是结尾行数,第三个参数表示动态添加的行数
// 向插入的行中动态的填充数据
for (int i = 0; i < datas.size(); i++) {
Map<String, Object> data = datas.get(i);
// 创建行
Row row = sheet.createRow(startRowIndex + i);
// 添加单元格
Cell cell = null;
for (int j = 0, length_2 = keys.length; j < length_2; j++) {
String key = keys[j];
String value = MapUtils.getString(data, key, "");
cell = row.createCell(j);
cell.setCellType(Cell.CELL_TYPE_STRING);
cell.setCellValue(value);
}
}
// 调整列宽
autoResizeColumn(keys.length);
}
public void exportExcel(File file) {
exportExcel(file.getAbsolutePath());
}
public void exportExcel(String fileFullPath) {
OutputStream outputStream = null;
try {
outputStream = new FileOutputStream(fileFullPath);
workBook.write(outputStream);
} catch (IOException e) {
// LOGGER.error(" exportExcel error", e);
} finally {
IOUtils.closeQuietly(outputStream);
}
}
private void autoResizeColumn(int colNumber) {
// 如果是SXSSFSheet,需要调用trackAllColumnsForAutoSizing方法一次
if (sheet instanceof SXSSFSheet) {
SXSSFSheet tmpSheet = (SXSSFSheet) sheet;
tmpSheet.trackAllColumnsForAutoSizing();
}
for (int i = 0; i < colNumber; i++) {
sheet.autoSizeColumn(i);
}
}
public Sheet getSheet() {
return sheet;
}
}
工具类介绍使用小提示
//1.模板文件所在路径
String mbPath = this.getClass().getClassLoader().getResource(“Template/增值税模板.xls”).getPath();
//2.工具类读取excel文件模板
ReadExcelUtil readExcelUtil = new ReadExcelUtil(mbPath, “命名”);
//3.替换单元格中不需要的数据,或替换成自己想要的数据
readExcelUtil.replaceCellValue(readExcelUtil.getSheet().getRow(0).getCell(0), “需要替换的数据”);
//4.让生成的文件不重复
String path = this.getClass().getClassLoader().getResource(“Temporary/”).getPath();
String name = path + filename + UUID.randomUUID().toString().replace(“-“, “”) + “.xls”;
//5.工具类获取Sheet对象,进行返回(如果需要的话可以进行返回,也可以生成新的excel文件,如果不生成excel文件,直接返回Sheet对象,里面的数据也是一样有的).
Sheet sheet = readExcelUtil.getSheet();
System.out.println(sheet.getRow(0).getCell(0).toString());//测试Sheet对象有没有值
//6.生成文件
readExcelUtil.exportExcel(new File(name));
第三步:封装PDF数据到Excel中,这里主要讲一下解决的思路,当然代码也会贴上
先上PDF文件样式和解析成Excel的样式
//下面我就直接上代码
package com.itheima.service.impl;
import com.itheima.domain.AddTax;
import com.itheima.util.ReadExcelUtil;
import com.itheima.util.ReadPdfUtil;
import org.apache.poi.ss.usermodel.Sheet;
import org.springframework.stereotype.Service;
import java.io.File;
import java.util.*;
@Service
public class ReadPdfToExcelServiceImpl3 {
public static void main(String[] args) {
String path="C:\\Users\\Rain\\Desktop\\临时办公区\\财务报表1\\2016增值税 .pdf";
readPdfToExcel1(path);
}
/* * 本文分为二个部分, * 一个是解析PDF表头文件到Excel模板中, * 一个方法是解析PDF表格内的数据到Excel模板数据中 * */
//生成Excel
//增值税
private static Sheet readPdfToExcel1(String path) {
//模板文件所在路径
String mbPath ="D:\\workspace\\java_code\\PdfFinal\\src\\main\\resources\\Template\\增值税模板.xls";
//工具类读取excel文件模板
ReadExcelUtil readExcelUtil = new ReadExcelUtil(mbPath, "sheet");
//表名
String filename = null;
//表头数据转移到excel
List<String> list = readPdfTitle1(path);
for (int i = 0; i < list.size(); i++) {
filename = list.get(i).trim();
readExcelUtil.replaceCellValue(readExcelUtil.getSheet().getRow(0).getCell(0), list.get(0));//表名
readExcelUtil.replaceCellValue(readExcelUtil.getSheet().getRow(3).getCell(0), list.get(1));//纳税人识别号
readExcelUtil.replaceCellValue(readExcelUtil.getSheet().getRow(2).getCell(0), list.get(2));//税款所属期
readExcelUtil.replaceCellValue(readExcelUtil.getSheet().getRow(5).getCell(0), list.get(3));//纳税人名称
}
//表中数据转移到excel
List<AddTax> addTaxes = readAddTax(path);
//进行给Excel赋值
int row = 10;
for (int j = 0; j < 38; j++) {
int cell = 0;
AddTax addTax = addTaxes.get(j);
readExcelUtil.replaceCellValue(readExcelUtil.getSheet().getRow(row).getCell(2 + cell - 1), addTax.getProject());
cell++;
readExcelUtil.replaceCellValue(readExcelUtil.getSheet().getRow(row).getCell(2 + cell - 1), addTax.getHurdles());
cell++;
readExcelUtil.replaceCellValue(readExcelUtil.getSheet().getRow(row).getCell(2 + cell - 1), addTax.getNumberOfMonth1());
cell++;
readExcelUtil.replaceCellValue(readExcelUtil.getSheet().getRow(row).getCell(2 + cell - 1), addTax.getNumberOfYear1());
cell++;
readExcelUtil.replaceCellValue(readExcelUtil.getSheet().getRow(row).getCell(2 + cell - 1), addTax.getNumberOfMonth2());
cell++;
readExcelUtil.replaceCellValue(readExcelUtil.getSheet().getRow(row).getCell(2 + cell - 1), addTax.getNumberOfYear2());
row++;
}
//excel文件生成的位置,这边有点小问题
String path2 = ReadPdfToExcelServiceImpl3.class.getClassLoader().getResource("Temporary/").getPath();
//让生成的文件不重复
String name = path2 + filename + UUID.randomUUID().toString().replace("-", "") + ".xls";
//生成的文件
readExcelUtil.exportExcel(new File(name));
//工具类获取Sheet对象,进行返回.
Sheet sheet = readExcelUtil.getSheet();
System.out.println(sheet.getRow(0).getCell(0).toString());//测试Sheet对象有没有值
return sheet;
}
//解析表内数据
private static List<AddTax> readAddTax(String path) {
//如果传的是File文件可以使用
// String path1 = path.getAbsolutePath();
String text = ReadPdfUtil.getTextFromPDF(path);
List<AddTax> list = new ArrayList<AddTax>();
Map<Integer, String> map = new LinkedHashMap<Integer, String>();
String[] split = text.split("\\n");
for (int i = 0; i < split.length; i++) {
map.put(i, split[i]);
}
AddTax addTax = null;
Iterator<Map.Entry<Integer, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
addTax = new AddTax();//这个为JavaBean,用于封装数据
Map.Entry<Integer, String> next = iterator.next();
if (next.getKey() > 4) {
String s = next.getValue().replaceAll(" ", "#");
if (s.contains("税款计算") || s.contains("税款缴纳") || s.contains("受理信息")) {
continue;
}
String[] split1 = s.split("#");
if (split1.length == 6) {
for (int i = 0; i < split1.length; i++) {
addTax.setProject(split1[0]);
addTax.setHurdles(split1[1]);
addTax.setNumberOfMonth1(split1[2]);
addTax.setNumberOfYear1(split1[3]);
addTax.setNumberOfMonth2(split1[4]);
addTax.setNumberOfYear2(split1[5].trim());
}
list.add(addTax);
}
}
}
return list;
}
//读取表头数据
private static List<String> readPdfTitle1(String path) {
List<String> listTitle = new ArrayList<String>();
String text = ReadPdfUtil.getTextFromPDF(path);
String[] lineTitle = text.split("\\n");
//表头前几行数据
for (int i = 0; i < lineTitle.length; i++) {
if (i <= 2) {
if (lineTitle[i].contains("税款所属期")) {
String[] timeLimit = lineTitle[i].split("税款所属期");
listTitle.add(timeLimit[0]);
listTitle.add("税款所属期" + timeLimit[1]);
} else if (lineTitle[i].contains("金额单位")) {
String[] moneyLimit = lineTitle[i].split("金额单位");
listTitle.add(moneyLimit[0]);
// listTitle.add("金额单位: 人民币元(列至角分)"); 用不到
} else {
listTitle.add(lineTitle[i].trim());
}
}
}
return listTitle;
}
}
代码亲测有用
下面给大家一些依赖吧,可能也不是全部都需要
<dependency>
<groupId>pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>0.7.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.12</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
下面给大家一些可能会用到的方法
- 将String类型的文件转成File类型 :File file=new File(“xxx”);
- 将File类型转成String类型 : String str = file.getAbsolutePath();
- 将MultipartFile类型转换为File类型:
CommonsMultipartFile cf = (CommonsMultipartFile) file;
DiskFileItem fi = (DiskFileItem) cf.getFileItem();
File f = fi.getStoreLocation();
最后送上Controller层
package com.itheima.controller;
import com.itheima.service.ReadPdfToExcelService;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import javax.annotation.Resource;
import java.io.File;
/** * @author Rain * @version 1.0 * @date 2019/7/22 */
@Controller
@RequestMapping("/upload")
public class ReadPdfToExcelController {
@Resource
private ReadPdfToExcelService readPdfToExcelService;
@RequestMapping("/filesUpload")
public String filesUpload(@RequestParam("files") MultipartFile[] files) {
//判断file数组不能为空并且长度大于0
if (files != null && files.length > 0) {
//循环获取file数组中得文件
for (int i = 0; i < files.length; i++) {
MultipartFile file = files[i];
//将MultipartFile类型转换为File类型
CommonsMultipartFile cf = (CommonsMultipartFile) file;
DiskFileItem fi = (DiskFileItem) cf.getFileItem();
File f = fi.getStoreLocation();
//调用service解析
readPdfToExcelService.readPdfToExcel(f);
}
}else {
return "fail";
}
return "success";
}
}
然后JavaBean一些简单的类我就不提供了,大致整个逻辑大家应该能看得懂,
今天的文章使用Java将PDF文件解析成Excel文件,史上最厉害的PDF解析分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/27679.html