java&python提取PDF中的表格——PDF转Excel

java&python提取PDF中的表格——PDF转Excel,第1张

java&python提取PDF中的表格——PDF转Excel 前言

        在日常工作中,word、excel、pdf等是我们最常见、最常用的文件格式,那么,随之而来的问题是:如何有效地对这3种文件进行相互转换?相信大家多多少少都有遇到过这样的转换需求。其中,word与excel的相互转换以及word、excel转为pdf是比较简单,比较麻烦的是pdf转excel。由于工作需要,作者恰好遇到了pdf转excel的需求,在此分享一下个人经验,与大家相互学习。

思路

        文件格式转换的思路很简单,就是将源文件内容读取出来、然后输出保存为目标格式。下面我们用三种方式将pdf转换为excel。

java实现——spire.pdf

步骤一:引入依赖


     
         com.e-iceblue
         http://repo.e-iceblue.cn/repository/maven-public/
    




     e-iceblue
     spire.pdf
     5.1.0

ps:如果maven方式无法下载依赖,可以直接访问 Repository - Nexus Repository Manager官方仓库,将对应jar包下载下来、再通过maven安装到本地仓或直接copy到项目中添加为依赖即可。

步骤二:代码示例

public static void main(String[] args) {
     // 加载pdf文件
     Pdfdocument pdf = new Pdfdocument();
     pdf.loadFromFile("源.pdf");
     //保存为Excel文档
     pdf.saveToFile("目标.xlsx", FileFormat.XLSX);
     pdf.dispose();
}

优点:

简单、代码量少纯代码实现,方便集成到项目所见即所得——excel里的表格与pdf里的看上去是一样的

缺点:

封装的很好但是不够灵活页码、空白部分也会被输出到excel,产生多余的行列 python实现——pdfplumber+xlwt

步骤一:环境准备

安装python环境pip install安装pdfplumber、xlwt库项目中引入安装的库

步骤二:代码示例

from os import pread
import pdfplumber
import xlwt
# 读取源pdf文件
pdf = pdfplumber.open("./test.pdf")
# 创建excel
workboot = xlwt.Workbook()
# 创建sheet
sheet = workboot.add_sheet("Sheet1")
# 行计数
i = 0
# 循环读取pdf的每一页
for page in pdf.pages:
    # 读取表格
    for table in page.extract_tables():
        # 读取表格中的行
        for row in table:
            print(row)
            for j in range(len(row)):
                sheet.write(i,j,row[j])
            i+=1

pdf.close()
print(i)
workboot.save("./test.xlsx")

优点:

代码量少,简单灵活,可以 *** 作pdf中表格的每一个单元格纯代码实现,方便集成到项目

缺点:

会忽略掉所有表格样式,相当于只粘贴文本 java配合wps软件实现——pdfbox、poi(wps vip用户请忽略以下内容^_^)

        专业的事情找专业的软件做肯定是比较完美的,wps作为免费办公软件还是想当好用的。但是,pdf转excel作为高级功能在wps里是需要开通vip会员才能使用的!不过,5页及以下pdf文件的转换对普通用户也是免费的。于是我们可以这么 *** 作:先用代码拆分pdf、每5页保存一个文件,再使用wps将拆分后的文件分别转换;最后使用代码将转换后的excel合并为一个文件。

步骤一:引入依赖


     org.apache.pdfbox
     pdfbox
     2.0.24



    org.apache.poi
    poi
    5.0.0

