IRONSOFTWAREHOME

Invoice Processing in C#: Generate, Extract, and Automate PDF Invoices with .NET

Curtis Chau
Curtis Chau
Updated: 2026年1月21日

發票處理C# .NET 中,使用IronPDF涵蓋了完整的文件生命週期:從HTML模板生成專業的PDF發票,符合ZUGFeRDFactur-X電子發票標準,使用文字解析和AI驅動的處理提取從收到的發票中提取結構化資料,並建立可以與QuickBooks、Xero和SAP等會計系統整合的批量自動化流水線

精讀:快速入門指南

本教程涵蓋在C# .NET中生成、提取和自動化PDF發票,包括電子發票合規性、AI驅動的解析以及會計系統整合。

  • 適用物件: 對.NET開發者正在建構發票模組、應付帳款自動化或電子發票合規性的開發者。
  • 您將構建的內容: 使用HTML模板的發票生成,包含行項目和稅費計算、支付連結的QR碼、符合ZUGFeRD/Factur-X的PDF/A-3輸出、使用正則表達式的文字提取、AI驅動的發票解析以及與會計系統整合的批量處理。
  • 運行環境: .NET 10、.NET 8 LTS、.NET Framework 4.6.2+ 和 .NET Standard 2.0。不需要外部服務依賴。
  • 適用情況: 當您需要生成發票PDF、滿足EU電子發票要求,或從供應商發票中提取資料以便應付帳款。
  • 技術重要性: IronPDF以像素精確度將HTML轉換為PDF,支持嵌入XML的PDF/A-3,並提供可與正則表達式或AI配合使用的文字提取API,以將非結構化發票轉化為結構化資料。

只需幾行程式碼即可生成您的第一份PDF發票:

  1. 1Install IronPDF with NuGet Package Manager

    PM > Install-Package IronPdf

  2. 2複製並運行這段程式碼片段。

    var renderer = new IronPdf.ChromePdfRenderer();
    var pdf = renderer.RenderHtmlAsPdf("<h1>Invoice #1001</h1><p>Total: $500.00</p>");
    pdf.SaveAs("invoice.pdf");
    C#
  3. 3部署以在您的實時環境中測試

    今天就開始在您的專案中使用IronPDF,透過免費試用
    arrow pointer

在您購買或註冊30天試用版IronPDF後,在應用程式的開始處新增您的授權金鑰。

IronPdf.License.LicenseKey = "KEY";

Start using IronPDF in your project today with a free trial.

第一步:
arrow pointer
NuGet使用NuGet安裝

PM > Install-Package IronPdf

Install IronPDF by running the command above in the NuGet Package Manager Console, or search for the package in the NuGet Package Manager.
目錄
NuGet使用NuGet安裝

PM > Install-Package IronPdf

Install IronPDF by running the command above in the NuGet Package Manager Console, or search for the package in the NuGet Package Manager.

什麼是發票生命週期,為什麼PDF仍然是標準?

在深入程式碼之前,理解發票在現代業務系統中的完整旅程是有幫助的。 發票的生命週期包括五個不同的階段:生成、分發、接收、資料提取和會計整合。

發票處理始於生成。 企業建立包含行項目、定價、稅費計算、付款條款和品牌化的發票。 發票需要看起來專業,並滿足所有法律要求。 接下來是分發,通過電子郵件、客戶門戶或傳統郵件將發票發送給客戶。 當客戶收到後,應付帳款團隊將捕獲文件,並準備好進行處理。 資料提取從發票中提取關鍵資訊,如供應商詳細資訊、行項目、總額和到期日,以便可以檢查並與採購訂單比對。 最後,會計整合將這些資料移入財務系統如QuickBooks、Xero或SAP進行付款和記錄保存。

為什麼在這麼多年後,PDF仍然是最廣泛使用的格式? 這歸結於一個獨特的優勢組合。 PDF讓您的發票格式不變,無論您使用什麼裝置或操作系統。 無論有人是在Windows、Mac或他們的手機上打開您的發票,它看起來正如您設計的那樣。 PDF也很難以錯誤方式更改,因此它比Word或Excel等格式更好地保護了您的文件完整性。 您可以新增數位簽章以獲得真實性並使用加密來保護安全。 最重要的是,PDF已經成為每個業務系統都認識和支持的通用標準。

當然,也有挑戰。 PDF旨在對人友好閱讀,而非計算機處理。 而不是以結構化資料儲存資訊,PDF會根據其在頁面上的出現位置來保存文字、線條、形狀和圖像。 這就是為什麼像IronPDF這樣的工具如此有幫助,因為它們使得將對人友好的文件轉變為軟體可處理的資料成為可能。


How to Generate Professional PDF Invoices in C#

程式化生成發票需要將結構化資料(如客戶資訊、行項目和計算)轉為精美的PDF文件。 IronPDF充分利用HTML和CSS,大多數開發人員已非常熟悉這些技術,這使得過程非常簡單。

在本教程中,我們將講解您在實際應用中可能遇到的場景。 您也可以在這裡下載下方顯示的項目。

如何構建發票HTML模板

使用IronPDF生成發票的基礎是HTML。 而不是撰寫底層的PDF繪圖命令,您可以使用標準HTML和CSS設計您的發票,然後讓IronPDF的基於Chrome的渲染引擎將其轉換成像素級精確的PDF。

以下是一個展示此方法的基本發票模板:

using IronPdf;

