使用Java将PDF文件解析成Excel文件,史上最厉害的PDF解析

使用Java将PDF文件解析成Excel文件,史上最厉害的PDF解析将PDF文件转为Excel(PDF文件为图表也可)**,本文章提供两个工具类,一个是将PDF可以读取出来的工具类,一个是将pdf转成excel文件的工具类(第一次写博客,见谅着看啊)我的需求:公司让我将PDF文件解析成excel,然后excel有固定的模板,也就是将PDF数据掏出来,然后将数据放到excel固定的格子中,然后再将excel数据解析保存到数据库(本文章只提供解析PDF为Exce…

将PDF文件转为Excel(PDF文件为图表也可)

**,本文章提供两个工具类,一个是将PDF可以读取出来的工具类,一个是将pdf转成excel文件的工具类(第一次写博客,见谅着看啊)

我的需求:

公司让我将PDF文件解析成excel,然后excel有固定的模板,也就是将PDF数据掏出来,然后将数据放到excel固定的格子中,然后再将excel数据解析保存到数据库(本文章只提供解析PDF为Excel样式,将excel内容保存到数据库的文章,网上很多,再此我就不提供了)

  1. 解析PDF为文本数据
  2. 读取Excel模板,替换对应单元格中的数据
  3. 生成新的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>

下面给大家一些可能会用到的方法

  1. 将String类型的文件转成File类型 :File file=new File(“xxx”);
  2. 将File类型转成String类型 : String str = file.getAbsolutePath();
  3. 将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

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注