最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java解析pdf格式發(fā)票的代碼實現(xiàn)

 更新時間:2024年08月11日 09:10:48   作者:懶人wsh  
為了減少用戶工作量及誤操作的可能性,需要實現(xiàn)用戶上傳PDF格式的發(fā)票,系統(tǒng)通過解析PDF文件獲取發(fā)票內(nèi)容,并直接將其寫入表單,以下文章記錄了功能實現(xiàn)的代碼,需要的朋友可以參考下

發(fā)票樣式

發(fā)票內(nèi)容解析

引用Maven

使用pdfbox

<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.24</version> <!-- 請檢查最新版本 -->
</dependency>

獲取PDF內(nèi)容

設(shè)置 sortByPosition 為 true 可以按文本位置提取內(nèi)容,否則獲取到的內(nèi)容錯亂,無法獲取到真正需要的內(nèi)容

    @RequestMapping("uploadReceiptsTest")
    @ResponseBody
    public Map<String,String> uploadReceiptsTest() throws Exception{
        String filePath = "D:/apache-tomcat-8.5.98/webapps/tspspic/發(fā)票文件/24372000000145100092.pdf"; // 保存路徑
        PDDocument document = PDDocument.load(new File(filePath));
        PDFTextStripper pdfStripper = new PDFTextStripper();
        // 排序文本行按其位置
        pdfStripper.setSortByPosition(true);
        String text = pdfStripper.getText(document);
        document.close();
        Map<String, String> map = pdfStr(text);
        return map;
    }