// Define the HTML template for a basic invoice
// Uses inline CSS for styling headers, tables, and totals
string invoiceHtml = @"
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; padding: 40px; }
.header { text-align: right; margin-bottom: 40px; }
.company-name { font-size: 24px; font-weight: bold; color: #333; }
.invoice-title { font-size: 32px; margin: 20px 0; }
.bill-to { margin: 20px 0; }
table { width: 100%; border-collapse: collapse; margin: 20px 0; }
th { background-color: #2A95D5; color: white; padding: 10px; text-align: left; }
td { padding: 10px; border-bottom: 1px solid #ddd; }
.total { text-align: right; font-size: 20px; font-weight: bold; margin-top: 20px; }
</style>
</head>
<body>
<div class='header'>
<div class='company-name'>Your Company Name</div>
<div>123 Business Street</div>
<div>City, State 12345</div>
</div>

<div class='invoice-title'>INVOICE</div>

<div class='bill-to'>
<strong>Bill To:</strong><br>
Customer Name<br>
456 Customer Avenue<br>
City, State 67890
</div>

<table>
<tr>
    <th>Description</th>
    <th>Quantity</th>
    <th>Price</th>
    <th>Total</th>
</tr>
<tr>
    <td>Web Development Services</td>
    <td>10 hours</td>
    <td>$100.00</td>
    <td>$1,000.00</td>
</tr>
<tr>
    <td>Consulting</td>
    <td>5 hours</td>
    <td>$150.00</td>
    <td>$750.00</td>
</tr>
</table>

<div class='total'>Total: $1,750.00</div>
</body>
</html>";

// Initialize the Chrome-based PDF renderer
var renderer = new ChromePdfRenderer();

// Convert the HTML string to a PDF document
var pdf = renderer.RenderHtmlAsPdf(invoiceHtml);

// Save the generated PDF to disk
pdf.SaveAs("basic-invoice.pdf");
C#

範例輸出

這種方法提供了豐富的靈活性。 在Chrome中可以使用的任何CSS都能在您的PDF中工作,包括像flexbox、grid布局和自定義字體等現代功能。 您甚至可以通過引用URL或本地文件路徑來使用外部樣式表和圖像。

如何新增動態行項目並計算總數

實際發票很少有靜態內容。 您需要從資料庫中填充行項目,計算小計,應用稅率,並格式化貨幣值。 以下範例展示了一種適合生產環境的動態發票生成模式:

using IronPdf;
using System;
using System.Collections.Generic;
using System.Linq;

// Represents a single line item on an invoice
public class InvoiceLineItem
{
    public string Description { get; set; }
    public decimal Quantity { get; set; }
    public decimal UnitPrice { get; set; }

    // Auto-calculates line total from quantity and unit price
    public decimal Total => Quantity * UnitPrice;
}

// Represents a complete invoice with customer details and line items
public class Invoice
{
    public string InvoiceNumber { get; set; }
    public DateTime InvoiceDate { get; set; }
    public string CustomerName { get; set; }
    public string CustomerAddress { get; set; }
    public List<InvoiceLineItem> LineItems { get; set; }

    // Computed properties for invoice totals
    public decimal Subtotal => LineItems.Sum(item => item.Total);
    public decimal TaxRate { get; set; } = 0.08m;  // Default 8% tax rate
    public decimal Tax => Subtotal * TaxRate;
    public decimal Total => Subtotal + Tax;
}

// Generates PDF invoices from Invoice objects using HTML templates
public class InvoiceGenerator
{
    public PdfDocument GenerateInvoice(Invoice invoice)
    {
        // Build HTML table rows dynamically from line items
        string lineItemsHtml = string.Join("", invoice.LineItems.Select(item => $@"
            <tr>
                <td>{item.Description}</td>
                <td>{item.Quantity}</td>
                <td>${item.UnitPrice:F2}</td>
                <td>${item.Total:F2}</td>
            </tr>
        "));

        // Build the complete HTML invoice using string interpolation
        // All invoice data is injected into the template dynamically
        string invoiceHtml = $@"
<!DOCTYPE html>
<html>
<head>
    <style>
        body {{font-family: Arial, sans-serif; padding: 40px;}}
        .header {{text-align: right; margin-bottom: 40px;}}
        .company-name {{font-size: 24px; font-weight: bold; color: #333;}}
        .invoice-details {{margin: 20px 0;}}
        table {{width: 100%; border-collapse: collapse; margin: 20px 0;}}
        th {{background-color: #2A95D5; color: white; padding: 10px; text-align: left;}}
        td {{padding: 10px; border-bottom: 1px solid #ddd;}}
        .totals {{text-align: right; margin-top: 20px;}}
        .totals div {{margin: 5px 0;}}
        .grand-total {{font-size: 20px; font-weight: bold; color: #2A95D5;}}
    </style>
</head>
<body>
    <div class='header'>
        <div class='company-name'>Your Company Name</div>
    </div>

    <h1>INVOICE</h1>

    <div class='invoice-details'>
        <strong>Invoice Number:</strong> {invoice.InvoiceNumber}<br>
        <strong>Date:</strong> {invoice.InvoiceDate:MMM dd, yyyy}<br>
        <strong>Bill To:</strong> {invoice.CustomerName}<br>
        {invoice.CustomerAddress}
    </div>

    <table>
        <tr>
            <th>Description</th>
            <th>Quantity</th>
            <th>Unit Price</th>
            <th>Total</th>
        </tr>
        {lineItemsHtml}
    </table>

    <div class='totals'>
        <div>Subtotal: ${invoice.Subtotal:F2}</div>
        <div>Tax ({invoice.TaxRate:P0}): ${invoice.Tax:F2}</div>
        <div class='grand-total'>Total: ${invoice.Total:F2}</div>
    </div>
</body>
</html>";

        // Render HTML to PDF and return the document
        var renderer = new ChromePdfRenderer();
        return renderer.RenderHtmlAsPdf(invoiceHtml);
    }
}
C#

範例輸出

Invoice類別包含所有發票資料及計算屬性,如小計、稅金和總額。 生成器使用字串插值將這些資料轉換為HTML,然後渲染為PDF。 這種責任分離使程式碼更易於維護和測試。

如何向發票新增公司品牌和水印

專業的發票需要品牌元素,如標誌,有時還需要水印來指示付款狀態。 IronPDF支持在HTML中嵌入圖像以及在渲染後進行程式化水印。

using IronPdf;

var renderer = new ChromePdfRenderer();

// Invoice HTML template with company logo embedded via URL
// Logo can also be Base64-encoded or a local file path
string htmlWithLogo = @"
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; padding: 40px; }
.logo { width: 200px; margin-bottom: 20px; }
</style>
</head>
<body>
<div style='text-align: center;'>
<img src='https://yourcompany.com/logo.png' alt='Company Logo' class='logo' />
</div>
<h1>INVOICE</h1>
<p><strong>Invoice Number:</strong> INV-2024-001</p>
<p><strong>Total:</strong> $1,250.00</p>
</body>
</html>";

// Render the HTML to PDF
var pdf = renderer.RenderHtmlAsPdf(htmlWithLogo);

// Apply a diagonal "UNPAID" watermark to mark invoice status
// 30% opacity keeps the content readable while the watermark is visible
pdf.ApplyWatermark("<h1 style='color: red;'>UNPAID</h1>",
    opacity: 30,
    rotation: 45,
    verticalAlignment: IronPdf.Editing.VerticalAlignment.Middle);

pdf.SaveAs("invoice-with-watermark.pdf");
C#

範例輸出

ApplyWatermark 方法接受HTML內容,讓您可以完全控制水印的外觀。 您可以調整透明度、旋轉和位置,以達到確切需要的外觀。 這對於標記發票為"已付款"、"草稿"或"已取消"而不需重新生成整個文件特別有用。

如何嵌入付款連結的QR碼

現代發票通常包括QR碼,客戶可以掃描來快速進行付款。 雖然IronPDF專注於PDF生成,但它與IronQR的條碼建立無縫配合:

using IronPdf;
using IronQr;
using IronSoftware.Drawing;

string invoiceNumber = "INV-2026-002";
decimal amount = 1500.00m;

// Create a payment URL with invoice details as query parameters
string paymentUrl = $"https://yourcompany.com/pay?invoice={invoiceNumber}&amount={amount}";

// Generate QR code from the payment URL using IronQR
QrCode qrCode = QrWriter.Write(paymentUrl);
AnyBitmap qrImage = qrCode.Save();
qrImage.SaveAs("payment-qr.png", AnyBitmap.ImageFormat.Png);

// Build invoice HTML with the QR code image embedded
// Customers can scan the QR to pay directly from their phone
string invoiceHtml = $@"
<!DOCTYPE html>
<html>
<head>
<style>
body {{ font-family: Arial, sans-serif; padding: 40px; }}
.payment-section {{ margin-top: 40px; text-align: center;
                   border-top: 2px solid #eee; padding-top: 20px; }}
.qr-code {{ width: 150px; height: 150px; }}
</style>
</head>
<body>
<h1>INVOICE {invoiceNumber}</h1>
<p><strong>Amount Due:</strong> ${amount:F2}</p>

<div class='payment-section'>
<p><strong>Scan to Pay Instantly:</strong></p>
<img src='payment-qr.png' alt='Payment QR Code' class='qr-code' />
<p style='font-size: 12px; color: #666;'>
    Or visit: {paymentUrl}
</p>
</div>
</body>
</html>";

// Convert HTML to PDF and save
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(invoiceHtml);
pdf.SaveAs($"invoice-{invoiceNumber}.pdf");
C#

範例輸出

QR碼直接連結到支付頁面,減少客戶摩擦,並加快現金流。 這種模式可用於支持基於URL支付啟動的任何支付提供商。


How to Comply with ZUGFeRD and Factur-X E-Invoicing Standards in C#

電子發票快速成為歐洲各地的強制性要求。 德國率先推出ZUGFeRD,法國隨後推出Factur-X。 這些標準將機器可讀的XML資料嵌入到PDF發票中,使自動化處理成為可能,同時保持可人閱讀的文件。 了解和實施這些標準對於在歐洲市場營運的企業越來越重要。

什麼是ZUGFeRD及其工作原理?

ZUGFeRD(Zentraler User Guide des Forums elektronische Rechnung Deutschland)是德國的電子發票標準,將發票資料作為XML文件附件嵌入在PDF/A-3合規文件內。 嵌入的XML允許無需OCR或解析即可自動提取資料。

該標準定義了三個合規層次,每個層次提供越來越多的結構化資料:

  • 基本: 包含核心發票資料,適合簡單的自動化處理
  • 舒適: 增加詳細資訊,支持完全自動化的發票處理
  • 擴展: 包括跨行業的複雜業務場景的全面資料

XML遵循UN/CEFACT跨行業發票(CII)模式,這已成為歐洲電子發票標準化的基礎。

什麼是Factur-X,與ZUGFeRD有何不同?

Factur-X是相同基礎標準的法國實施。 ZUGFeRD 2.0和Factur-X技術上是相同的。 它們共享相同的XML模式和基於歐洲規範EN 16931的合規概況。區別純屬地區性命名:按ZUGFeRD規格建立的發票在Factur-X下有效,反之亦然。

如何將XML資料嵌入PDF/A-3發票

IronPDF提供了建立合規電子發票所需的附件功能。 該過程涉及生產發票PDF,根據CII模式建立XML資料,並將XML作為附件嵌入,遵循正確的命名約定:

using System;
using System.Xml.Linq;

// Generates ZUGFeRD-compliant invoices by embedding structured XML data
// ZUGFeRD allows automated processing while keeping a human-readable PDF
public class ZUGFeRDInvoiceGenerator
{
    public void GenerateZUGFeRDInvoice(Invoice invoice)
    {
        // First, create the visual PDF that humans will read
        var renderer = new ChromePdfRenderer();
        string invoiceHtml = BuildInvoiceHtml(invoice);
        var pdf = renderer.RenderHtmlAsPdf(invoiceHtml);

        // Define the UN/CEFACT namespaces required by the ZUGFeRD standard
        // These are mandatory for compliance with European e-invoicing regulations
        XNamespace rsm = "urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100";
        XNamespace ram = "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100";
        XNamespace udt = "urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100";

        // Build the ZUGFeRD XML structure following the Cross-Industry Invoice schema
        var zugferdXml = new XDocument(
            new XDeclaration("1.0", "UTF-8", null),
            new XElement(rsm + "CrossIndustryInvoice",
                new XAttribute(XNamespace.Xmlns + "rsm", rsm.NamespaceName),
                new XAttribute(XNamespace.Xmlns + "ram", ram.NamespaceName),
                new XAttribute(XNamespace.Xmlns + "udt", udt.NamespaceName),

                // Document context identifies which e-invoicing guideline is being followed
                new XElement(rsm + "ExchangedDocumentContext",
                    new XElement(ram + "GuidelineSpecifiedDocumentContextParameter",
                        new XElement(ram + "ID", "urn:cen.eu:en16931:2017")
                    )
                ),

                // Core document identification: invoice number, type, and date
                new XElement(rsm + "ExchangedDocument",
                    new XElement(ram + "ID", invoice.InvoiceNumber),
                    new XElement(ram + "TypeCode", "380"), // 380 = Commercial Invoice per UN/CEFACT
                    new XElement(ram + "IssueDateTime",
                        new XElement(udt + "DateTimeString",
                            new XAttribute("format", "102"),
                            invoice.InvoiceDate.ToString("yyyyMMdd")
                        )
                    )
                ),

                // A complete implementation would include additional sections:
                // - Seller information (ram:SellerTradeParty)
                // - Buyer information (ram:BuyerTradeParty)
                // - Line items (ram:IncludedSupplyChainTradeLineItem)
                // - Payment terms (ram:SpecifiedTradePaymentTerms)
                // - Tax summaries (ram:ApplicableTradeTax)

                // Financial summary with all monetary totals
                new XElement(rsm + "SupplyChainTradeTransaction",
                    new XElement(ram + "ApplicableHeaderTradeSettlement",
                        new XElement(ram + "InvoiceCurrencyCode", "EUR"),
                        new XElement(ram + "SpecifiedTradeSettlementHeaderMonetarySummation",
                            new XElement(ram + "TaxBasisTotalAmount", invoice.Subtotal),
                            new XElement(ram + "TaxTotalAmount",
                                new XAttribute("currencyID", "EUR"),
                                invoice.Tax),
                            new XElement(ram + "GrandTotalAmount", invoice.Total),
                            new XElement(ram + "DuePayableAmount", invoice.Total)
                        )
                    )
                )
            )
        );

        // Save the XML to a temp file for embedding
        string xmlPath = $"zugferd-{invoice.InvoiceNumber}.xml";
        zugferdXml.Save(xmlPath);

        // Attach the XML to the PDF - filename must follow ZUGFeRD conventions
        pdf.Attachments.AddFile(xmlPath, "zugferd-invoice.xml", "ZUGFeRD Invoice Data");

        // Final PDF contains both visual invoice and machine-readable XML
        pdf.SaveAs($"invoice-{invoice.InvoiceNumber}-zugferd.pdf");
    }

    // Generates simple HTML for the visual portion of the invoice
    private string BuildInvoiceHtml(Invoice invoice)
    {
        return $@"
<!DOCTYPE html>
<html>
<head>
    <style>
        body {{font-family: Arial, sans-serif; padding: 40px;}}
        h1 {{color: #333;}}
        .zugferd-notice {{margin-top: 30px; padding: 10px; 
            background: #f0f0f0; font-size: 11px;}}
    </style>
</head>
<body>
    <h1>RECHNUNG / INVOICE</h1>
    <p><strong>Rechnungsnummer:</strong> {invoice.InvoiceNumber}</p>
    <p><strong>Datum:</strong> {invoice.InvoiceDate:dd.MM.yyyy}</p>
    <p><strong>Betrag:</strong> €{invoice.Total:F2}</p>
    
    <div class='zugferd-notice'>
        This invoice contains embedded ZUGFeRD data for automated processing.
    </div>
</body>
</html>";
    }
}
C#

範例輸出

合規的關鍵在於使用正確的XML名字空間,遵循CII模式結構,並以適當的文件名嵌入XML。 型別程式碼"380"明確將文件標識為UN/CEFACT標準中的商業發票。

如何為EU規定未來證明發票

歐盟正在逐步強制要求成員國間使用電子發票。 意大利已經要求用於B2B交易,法國則持續到2026年逐步實施,德國宣布在2025年開始強制性B2B電子發票。現在建支持ZUGFeRD/Factur-X的基礎,能為這些監管要求做好準備。

以下是針對不同標準的合規意識發票生成器的模式:

using IronPdf;
using System;

// Enum representing supported European e-invoicing standards
public enum InvoiceStandard
{
    None,
    ZUGFeRD,    // German standard - uses CII XML format
    FacturX,    // French standard - technically identical to ZUGFeRD 2.0
    Peppol      // Pan-European standard - uses UBL XML format
}

// Factory class that generates invoices compliant with different e-invoicing standards
// Allows switching between standards without changing core invoice generation logic
public class CompliantInvoiceGenerator
{
    public PdfDocument GenerateCompliantInvoice(Invoice invoice, InvoiceStandard standard)
    {
        // Generate the base PDF from HTML
        var renderer = new ChromePdfRenderer();
        string html = BuildInvoiceHtml(invoice);
        var pdf = renderer.RenderHtmlAsPdf(html);

        // Attach the appropriate XML format based on target market/regulation
        switch (standard)
        {
            case InvoiceStandard.ZUGFeRD:
            case InvoiceStandard.FacturX:
                // Both use Cross-Industry Invoice format, just different filenames
                EmbedCIIXmlData(pdf, invoice, standard);
                break;
            case InvoiceStandard.Peppol:
                // Peppol uses Universal Business Language format
                EmbedUBLXmlData(pdf, invoice);
                break;
        }

        return pdf;
    }

    // Creates and embeds CII-format XML (used by ZUGFeRD and Factur-X)
    private void EmbedCIIXmlData(PdfDocument pdf, Invoice invoice, InvoiceStandard standard)
    {
        string xml = GenerateCIIXml(invoice);

        // Filename convention differs between German and French standards
        string filename = standard == InvoiceStandard.ZUGFeRD
            ? "zugferd-invoice.xml"
            : "factur-x.xml";

        System.IO.File.WriteAllText("temp-invoice.xml", xml);
        pdf.Attachments.AddFile("temp-invoice.xml", filename, $"{standard} Invoice Data");
    }

    // Creates and embeds UBL-format XML for Peppol network compliance
    private void EmbedUBLXmlData(PdfDocument pdf, Invoice invoice)
    {
        // UBL (Universal Business Language) is the Peppol standard format
        string xml = $@"<?xml version='1.0' encoding='UTF-8'?>
<Invoice xmlns='urn:oasis:names:specification:ubl:schema:xsd:Invoice-2'>
    <id>{invoice.InvoiceNumber}</id>
    <IssueDate>{invoice.InvoiceDate:yyyy-MM-dd}</IssueDate>
    <DocumentCurrencyCode>EUR</DocumentCurrencyCode>
    <LegalMonetaryTotal>
        <PayableAmount currencyID='EUR'>{invoice.Total}</PayableAmount>
    </LegalMonetaryTotal>
</Invoice>";

        System.IO.File.WriteAllText("peppol-invoice.xml", xml);
        pdf.Attachments.AddFile("peppol-invoice.xml", "invoice.xml", "Peppol UBL Invoice");
    }

    // Generates minimal CII XML structure for demonstration
    private string GenerateCIIXml(Invoice invoice)
    {
        return $@"<?xml version='1.0' encoding='UTF-8'?>
<rsm:CrossIndustryInvoice
    xmlns:rsm='urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100'
    xmlns:ram='urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100'>
    <rsm:ExchangedDocument>
        <ram:ID>{invoice.InvoiceNumber}</ram:ID>
        <ram:TypeCode>380</ram:TypeCode>
    </rsm:ExchangedDocument>
</rsm:CrossIndustryInvoice>";
    }

    private string BuildInvoiceHtml(Invoice invoice)
    {
        return $"<html><body><h1>Invoice {invoice.InvoiceNumber}</h1></body></html>";
    }
}

此架構允許您在不重構核心發票生成邏輯的情況下新增新興標準。 基於枚舉的方法讓使用者或配置輕鬆決定使用何種合規模式。


我最喜歡的程式庫是IronPDF。它允許快速高效地操作PDF文件。它還有許多有價值的功能,例如導出到PDF/A格式和數位簽署PDF文件。

Milan Jovanovic

Microsoft MVP

查看案例研究

IronOCR意味著我們每年可以從手動處理中節省$40,000,同時提高生產力,釋放資源以進行高影響的任務。我會強烈推薦它。

Brent Matzelle

首席技術官,OPYN

查看案例研究

IronSuite在我們的運營中扮演著至關重要的角色。這些工具增加了包括建立平面圖和改善庫存管理在內的業務效率。

David Jones

首席軟體工程師,Agorus Build

查看案例研究

How to Extract Data from PDF Invoices in C#

生成發票只是問題的一半。 大多數企業還會收到供應商的發票,必須提取資料以進行處理。 IronPDF提供強大的文字提取功能,是發票資料捕獲的基礎。

如何從PDF發票中提取文字

最基本的提取操作是從PDF中檢索所有文字內容。 IronPDF的ExtractAllText方法處理PDF文字編碼和定位的複雜性:

using IronPdf;
using System;

// Extracts raw text content from PDF invoices for further processing
public class InvoiceTextExtractor
{
    // Extracts all text from a PDF in one operation
    // Best for single-page invoices or when you need the complete content
    public string ExtractInvoiceText(string pdfPath)
    {
        var pdf = PdfDocument.FromFile(pdfPath);

        // IronPDF handles the complexity of PDF text encoding and positioning
        string allText = pdf.ExtractAllText();
        Console.WriteLine("Full invoice text:");
        Console.WriteLine(allText);

        return allText;
    }

    // Extracts text page by page - useful for multi-page invoices
    // Allows you to process header info separately from line items
    public void ExtractTextByPage(string pdfPath)
    {
        var pdf = PdfDocument.FromFile(pdfPath);

        // Iterate through each page (0-indexed)
        for (int i = 0; i < pdf.PageCount; i++)
        {
            string pageText = pdf.ExtractTextFromPage(i);
            Console.WriteLine($"\n--- Page {i + 1} ---");
            Console.WriteLine(pageText);
        }
    }
}

逐頁提取對於多頁面發票特別有用,這時您需要定位特定部分,例如找到跨多頁的行項目,而頭資訊只出現在首頁。

如何提取行項目的表格資料

發票行項目通常以表格形式出現。 PDF缺少本地表結構,但您可以提取文字並解析構建表格資料:

using IronPdf;
using System;
using System.Collections.Generic;

// Data model for a single invoice line item
public class InvoiceLineItem
{
    public string Description { get; set; }
    public decimal Quantity { get; set; }
    public decimal UnitPrice { get; set; }
    public decimal Total { get; set; }
}

// Extracts tabular line item data from PDF invoices
// Note: PDFs don't have native table structure, so this uses text parsing
public class InvoiceTableExtractor
{
    public List<InvoiceLineItem> ExtractLineItems(string pdfPath)
    {
        var pdf = PdfDocument.FromFile(pdfPath);
        string text = pdf.ExtractAllText();

        var lineItems = new List<InvoiceLineItem>();
        string[] lines = text.Split('\n');

        foreach (string line in lines)
        {
            // Currency symbols indicate potential line items with amounts
            if (line.Contains("$") || line.Contains("€"))
            {
                Console.WriteLine($"Potential line item: {line.Trim()}");

                // Split on whitespace to separate columns
                // Actual parsing logic depends on your invoice format
                string[] parts = line.Split(new[] { '\t', ' ' },
                    StringSplitOptions.RemoveEmptyEntries);

                // Try to find numeric values that could be amounts
                foreach (string part in parts)
                {
                    string cleaned = part.Replace("$", "").Replace("€", "").Replace(",", "");
                    if (decimal.TryParse(cleaned, out decimal amount))
                    {
                        Console.WriteLine($"  Found amount: {amount:C}");
                    }
                }
            }
        }

        return lineItems;
    }
}

解析邏輯將依據發票格式而異。 對於來自已知供應商的固定格式發票,您可以構建特定格式的解析器。 對於各種格式,請考慮本文稍後介紹的AI驅動的提取。

如何使用模式匹配提取發票編號、日期和總額

正則表達式對於從發票文字中提取特定資料點非常有價值。 關鍵字段如發票編號、日期和總額通常遵循可識別的模式:

using IronPdf;
using System;
using System.Text.RegularExpressions;

// Data model for extracted invoice information
public class InvoiceData
{
    public string InvoiceNumber { get; set; }
    public string InvoiceDate { get; set; }
    public decimal TotalAmount { get; set; }
    public string VendorName { get; set; }
}

// Extracts key invoice fields using regex pattern matching
// Multiple patterns handle variations across different vendors
public class InvoiceParser
{
    public InvoiceData ParseInvoice(string pdfPath)
    {
        var pdf = PdfDocument.FromFile(pdfPath);
        string text = pdf.ExtractAllText();

        var invoiceData = new InvoiceData();

        // Try multiple patterns to find invoice number
        // Handles: "Invoice #123", "INV-123", "Invoice Number: 123", German "Rechnungsnummer"
        string[] invoiceNumberPatterns = new[]
        {
            @"Invoice\s*#?\s*:?\s*([A-Z0-9-]+)",
            @"INV[-\s]?(\d+)",
            @"Invoice\s+Number\s*:?\s*([A-Z0-9-]+)",
            @"Rechnungsnummer\s*:?\s*([A-Z0-9-]+)"
        };

        foreach (string pattern in invoiceNumberPatterns)
        {
            var match = Regex.Match(text, pattern, RegexOptions.IgnoreCase);
            if (match.Success)
            {
                invoiceData.InvoiceNumber = match.Groups[1].Value;
                Console.WriteLine($"Found Invoice Number: {invoiceData.InvoiceNumber}");
                break;
            }
        }

        // Date patterns for US, European, and written formats
        string[] datePatterns = new[]
        {
            @"Date\s*:?\s*(\d{1,2}[/-]\d{1,2}[/-]\d{2,4})",
            @"Invoice\s+Date\s*:?\s*(\d{1,2}[/-]\d{1,2}[/-]\d{2,4})",
            @"(\d{1,2}\.\d{1,2}\.\d{4})",  // European: DD.MM.YYYY
            @"(\w+\s+\d{1,2},?\s+\d{4})"   // Written: January 15, 2024
        };

        foreach (string pattern in datePatterns)
        {
            var match = Regex.Match(text, pattern, RegexOptions.IgnoreCase);
            if (match.Success)
            {
                invoiceData.InvoiceDate = match.Groups[1].Value;
                Console.WriteLine($"Found Date: {invoiceData.InvoiceDate}");
                break;
            }
        }

        // Look for total amount with various labels
        string[] totalPatterns = new[]
        {
            @"Total\s*:?\s*[\$€]?\s*([\d,]+\.\d{2})",
            @"Amount\s+Due\s*:?\s*[\$€]?\s*([\d,]+\.\d{2})",
            @"Grand\s+Total\s*:?\s*[\$€]?\s*([\d,]+\.\d{2})",
            @"Balance\s+Due\s*:?\s*[\$€]?\s*([\d,]+\.\d{2})"
        };

        foreach (string pattern in totalPatterns)
        {
            var match = Regex.Match(text, pattern, RegexOptions.IgnoreCase);
            if (match.Success)
            {
                // Remove commas before parsing
                string amountStr = match.Groups[1].Value.Replace(",", "");
                if (decimal.TryParse(amountStr, out decimal amount))
                {
                    invoiceData.TotalAmount = amount;
                    Console.WriteLine($"Found Total: ${invoiceData.TotalAmount:F2}");
                    break;
                }
            }
        }

        return invoiceData;
    }
}

這種模式化的方法非常適合具有可預測格式的發票。 多種模式變體可處理供應商間常見的格式差異,如"Invoice #"和"Invoice Number:"

那麼掃描或基於圖像的發票怎麼辦?

上面顯示的文字提取方法適用於包含內嵌文字的PDF。 然而,掃描的文件和基於圖像的PDF無法提取文字。 它們本質上是發票的圖片。

請注意: 對於處理掃描的發票,您將需要OCR(光學字元識別)功能。 IronOCR是Iron Suite的組成部分,在這些場景中與IronPDF無縫整合。 存取 https://ironsoftware.com/csharp/ocr/ 以了解更多有關從掃描文件和圖像中提取文字的資訊。

如何使用AI在.NET中處理發票

傳統模式匹配在標準化的發票上效果良好,但實際上的應付帳款部門會收到不同格式的文件。 AI驅動的提取在這裡發揮作用。 大型語言模型能夠理解發票語義,即使面對不熟悉的佈局,也能提取結構化資料。

如何整合AI進行發票解析

AI驅動發票處理的模式將IronPDF的文字提取與LLM API調用結合起來。 以下是一個通用實現,可以與任何OpenAI相容的API合作:

using IronPdf;
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

// Data model for extracted invoice information
public class InvoiceData
{
    public string InvoiceNumber { get; set; }
    public string InvoiceDate { get; set; }
    public string VendorName { get; set; }
    public decimal TotalAmount { get; set; }
}

// Leverages AI/LLM APIs to extract structured data from any invoice format
// Works with OpenAI or any compatible API endpoint
public class AIInvoiceParser
{
    private readonly HttpClient _httpClient;
    private readonly string _apiKey;
    private readonly string _apiUrl;

    public AIInvoiceParser(string apiKey, string apiUrl = "https://api.openai.com/v1/chat/completions")
    {
        _apiKey = apiKey;
        _apiUrl = apiUrl;
        _httpClient = new HttpClient();
        _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_apiKey}");
    }

    public async Task<InvoiceData> ParseInvoiceWithAI(string pdfPath)
    {
        // First extract raw text from the PDF using IronPDF
        var pdf = PdfDocument.FromFile(pdfPath);
        string invoiceText = pdf.ExtractAllText();

        // Construct a prompt that instructs the AI to return structured JSON
        // Being explicit about the format reduces parsing errors
        string prompt = $@"Extract the following information from this invoice text.
Return ONLY valid JSON with no additional text or markdown formatting.

Required fields:
- InvoiceNumber: The invoice or document number
- InvoiceDate: The invoice date in YYYY-MM-DD format
- VendorName: The company or person who sent the invoice
- TotalAmount: The total amount due as a number (no currency symbols)

Invoice text:
{invoiceText}

JSON response:";

        // Build the API request with a system prompt for context
        var requestBody = new
        {
            model = "gpt-4",
            messages = new[]
            {
                new {
                    role = "system",
                    content = "You are an invoice data extraction assistant. Extract structured data from invoices and return valid JSON only."
                },
                new { role = "user", content = prompt }
            },
            temperature = 0.1  // Low temperature ensures consistent, deterministic results
        };

        var json = JsonSerializer.Serialize(requestBody);
        var content = new StringContent(json, Encoding.UTF8, "application/json");

        var response = await _httpClient.PostAsync(_apiUrl, content);
        var responseJson = await response.Content.ReadAsStringAsync();

        // Navigate the API response structure to get the extracted content
        using var doc = JsonDocument.Parse(responseJson);
        var messageContent = doc.RootElement
            .GetProperty("choices")[0]
            .GetProperty("message")
            .GetProperty("content")
            .GetString();

        Console.WriteLine("AI Extracted Data:");
        Console.WriteLine(messageContent);

        // Deserialize the AI's JSON response into our data class
        var invoiceData = JsonSerializer.Deserialize<InvoiceData>(messageContent,
            new JsonSerializerOptions { PropertyNameCaseInsensitive = true });

        return invoiceData;
    }
}

低溫設置(0.1)鼓勵確定性輸出,這對於需要一致結果的資料提取任務很重要。

如何從發票提取結構化JSON資料

對於行項目、供應商詳細資訊和客戶資訊更加複雜的發票,您可以請求提供更豐富的JSON結構:

using IronPdf;
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;

// Comprehensive invoice data model with all details
public class DetailedInvoiceData
{
    public string InvoiceNumber { get; set; }
    public DateTime InvoiceDate { get; set; }
    public DateTime DueDate { get; set; }
    public VendorInfo Vendor { get; set; }
    public CustomerInfo Customer { get; set; }
    public List<LineItem> LineItems { get; set; }
    public decimal Subtotal { get; set; }
    public decimal Tax { get; set; }
    public decimal Total { get; set; }
}

public class VendorInfo
{
    public string Name { get; set; }
    public string Address { get; set; }
    public string TaxId { get; set; }
}

public class CustomerInfo
{
    public string Name { get; set; }
    public string Address { get; set; }
}

public class LineItem
{
    public string Description { get; set; }
    public decimal Quantity { get; set; }
    public decimal UnitPrice { get; set; }
    public decimal Total { get; set; }
}

// Extracts comprehensive invoice data including line items and party details
public class StructuredInvoiceExtractor
{
    private readonly AIInvoiceParser _aiParser;

    public StructuredInvoiceExtractor(string apiKey)
    {
        _aiParser = new AIInvoiceParser(apiKey);
    }

    public async Task<DetailedInvoiceData> ExtractDetailedData(string pdfPath)
    {
        var pdf = PdfDocument.FromFile(pdfPath);
        string text = pdf.ExtractAllText();

        // Define the exact JSON structure we want the AI to return
        // This schema guides the AI to extract all relevant fields
        string jsonSchema = @"{
  ""InvoiceNumber"": ""string"",
  ""InvoiceDate"": ""YYYY-MM-DD"",
  ""DueDate"": ""YYYY-MM-DD"",
  ""Vendor"": {
    ""Name"": ""string"",
    ""Address"": ""string"",
    ""TaxId"": ""string or null""
  },
  ""Customer"": {
    ""Name"": ""string"",
    ""Address"": ""string""
  },
  ""LineItems"": [
    {
      ""Description"": ""string"",
      ""Quantity"": 0.0,
      ""UnitPrice"": 0.00,
      ""Total"": 0.00
    }
  ],
  ""Subtotal"": 0.00,
  ""Tax"": 0.00,
  ""Total"": 0.00
}";

        // Prompt includes both the schema and the extracted text
        string prompt = $@"Extract all invoice data and return it in this exact JSON structure:
{jsonSchema}

Invoice text:
{text}

Return only valid JSON, no markdown formatting or additional text.";

        // Call AI API and parse response (implementation as shown above)
        // Return deserialized DetailedInvoiceData

        return new DetailedInvoiceData(); // Placeholder
    }
}

如何處理不一致的發票格式

AI提取的真正威力在於處理來自多個供應商的發票,每個供應商都有獨特的格式。 一個智能的處理器可以先嘗試基於模式的提取(速度快且免費),僅在需要時才退回AI處理:

using IronPdf;
using System.Threading.Tasks;

// Hybrid processor that optimizes for cost and capability
// Tries fast regex patterns first, uses AI only when patterns fail
public class SmartInvoiceProcessor
{
    private readonly AIInvoiceParser _aiParser;

    public SmartInvoiceProcessor(string aiApiKey)
    {
        _aiParser = new AIInvoiceParser(aiApiKey);
    }

    public async Task<InvoiceData> ProcessAnyInvoice(string pdfPath)
    {
        var pdf = PdfDocument.FromFile(pdfPath);
        string text = pdf.ExtractAllText();

        // First attempt: regex patterns (fast and free)
        var patternParser = new InvoiceParser();
        var standardResult = patternParser.ParseInvoiceFromText(text);

        // If pattern matching found all required fields, use that result
        if (IsComplete(standardResult))
        {
            Console.WriteLine("Pattern extraction successful");
            return standardResult;
        }

        // Fallback: use AI for complex or unusual invoice formats
        // This costs money but handles any layout
        Console.WriteLine("Using AI extraction for complex invoice format");
        var aiResult = await _aiParser.ParseInvoiceWithAI(pdfPath);

        return aiResult;
    }

    // Validates that we have the minimum required fields
    private bool IsComplete(InvoiceData data)
    {
        return !string.IsNullOrEmpty(data.InvoiceNumber) &&
               !string.IsNullOrEmpty(data.InvoiceDate) &&
               data.TotalAmount > 0;
    }
}

如何建立應付帳款自動化流程

將這些部分全部組合在一起,以下是一個完整的自動化流程,處理傳入發票,提取資料,驗證資料,並為您的會計系統做好準備:

using IronPdf;
using System;
using System.IO;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;

// Tracks the outcome of processing each invoice
public class ProcessingResult
{
    public string FileName { get; set; }
    public bool Success { get; set; }
    public string InvoiceNumber { get; set; }
    public string ErrorMessage { get; set; }
}

// Complete automation pipeline for accounts payable
// Watches a folder, extracts data, validates, and routes to accounting system
public class InvoiceAutomationPipeline
{
    private readonly SmartInvoiceProcessor _processor;
    private readonly string _inputFolder;
    private readonly string _processedFolder;
    private readonly string _errorFolder;

    public InvoiceAutomationPipeline(string apiKey, string inputFolder)
    {
        _processor = new SmartInvoiceProcessor(apiKey);
        _inputFolder = inputFolder;
        _processedFolder = Path.Combine(inputFolder, "processed");
        _errorFolder = Path.Combine(inputFolder, "errors");

        // Create output directories if they don't exist
        Directory.CreateDirectory(_processedFolder);
        Directory.CreateDirectory(_errorFolder);
    }

    // Main entry point - processes all PDFs in the input folder
    public async Task<List<ProcessingResult>> ProcessInvoiceBatch()
    {
        string[] invoiceFiles = Directory.GetFiles(_inputFolder, "*.pdf");
        Console.WriteLine($"Found {invoiceFiles.Length} invoices to process");

        var results = new List<ProcessingResult>();

        foreach (string invoicePath in invoiceFiles)
        {
            string fileName = Path.GetFileName(invoicePath);

            try
            {
                Console.WriteLine($"Processing: {fileName}");

                // Extract data using smart processor (patterns first, then AI)
                var invoiceData = await _processor.ProcessAnyInvoice(invoicePath);

                // Ensure we have minimum required fields before proceeding
                if (ValidateInvoiceData(invoiceData))
                {
                    // Send to accounting system (QuickBooks, Xero, etc.)
                    await SaveToAccountingSystem(invoiceData);

                    // Archive successful invoices
                    string destPath = Path.Combine(_processedFolder, fileName);
                    File.Move(invoicePath, destPath, overwrite: true);

                    results.Add(new ProcessingResult
                    {
                        FileName = fileName,
                        Success = true,
                        InvoiceNumber = invoiceData.InvoiceNumber
                    });

                    Console.WriteLine($"✓ Processed: {invoiceData.InvoiceNumber}");
                }
                else
                {
                    throw new Exception("Validation failed - missing required fields");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"✗ Failed: {fileName} - {ex.Message}");

                // Quarantine failed invoices for manual review
                string destPath = Path.Combine(_errorFolder, fileName);
                File.Move(invoicePath, destPath, overwrite: true);

                results.Add(new ProcessingResult
                {
                    FileName = fileName,
                    Success = false,
                    ErrorMessage = ex.Message
                });
            }
        }

        GenerateReport(results);
        return results;
    }

    // Checks for minimum required fields
    private bool ValidateInvoiceData(InvoiceData data)
    {
        return !string.IsNullOrEmpty(data.InvoiceNumber) &&
               !string.IsNullOrEmpty(data.VendorName) &&
               data.TotalAmount > 0;
    }

    // Placeholder for accounting system integration
    private async Task SaveToAccountingSystem(InvoiceData data)
    {
        // Integrate with your accounting system here
        // Examples: QuickBooks API, Xero API, SAP, or database storage
        Console.WriteLine($"  Saved invoice {data.InvoiceNumber} to accounting system");
        await Task.CompletedTask;
    }

    // Outputs a summary of the batch processing results
    private void GenerateReport(List<ProcessingResult> results)
    {
        int successful = results.Count(r => r.Success);
        int failed = results.Count(r => !r.Success);

        Console.WriteLine($"\n========== Processing Complete ==========");
        Console.WriteLine($"Total Processed: {results.Count}");
        Console.WriteLine($"Successful: {successful}");
        Console.WriteLine($"Failed: {failed}");

        if (failed > 0)
        {
            Console.WriteLine("\nFailed invoices requiring review:");
            foreach (var failure in results.Where(r => !r.Success))
            {
                Console.WriteLine($"  • {failure.FileName}: {failure.ErrorMessage}");
            }
        }
    }
}

這條流水線實現了完整的工作流程:掃描文件夾中的傳入PDF,處理每一個,驗證提取的資料,將成功提取的資料引導至您的會計系統,並將失敗記錄設置隔離以供人工審查。 摘要報告提供了對處理結果的可見性。


How to Integrate C# Invoice Processing with Accounting Systems

提取的發票資料最終需要流入會計系統以便付款和記錄保存。 具體方式因平台而異,但整合模式是一致的。

QuickBooks、Xero和SAP的常見整合模式是什麼?

大多數會計平台提供可程式化建立帳單或發票的REST API。 以下是一種可以根據您的特定平台進行調整的通用模式:

using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

// Generic integration layer for pushing invoice data to accounting systems
// Adapt the API calls based on your specific platform
public class AccountingSystemIntegration
{
    private readonly HttpClient _httpClient;
    private readonly string _apiKey;
    private readonly string _baseUrl;

    public AccountingSystemIntegration(string apiKey, string baseUrl)
    {
        _apiKey = apiKey;
        _baseUrl = baseUrl;
        _httpClient = new HttpClient();
        _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_apiKey}");
    }

    // Creates a Bill in QuickBooks (vendor invoices are called "Bills")
    public async Task SendToQuickBooks(InvoiceData invoice)
    {
        // QuickBooks Bill structure - see their API docs for full schema
        var bill = new
        {
            VendorRef = new { name = invoice.VendorName },
            TxnDate = invoice.InvoiceDate,
            DocNumber = invoice.InvoiceNumber,
            TotalAmt = invoice.TotalAmount,
            Line = new[]
            {
                new
                {
                    Amount = invoice.TotalAmount,
                    DetailType = "AccountBasedExpenseLineDetail",
                    AccountBasedExpenseLineDetail = new
                    {
                        AccountRef = new { name = "Accounts Payable" }
                    }
                }
            }
        };

        await PostToApi("/v3/company/{companyId}/bill", bill);
    }

    // Creates an accounts payable invoice in Xero
    public async Task SendToXero(InvoiceData invoice)
    {
        // ACCPAY type indicates this is a bill to pay (not a sales invoice)
        var bill = new
        {
            Type = "ACCPAY",
            Contact = new { Name = invoice.VendorName },
            Date = invoice.InvoiceDate,
            InvoiceNumber = invoice.InvoiceNumber,
            Total = invoice.TotalAmount
        };

        await PostToApi("/api.xro/2.0/Invoices", bill);
    }

    // Generic POST helper with error handling
    private async Task PostToApi(string endpoint, object payload)
    {
        string json = JsonSerializer.Serialize(payload);
        var content = new StringContent(json, Encoding.UTF8, "application/json");

        var response = await _httpClient.PostAsync($"{_baseUrl}{endpoint}", content);

        if (!response.IsSuccessStatusCode)
        {
            string error = await response.Content.ReadAsStringAsync();
            throw new Exception($"API Error: {response.StatusCode} - {error}");
        }

        Console.WriteLine($"Successfully posted to {endpoint}");
    }
}

每個平台都有自己的身份驗證機制(QuickBooks和Xero的OAuth,SAP的多種方法),必填字段和API約定。 請參考目標平台的文件以獲取具體資訊,但將提取的發票資料轉換為API有效負載的模式保持一致。

如何批量處理數百張發票

高容量發票處理需要仔細關注並發揮並發性和資源管理。 以下是使用並行處理及控制的並行度的模式:

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

// Tracks the result of processing a single invoice in a batch
public class BatchResult
{
    public string FilePath { get; set; }
    public bool Success { get; set; }
    public string InvoiceNumber { get; set; }
    public string Error { get; set; }
}

// High-volume invoice processor with controlled parallelism
// Prevents overwhelming APIs while maximizing throughput
public class BatchInvoiceProcessor
{
    private readonly SmartInvoiceProcessor _invoiceProcessor;
    private readonly AccountingSystemIntegration _accountingIntegration;
    private readonly int _maxConcurrency;

    public BatchInvoiceProcessor(string aiApiKey, string accountingApiKey,
        string accountingUrl, int maxConcurrency = 5)
    {
        _invoiceProcessor = new SmartInvoiceProcessor(aiApiKey);
        _accountingIntegration = new AccountingSystemIntegration(accountingApiKey, accountingUrl);
        _maxConcurrency = maxConcurrency;  // Adjust based on API rate limits
    }

    // Processes multiple invoices in parallel with controlled concurrency
    public async Task<List<BatchResult>> ProcessInvoiceBatch(List<string> invoicePaths)
    {
        // Thread-safe collection for gathering results from parallel tasks
        var results = new ConcurrentBag<BatchResult>();

        // Semaphore limits how many invoices process simultaneously
        var semaphore = new SemaphoreSlim(_maxConcurrency);

        // Create a task for each invoice
        var tasks = invoicePaths.Select(async path =>
        {
            // Wait for a slot to become available
            await semaphore.WaitAsync();
            try
            {
                var result = await ProcessSingleInvoice(path);
                results.Add(result);
            }
            finally
            {
                // Release slot for next invoice
                semaphore.Release();
            }
        });

        // Wait for all invoices to complete
        await Task.WhenAll(tasks);

        // Output summary statistics
        var resultList = results.ToList();
        int successful = resultList.Count(r => r.Success);
        int failed = resultList.Count(r => !r.Success);

        Console.WriteLine($"\nBatch Processing Complete:");
        Console.WriteLine($"  Total: {resultList.Count}");
        Console.WriteLine($"  Successful: {successful}");
        Console.WriteLine($"  Failed: {failed}");

        return resultList;
    }

    // Processes one invoice: extract data and send to accounting system
    private async Task<BatchResult> ProcessSingleInvoice(string pdfPath)
    {
        try
        {
            Console.WriteLine($"Processing: {pdfPath}");

            var invoiceData = await _invoiceProcessor.ProcessAnyInvoice(pdfPath);
            await _accountingIntegration.SendToQuickBooks(invoiceData);

            Console.WriteLine($"✓ Completed: {invoiceData.InvoiceNumber}");

            return new BatchResult
            {
                FilePath = pdfPath,
                Success = true,
                InvoiceNumber = invoiceData.InvoiceNumber
            };
        }
        catch (Exception ex)
        {
            Console.WriteLine($"✗ Failed: {pdfPath}");

            return new BatchResult
            {
                FilePath = pdfPath,
                Success = false,
                Error = ex.Message
            };
        }
    }
}

SemaphoreSlim 確保您不會對外部API造成過載,或耗盡系統資源。 根據您的API速率限制和伺服器容量調整_maxConcurrencyConcurrentBag 安全地收集並行操作的結果。


後續步驟

發票自動化代表著一個大幅減少人工工作、最小化錯誤和加速業務流程的重要機會。 本指南講解了完整的生命週期:從HTML模板生成專業發票,符合ZUGFeRD和Factur-X電子發票標準,從收到的發票中提取資料,使用模式匹配和AI驅動的處理,以及構建可擴展的自動化流程。

IronPDF是這些功能的基礎,提供強大的HTML到PDF渲染,可靠的文字提取及為PDF/A-3電子發票合規性所需的附件功能。 其基於Chrome的渲染引擎確保您的發票看起來正如您所設計,並且其提取方法自動處理PDF文字編碼的複雜性。

本文展示的模式是起點。 實際應用需要針對您特定的發票格式、會計系統和業務規則進行調整。 對於高容量情況,本批量處理教程涵蓋了控制的並行執行和錯誤恢復。

準備好開始構建了嗎? 下載IronPDF並嘗試免費試用。 該庫包含免費的開發授權,因此您可以在進入生產環境之前,完全評估發票生成、資料提取及PDF報告功能。 如果您對發票自動化或會計系統整合有疑問,請聯繫我們的工程支援團隊

常見問題

IronPDF在C#發票處理中有什麼應用?

IronPDF在C#發票處理中用於生成專業PDF發票,提取結構化資料,並自動化發票工作流程,同時確保符合ZUGFeRD和Factur-X等標準。

如何在C#中使用IronPDF生成PDF發票?

您可以通過利用IronPDF的API來程式化建立和自定義PDF文件,生成PDF發票。這包括新增構成發票的元素,如文字、表格和圖片。

什麼是ZUGFeRD和Factur-X,IronPDF如何支持它們?

ZUGFeRD和Factur-X是電子發票標準,確保發票既可供人閱讀又可供機器閱讀。IronPDF通過讓您生成符合這些規範的PDF發票來支持這些標準。

IronPDF如何幫助自動化應付賬款流程?

IronPDF可以通過從發票中提取結構化資料,並與自動化管道整合,來自動化應付賬款流程,減少手動資料輸入並提高效率。

IronPDF能否從現有的PDF發票中提取資料?

是的,IronPDF可以從現有的PDF發票中提取結構化資料,使得自動處理和分析發票資訊更加方便。

在C#中使用IronPDF進行發票處理有哪些好處?

在C#中使用IronPDF進行發票處理的好處包括簡化發票生成、符合國際發票標準、有效資料提取和增強的自動化能力。

是否可以使用IronPDF自定義PDF發票的外觀?

是的,IronPDF允許您通過新增各種設計元素,如標誌、文字格式和佈局調整來自定義PDF發票的外觀,以滿足品牌需求。

使用IronPDF自動化發票處理的典型步驟是什麼?

要使用IronPDF自動化發票處理,通常會生成發票,提取必要的資料,並與其他系統或自動化工具整合,以簡化工作流程。

IronPDF如何處理不同的發票格式?

IronPDF可以通過提供生成、操控和讀取PDF文件的工具來處理多種發票格式,確保其符合常見的電子發票標準。

Curtis Chau
技術作家

Curtis Chau擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。

...
閱讀更多

準備開始了嗎?

Nuget Downloads 20,667,543版本:2026.7剛剛發布

立即獲取您的免費30天試用密鑰
不需要信用卡或建立賬戶
C# 用於PDF的NuGet程式庫
使用NuGet安裝

版本: 2026.7

PM > Install-Package IronPdf
nuget.org/packages/IronPdf/
  1. 在解決方案資源管理器,右鍵點選參考,管理NuGet包
  2. 選擇瀏覽並搜尋"IronPdf"
  3. 選擇套件並安裝
C# PDF DLL
下載DLL

版本: 2026.7

立即下載

或者點擊此處下載Windows安裝程式。

  1. 下載並解壓IronPDF到類似~/Libs的位置,位於您的解決方案目錄中
  2. 在Visual Studio解決方案資源管理器,右鍵點選參考。選擇瀏覽,"IronPdf.dll"

授權從$999

有問題嗎?聯絡我們的開發團隊。

Key in blue circle

立即免費取得 30 天試用金鑰

無任何限制。100% 解鎖。無需信用卡。

bullet_checked無需信用卡或建立帳號無任何限制。100% 解鎖。無需信用卡。
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
預訂您的免費現場演示
Booking Badge

受到全球數百萬工程師的信任

Iron Software的客戶標誌
獲取您的無義務諮詢
填寫以下表格或電子郵件sales@ironsoftware.com
您的詳細資訊將始終保密
受到全球數百萬工程師的信任
Iron Software的客戶標誌
立即獲取您的30天試用金鑰
無需信用卡或帳戶建立