步骤二:拆分pdf

    public static void splitPdf(String root) throws Exception{
        File file = new File(root);
        PDdocument pddocument = PDdocument.load(file);
        // 拆分后的文件集合保存目录
        String saveTo = root.substring(0,root.lastIndexOf("."));
        File save = new File(saveTo);
        if (!save.exists()){
            save.mkdirs();
        }
        PDPageTree pages = pddocument.getPages();
        int count = pages.getCount();
        System.out.println(count);
        int i = 1;
        List list = new ArrayList<>();
        for (PDPage page : pages) {
            list.add(page);
            if (i % 5 == 0){
                PDdocument split = new PDdocument();
                for (int j = 0; j < 5; j++) {
                    split.addPage(list.remove(0));
                }
                // 每5页作为新的pdf输出,以数字序号命名
                split.save(new File( saveTo + "\" + (i/5) + ".pdf"));
            }
            i++;
        }
        // 不满5页的尾数处理
        if (list.size() > 0){
            PDdocument split = new PDdocument();
            for (PDPage pdPage : list) {
                split.addPage(pdPage);
            }
            split.save(new File(saveTo + "\" + (count/5 + 1) + ".pdf") );
        }
    }

步骤三:合并excel

public static void mergeExcel(String root) throws Exception{
	Workbook workbook = WorkbookFactory.create(true);
	Sheet sheet = workbook.createSheet("sheet1");
	// excel文件集合
	long count = Files.list(Paths.get(root)).filter(path -> path.toString().endsWith(".xlsx")).count();
	System.out.println("总数:" + count);

	int rowNumber = 0;
	// excel文件以数字序列命名的
	for (long l = 1; l <= count; l++) {
		String fileName = root + l + ".xlsx";
		System.out.println("处理:" + fileName);
		Workbook temp = WorkbookFactory.create(new File(fileName));
		Sheet tempSheet = temp.getSheetAt(0);
		for (Row cells : tempSheet) {
			Row newRow = sheet.createRow(rowNumber++);
			// 复制行格式
			newRow.setHeight(cells.getHeight());
			newRow.setHeightInPoints(cells.getHeightInPoints());
			newRow.setRowStyle(cells.getRowStyle());
			newRow.setZeroHeight(cells.getZeroHeight());
			int cellNumber = 0;
			for (Cell cell : cells) {
				// 复制列格式
				sheet.setColumnWidth(cellNumber,tempSheet.getColumnWidth(cellNumber));
				// 复制数据
				Cell newCell = newRow.createCell(cellNumber);
				CellType cellType = CellType.valueOf(cell.getCellType().name());
				switch (cellType){
					case STRING:
						newCell.setCellValue(cell.getStringCellValue());
						break;
					case BLANK:
						newCell.setBlank();
						break;
					case NUMERIC:
						newCell.setCellValue(cell.getNumericCellValue());
						break;
					default:

				}
				// 复制单元格格式
				newCell.setCellComment(cell.getCellComment());
				CellStyle cellStyle = workbook.createCellStyle();
				cellStyle.cloneStyleFrom(cell.getCellStyle());
				newCell.setCellStyle(cellStyle);
				newCell.setHyperlink(cell.getHyperlink());
				cellNumber++;
			}
		}
		// 合并单元格设置,合并区域的坐标需要根据上个文件的行数调整
		int lastRowNum = sheet.getLastRowNum() - tempSheet.getLastRowNum();
		for (CellRangeAddress mergedRegion : tempSheet.getMergedRegions()) {
			int firstRow = mergedRegion.getFirstRow();
			int lastRow = mergedRegion.getLastRow();
			mergedRegion.setFirstRow(firstRow + lastRowNum);
			mergedRegion.setLastRow(lastRow + lastRowNum);
			sheet.addMergedRegion(mergedRegion);
		}
		temp.close();
	}
	workbook.write(new FileOutputStream(root + "合并.xlsx"));
	workbook.close();
}

优点:

免费使用专业软件的付费功能pdf里的表格样式可以完美复制

缺点:

非纯代码实现,不能集成到项目实现比较复杂,代码量多 总结

        以上方式仅适用于pdf里的表格为非图片形式,如果表格以图片形式存在于pdf里是无法转换的。可能需要使用图文识别方面的技术,有了解的小伙伴可以留言哈。(wps是支持图片形式的表格识别的,不过作者没有亲测,vip可用)

        

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5707282.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-17
下一篇2022-12-17

发表评论

登录后才能评论

评论列表(0条)

    保存