文本內(nèi)容(部分內(nèi)容以*替代)

    public static void main(String[] args) {
        String invoiceInfo = "電子發(fā)票(普通發(fā)票) 發(fā)票號碼:******\n" +
                             "開票日期:******\n" +
                             "購 名稱:****** 銷 名稱:******\n" +
                             "買 售\n" +
                             "方 方\n" +
                             "信 統(tǒng)一社會信用代碼/納稅人識別號:****** 信 統(tǒng)一社會信用代碼/納稅人識別號:******\n" +
                             "息 息\n" +
                             "項目名稱 規(guī)格型號 單 位 數(shù) 量 單 價 金 額 稅率/征收率 稅 額\n" +
                             "******* 100ml:5g 袋 800 4.070796 3256.64 13% 423.36\n" +
                             "******\n" +
                             "合 計 ¥3256.64 ¥423.36\n" +
                             "價稅合計(大寫) 叁仟陸佰捌拾圓整 (小寫)¥3680.00\n" +
                             "批號:******/ 生產(chǎn)日期:2024-05-15/ 有效期至:2026-04-30/ 含稅單價:4.6000/ 生產(chǎn)廠家:******/ 批準(zhǔn)文號:******/\n" +
                             "備 注\n" +
                             "開票人:王寧\n" +
                             "王寧";

解析文件內(nèi)容,返回數(shù)據(jù)

初版測試

    public Map<String,String> pdfStr(String invoiceInfo) {
 		//因解析出的括號不確定為中文還是英文,統(tǒng)一替換為英文字符
        invoiceInfo = invoiceInfo.replaceAll("(","(").replaceAll(")",")");
        // 定義正則表達式模式
        Pattern patternInvoiceNumber = Pattern.compile("發(fā)票號碼:(\\d+)");
        Pattern patternInvoiceDate = Pattern.compile("開票日期:(\\d{4}年\\d{1,2}月\\d{1,2}日)");
        Pattern patternBuyerName = Pattern.compile("購 名稱:(.+?) 銷 名稱:(.+?)\n");
        //由上圖可以發(fā)現(xiàn)“項目名稱 規(guī)格型號 單 位 數(shù) 量 單 價 金 額 稅率/征收率 稅 額”所需要的內(nèi)容在下一行數(shù)據(jù),使用笨方法直接獲取“稅額與合計”之間的數(shù)據(jù)通過之后的空格分割進行獲取數(shù)據(jù)
        Pattern patternItemDetails = Pattern.compile("稅 額\\s+(.*?)合 計", Pattern.DOTALL);
        Pattern patternTotal = Pattern.compile("\\(小寫\\)¥(\\d+(\\.\\d+)?)");
        Pattern patternBatchNumber = Pattern.compile("批號:(.+?)/");
        Pattern patternProductionDate = Pattern.compile("生產(chǎn)日期:(\\d{4}-\\d{1,2}-\\d{1,2})/");
        Pattern patternExpirationDate = Pattern.compile("有效期至:(\\d{4}-\\d{1,2}-\\d{1,2})/");
        Pattern patternTaxIncludedPrice = Pattern.compile("含稅單價:(\\d+(\\.\\d+)?)");
        Pattern patternManufacturer = Pattern.compile("生產(chǎn)廠家:(.+?)/");
        Pattern patternApprovalNumber = Pattern.compile("批準(zhǔn)文號:(.+?)/");
        Pattern patternIssuer = Pattern.compile("開票人:(.+)");

        // 創(chuàng)建Matcher對象
        Matcher matcherInvoiceNumber = patternInvoiceNumber.matcher(invoiceInfo);
        Matcher matcherInvoiceDate = patternInvoiceDate.matcher(invoiceInfo);
        Matcher matcherBuyerName = patternBuyerName.matcher(invoiceInfo);
        Matcher matcherItemDetails = patternItemDetails.matcher(invoiceInfo);
        Matcher matcherTotal = patternTotal.matcher(invoiceInfo);
        Matcher matcherBatchNumber = patternBatchNumber.matcher(invoiceInfo);
        Matcher matcherProductionDate = patternProductionDate.matcher(invoiceInfo);
        Matcher matcherExpirationDate = patternExpirationDate.matcher(invoiceInfo);
        Matcher matcherTaxIncludedPrice = patternTaxIncludedPrice.matcher(invoiceInfo);
        Matcher matcherManufacturer = patternManufacturer.matcher(invoiceInfo);
        Matcher matcherApprovalNumber = patternApprovalNumber.matcher(invoiceInfo);
        Matcher matcherIssuer = patternIssuer.matcher(invoiceInfo);

        // 提取數(shù)據(jù)
        String invoiceNumber = "";
        String invoiceDate = "";
        String buyerName = "";
        String sellerName = "";
        String productName = "";
        String specification = "";
        String unit = "";
        int quantity = 0;
        double unitPrice = 0.0;
        double amount = 0.0;
        String taxRate = "";
        double taxAmount = 0.0;
        double total = 0.0;
        String batchNumber = "";
        String productionDate = "";
        String expirationDate = "";
        double taxIncludedPrice = 0.0;
        String manufacturer = "";
        String approvalNumber = "";
        String issuer = "";

        if (matcherInvoiceNumber.find()) {
            invoiceNumber = matcherInvoiceNumber.group(1);
        }

        if (matcherInvoiceDate.find()) {
            invoiceDate = matcherInvoiceDate.group(1);
        }

        if (matcherBuyerName.find()) {
            buyerName = matcherBuyerName.group(1);
            sellerName = matcherBuyerName.group(2);
        }

        // 處理項目名稱、規(guī)格型號、單位、數(shù)量、單價、金額、稅率/征收率、稅額
        if (matcherItemDetails.find()) {
            String itemDetailsLine = matcherItemDetails.group(1).trim();
            itemDetailsLine = itemDetailsLine.replace("\n"," ");
            String[] details = itemDetailsLine.split(" "); // 按空格分割

            if (details.length >= 8) { // 確保有足夠的字段
            //因部分名稱過長,換行數(shù)據(jù)解析到最后進行拼接
                productName = details[0].trim(); // 項目名稱
                if (details.length >= 9){
                    productName = details[0].trim()+details[8].trim(); // 項目名稱
                }
                specification = details[1].trim(); // 規(guī)格型號
                unit = details[2].trim(); // 單位
                quantity = Integer.parseInt(details[3].trim()); // 數(shù)量
                unitPrice = Double.parseDouble(details[4].trim()); // 單價
                amount = Double.parseDouble(details[5].trim()); // 金額
                taxRate = details[6].trim(); // 稅率/征收率
                taxAmount = Double.parseDouble(details[7].trim()); // 稅額

                System.out.println("項目名稱: " + productName);
                System.out.println("規(guī)格型號: " + specification);
                System.out.println("單位: " + unit);
                System.out.println("數(shù)量: " + quantity);
                System.out.println("單價: " + unitPrice);
                System.out.println("金額: " + amount);
                System.out.println("稅率/征收率: " + taxRate);
                System.out.println("稅額: " + taxAmount);
            }
        }

        if (matcherTotal.find()) {
            total = Double.parseDouble(matcherTotal.group(1));
        }

        if (matcherBatchNumber.find()) {
            batchNumber = matcherBatchNumber.group(1);
        }

        if (matcherProductionDate.find()) {
            productionDate = matcherProductionDate.group(1);
        }

        if (matcherExpirationDate.find()) {
            expirationDate = matcherExpirationDate.group(1);
        }

        if (matcherTaxIncludedPrice.find()) {
            taxIncludedPrice = Double.parseDouble(matcherTaxIncludedPrice.group(1));
        }

        if (matcherManufacturer.find()) {
            manufacturer = matcherManufacturer.group(1);
        }

        if (matcherApprovalNumber.find()) {
            approvalNumber = matcherApprovalNumber.group(1);
        }

        if (matcherIssuer.find()) {
            issuer = matcherIssuer.group(1);
        }

        // 輸出其他結(jié)果
        System.out.println("發(fā)票號碼: " + invoiceNumber);
        System.out.println("開票日期: " + invoiceDate);
        System.out.println("購買方名稱: " + buyerName);
        System.out.println("銷售方名稱: " + sellerName);
        System.out.println("價稅合計: " + total);
        System.out.println("批號: " + batchNumber);
        System.out.println("生產(chǎn)日期: " + productionDate);
        System.out.println("有效期至: " + expirationDate);
        System.out.println("含稅單價: " + taxIncludedPrice);
        System.out.println("生產(chǎn)廠家: " + manufacturer);
        System.out.println("批準(zhǔn)文號: " + approvalNumber);
        System.out.println("開票人: " + issuer);
    }

優(yōu)化代碼

  • Map存儲正則表達式:將所有正則表達式模式和對應(yīng)的字段名稱存儲在一個Map中,遍歷Map并執(zhí)行匹配,從而避免了為每個字段都寫單獨的匹配代碼。

  • 抽取通用邏輯:將匹配邏輯抽象成一個通用方法,簡化了代碼結(jié)構(gòu),減少了重復(fù)代碼。

  • 處理商品詳情:在匹配完itemDetails后,再拆分字符串并填充對應(yīng)的字段。

    public static Map<String, String> pdfStr(String invoiceInfo) {
        invoiceInfo = invoiceInfo.replaceAll("(", "(").replaceAll(")", ")");

        // 定義正則表達式模式
        Map<String, String> patterns = new HashMap<>();
        patterns.put("invoiceNumber", "發(fā)票號碼:(\\d+)");
        patterns.put("invoiceDate", "開票日期:(\\d{4}年\\d{1,2}月\\d{1,2}日)");
        patterns.put("buyerName", "購 名稱:(.+?) 銷 名稱:(.+?)\n");
        patterns.put("itemDetails", "稅 額\\s+(.*?)合 計");
        patterns.put("total", "\\(小寫\\)¥(\\d+(\\.\\d+)?)");
        patterns.put("batchNumber", "批號:(.+?)/");
        patterns.put("productionDate", "生產(chǎn)日期:(\\d{4}-\\d{1,2}-\\d{1,2})/");
        patterns.put("expirationDate", "有效期至:(\\d{4}-\\d{1,2}-\\d{1,2})/");
        patterns.put("taxIncludedPrice", "含稅單價:(\\d+(\\.\\d+)?)");
        patterns.put("manufacturer", "生產(chǎn)廠家:(.+?)/");
        patterns.put("approvalNumber", "批準(zhǔn)文號:(.+?)/");
        patterns.put("issuer", "開票人:(.+)");

        // 提取數(shù)據(jù)
        Map<String, String> result = new HashMap<>();

        for (Map.Entry<String, String> entry : patterns.entrySet()) {
            Pattern pattern = Pattern.compile(entry.getValue(), Pattern.DOTALL);
            Matcher matcher = pattern.matcher(invoiceInfo);
            if (matcher.find()) {
                result.put(entry.getKey(), matcher.group(1).trim());
            }
        }

        // 處理項目名稱、規(guī)格型號、單位、數(shù)量、單價、金額、稅率/征收率、稅額
        if (result.containsKey("itemDetails")) {
            String[] details = result.get("itemDetails").replace("\n", " ").split(" ");
            if (details.length >= 8) {
                result.put("productName", details[0].trim() + (details.length > 8 ? details[8].trim() : ""));
                result.put("specification", details[1].trim());
                result.put("unit", details[2].trim());
                result.put("quantity", details[3].trim());
                result.put("unitPrice", details[4].trim());
                result.put("amount", details[5].trim());
                result.put("taxRate", details[6].trim());
                result.put("taxAmount", details[7].trim());
            }
        }

        // 打印結(jié)果
        for (Map.Entry<String, String> entry : result.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }

        return result;
    }

到此這篇關(guān)于Java解析pdf格式發(fā)票的代碼實現(xiàn)的文章就介紹到這了,更多相關(guān)Java解析pdf格式發(fā)票內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java8中定時任務(wù)最佳實現(xiàn)方式(實現(xiàn)原理)

    java8中定時任務(wù)最佳實現(xiàn)方式(實現(xiàn)原理)

    這篇文章主要介紹了java8中定時任務(wù)最佳實現(xiàn)方式,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2024-12-12
  • 兩個SpringBoot模塊互相調(diào)用實現(xiàn)方式

    兩個SpringBoot模塊互相調(diào)用實現(xiàn)方式

    文章介紹了如何在兩個SpringBoot模塊之間進行互調(diào),未使用SpringCloud的Feign和OpenFeign,具體步驟包括:在啟動類中加入RestTemplate并注冊到容器中;在需要調(diào)用的類中注入RestTemplate;在方法中使用RestTemplate調(diào)用其他模塊的接口
    2025-11-11
  • Spring?Boot與graphql-java如何構(gòu)建高效GraphQL服務(wù)

    Spring?Boot與graphql-java如何構(gòu)建高效GraphQL服務(wù)

    文章介紹如何在SpringBoot中集成graphql-java庫,通過定義GraphQLSchema、構(gòu)建實例及注冊Web端點實現(xiàn)高效數(shù)據(jù)查詢與突變操作,解決RESTAPI的過度獲取問題,提升開發(fā)靈活性與性能,并結(jié)合工具如ApolloClient優(yōu)化前端數(shù)據(jù)管理,感興趣的朋友跟隨小編一起看看吧
    2025-09-09
  • springboot項目引入外部jar包的詳細(xì)圖文教程

    springboot項目引入外部jar包的詳細(xì)圖文教程

    在項目中有時候需要引入外部jar包,啟動運行,下面這篇文章主要給大家介紹了關(guān)于springboot項目引入外部jar包的詳細(xì)圖文教程,需要的朋友可以參考下
    2023-09-09
  • Java實現(xiàn)普通類注入service對象

    Java實現(xiàn)普通類注入service對象

    這篇文章主要介紹了Java實現(xiàn)普通類注入service對象,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • SpringBoot結(jié)合kaptcha生成圖片驗證碼詳解

    SpringBoot結(jié)合kaptcha生成圖片驗證碼詳解

    這篇文章主要為大家詳細(xì)介紹了SpringBoot如何結(jié)合kaptcha實現(xiàn)圖片驗證碼功能,文中的示例代碼講解詳細(xì),有需要的小伙伴可以參考一下
    2024-01-01
  • Spring與Mybatis相結(jié)合實現(xiàn)多數(shù)據(jù)源切換功能

    Spring與Mybatis相結(jié)合實現(xiàn)多數(shù)據(jù)源切換功能

    這篇文章主要介紹了Spring與Mybatis相結(jié)合實現(xiàn)多數(shù)據(jù)源切換功能的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-06-06
  • mybatis初始化SqlSessionFactory失敗的幾個原因分析

    mybatis初始化SqlSessionFactory失敗的幾個原因分析

    這篇文章主要介紹了mybatis初始化SqlSessionFactory失敗的幾個原因分析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java 實現(xiàn)協(xié)同過濾算法推薦算法的示例代碼

    Java 實現(xiàn)協(xié)同過濾算法推薦算法的示例代碼

    本文介紹了協(xié)同過濾算法的概念,包括基于用戶的協(xié)同過濾和基于物品的協(xié)同過濾,文章詳細(xì)解釋了數(shù)據(jù)準(zhǔn)備、相似度計算以及如何在Java中實現(xiàn)這些算法,通過一個簡單的用戶-物品評分矩陣示例,展示了如何計算用戶和物品之間的相似度,并推薦未評分的物品,感興趣的朋友一起看看吧
    2025-02-02
  • Java中Swagger框架的使用詳解

    Java中Swagger框架的使用詳解

    這篇文章主要介紹了Java框架Swagger的使用詳解,在開發(fā)期間接口會因業(yè)務(wù)的變更頻繁而變動,如果需要實時更新接口文檔,這是一個費時費力的工作,Swagger應(yīng)運而生,他可以輕松的整合進框架并通過一系列注解生成強大的API文檔,需要的朋友可以參考下
    2023-08-08

最新評論

长泰县| 额济纳旗| 绥江县| 祁东县| 商水县| 溧水县| 克拉玛依市| 泗洪县| 晋城| 永定县| 澄江县| 杭锦旗| 即墨市| 沅陵县| 连平县| 博兴县| 鄂托克旗| 通江县| 前郭尔| 邓州市| 囊谦县| 临江市| 房产| 呼图壁县| 永年县| 赫章县| 忻州市| 项城市| 荆门市| 大冶市| 宁化县| 手游| 汉寿县| 崇仁县| 顺平县| 和硕县| 鄢陵县| 墨玉县| 安丘市| 永泰县| 临朐县|