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

This article was translated from English: Does it need improvement?
Translated
View the article in English

C# .NET ile IronPDF'de fatura işleme, döküman yaşam döngüsünün tamamını kapsar: HTML şablonlarından profesyonel PDF faturaları oluşturma, ZUGFeRD ve Factur-X e-fatura standartlarına uyum sağlama, alınan faturalardan yapılandırılmış veri çıkarma ve AI destekli işleme ile muhasebe sistemleriyle entegre olan toplu otomasyon hatları kurma.

Kısa Başlangıç Rehberi

Bu eğitim, C# .NET'te PDF faturalarını oluşturma, çıkarma ve otomatikleştirme süreçlerini kapsar, e-fatura uyumluluğunu, AI destekli ayrıştırmayı ve muhasebe sistemi entegrasyonunu içerir.

  • Kimler için: Faturalama modülleri, alacak hesapları otomasyonu veya e-fatura uyumluluğu geliştiren .NET geliştiricileri.
  • Ne inşa edeceksiniz: Kalem ve vergi hesaplamaları ile HTML şablonlu fatura üretimi, ödeme bağlantıları için QR kodları, ZUGFeRD/Factur-X uyumlu PDF/A-3 çıktısı, regex ile metin çıkarma, AI destekli fatura ayrıştırma ve muhasebe sistemi entegrasyonu ile toplu işlem.
  • Çalıştığı yer: .NET 10, .NET 8 LTS, .NET Framework 4.6.2+ ve .NET Standard 2.0. Harici hizmet bağımlılığı yok.
  • Bu yaklaşımı ne zaman kullanmalı: Fatura PDF'leri oluşturmanız, AB e-fatura zorunluluklarına uymak veya satıcı faturalarından alacak hesapları için veri çıkarmak gerektiğinde.
  • Neden teknik olarak önemli: IronPDF, piksel mükemmel doğrulukla HTML'den PDF'ye dönüştürür, gömülü XML için PDF/A-3'ü destekler ve yapılandırılmamış faturaları yapılandırılmış verilere dönüştürmek için regex veya AI ile eşleşen metin çıkarma API'leri sağlar.

Sadece birkaç satır kodla ilk PDF faturalarınızı oluşturun:

  1. NuGet Paket Yöneticisi ile https://www.nuget.org/packages/IronPdf yükleyin

    PM > Install-Package IronPdf
  2. Bu kod parçasını kopyalayıp çalıştırın.

    var renderer = new IronPdf.ChromePdfRenderer();
    var pdf = renderer.RenderHtmlAsPdf("<h1>Invoice #1001</h1><p>Total: $500.00</p>");
    pdf.SaveAs("invoice.pdf");
  3. Canlı ortamınızda test etmek için dağıtın

    Bugün projenizde IronPDF kullanmaya başlayın ücretsiz deneme ile

    arrow pointer

IronPDF'nin 30 günlük deneme sürümünü satın aldıktan veya kaydolduktan sonra, uygulamanızın başlangıcında lisans anahtarınızı ekleyin.

IronPdf.License.LicenseKey = "KEY";
IronPdf.License.LicenseKey = "KEY";
Imports IronPdf

IronPdf.License.LicenseKey = "KEY"
$vbLabelText   $csharpLabel

!{--0100110001001001010000100101001001000001010100100101100101011111--}

NuGet NuGet ile Yükle

PM >  Install-Package IronPdf

IronPDF üzerine NuGet için hızlı bir kurulum kontrol edin. 10 milyondan fazla indirme ile C# ile PDF geliştirmesini dönüştürüyor. DLL veya Windows yükleyicisini de indirebilirsiniz.

İçindekiler

NuGet NuGet ile Yükle

PM >  Install-Package IronPdf

IronPDF üzerine NuGet için hızlı bir kurulum kontrol edin. 10 milyondan fazla indirme ile C# ile PDF geliştirmesini dönüştürüyor. DLL veya Windows yükleyicisini de indirebilirsiniz.

Fatura Yaşam Döngüsü Nedir ve Neden PDF Standart Olarak Kalır?

Koda dalmadan önce, modern bir iş sisteminde bir faturanın geçtiği tam yolculuğu anlamaya yardımcı olur. Fatura yaşam döngüsü beş farklı aşamadan oluşur: oluşturma, dağıtım, alım, veri çıkarma ve muhasebe entegrasyonu.

Fatura süreci, oluşturulma ile başlar. Bir işletme, kalemler, fiyatlandırma, vergi hesaplamaları, ödeme şartları ve marka unsurlarını içeren bir fatura oluşturur. Fatura, profesyonel görünmeli ve tüm yasal gereklilikleri karşılamalıdır. Sonrasında, faturanın müşteriye e-posta, müşteri portalı veya geleneksel posta yoluyla gönderildiği dağıtım aşaması gelir. Müşteri onu aldığında, alacak hesapları ekibi belgeyi alır ve işleme hazırlanmaya başlar. Veri çıkarma, satıcı bilgileri, kalemler, toplamlar ve vade tarihleri gibi fatura üzerinden anahtar bilgileri çeker, böylece bu bilgiler kontrol edilebilir ve satın alma siparişlerine uydurulabilir. Son olarak, muhasebe entegrasyonu bu verileri QuickBooks, Xero veya SAP gibi finansal sistemlere ödeme ve kayıt tutma için hareket ettirir.

Peki neden PDF, bu kadar yıldır hala en çok kullanılan format? Bu, avantajların eşsiz bir karışımıyla ilgilidir. PDF'ler, fatura biçiminizi hangi cihaz veya işletim sistemini kullandığınızdan bağımsız olarak tutarlı tutar. Birisi Windows'da, Mac'te veya telefonunda faturanızı açtığında, onu tasarladığınız gibi görünür. PDF'ler ayrıca yanlışlıkla değiştirilmeleri zor olduğu için belgelerinizin bütünlüğünü Word veya Excel gibi formatlardan daha iyi korur. Otantiklik için dijital imzalar ekleyebilir ve güvenlik için şifreleme kullanabilirsiniz. En önemlisi, PDF'ler her iş sisteminin tanıdığı ve desteklediği evrensel bir standart haline gelmiştir.

Tabii ki, bir zorluk var. PDF'ler insanların okuması için yapılmışken, bilgisayarların işlemesi için değil. Bilgileri yapılandırılmış verilerde saklamak yerine, bir PDF, metin, çizgiler, şekiller ve resimleri sayfa üzerinde göründükleri yere göre kaydeder. Bu nedenle, IronPDF gibi araçlar çok faydalıdır, onlar, kullanıcı dostu belgeleri yazılım ile çalışılabilir verilere dönüştürme imkanı sağlar.


How to Generate Professional PDF Invoices in C

Faturaları programatik olarak oluşturmak, müşteri bilgileri, kalemler ve hesaplamalar gibi yapılandırılmış verileri cilalı bir PDF belgesine dönüştürmeyi gerektirir. IronPDF, çoğu geliştiricinin zaten iyi bildiği HTML ve CSS teknolojilerinden yararlanarak bunu olağanüstü derecede anlaşılır yapar.

Bu eğitimde, gerçek dünyada karşılaşacağınız olası senaryolar üzerinden geçeceğiz. Aşağıda gösterilen projeyi buradan da indirebilirsiniz.

Fatura HTML Şablonu Nasıl Oluşturulur

IronPDF ile fatura oluşturmanın temeli HTML'dir. Düşük seviyeli PDF çizim komutlarıyla uğraşmak yerine, faturalarınızı standart HTML ve CSS kullanarak tasarlar, ardından IronPDF'nin Chrome tabanlı işleme motorunun bunu piksel mükemmel bir PDF'ye dönüştürmesine izin verirsiniz.

İşte yaklaşımı gösteren temel bir fatura şablonu:

:path=/static-assets/pdf/content-code-examples/tutorials/csharp-invoice-processing/basic-invoice-template.cs
using IronPdf;

// Define the HTML template for a basic invoice
// Uses inline CSS for styling headers, tables, and totals
string invoiceHtml = @"
E html>


le>
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; }
yle>


 class='header'>
<div class='company-name'>Your Company Name</div>
<div>123 Business Street</div>
<div>City, State 12345</div>
v>

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

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

le>
<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>
ble>

 class='total'>Total: $1,750.00</div>

;

// 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");
Imports IronPdf

' Define the HTML template for a basic invoice
' Uses inline CSS for styling headers, tables, and totals
Dim invoiceHtml As String = "
<!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
Dim renderer As New ChromePdfRenderer()

' Convert the HTML string to a PDF document
Dim pdf = renderer.RenderHtmlAsPdf(invoiceHtml)

' Save the generated PDF to disk
pdf.SaveAs("basic-invoice.pdf")
$vbLabelText   $csharpLabel

Örnek Çıktı

Bu yaklaşım muazzam esneklik sunar. Chrome'da çalışan herhangi bir CSS, flexbox, grid düzenler ve özel yazı tipleri gibi modern özellikler de dahil, PDF'nizde çalışacaktır. Hatta URL'ler veya yerel dosya yollarını referans alarak harici stil sayfalarını ve resimleri kullanabilirsiniz.

Dinamik Kalemler Nasıl Eklenir ve Toplamlar Nasıl Hesaplanır

Gerçek faturalar nadiren statik içerik barındırır. Veritabanından kalemleri doldurmanız, ara toplamları hesaplamanız, vergi oranlarını uygulamanız ve para birimi değerlerini biçimlendirmeniz gerekir. Aşağıdaki örnek, dinamik fatura oluşturma için üretime hazır bir deseni gösterir:

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);
    }
}
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);
    }
}
Imports IronPdf
Imports System
Imports System.Collections.Generic
Imports System.Linq

' Represents a single line item on an invoice
Public Class InvoiceLineItem
    Public Property Description As String
    Public Property Quantity As Decimal
    Public Property UnitPrice As Decimal

    ' Auto-calculates line total from quantity and unit price
    Public ReadOnly Property Total As Decimal
        Get
            Return Quantity * UnitPrice
        End Get
    End Property
End Class

' Represents a complete invoice with customer details and line items
Public Class Invoice
    Public Property InvoiceNumber As String
    Public Property InvoiceDate As DateTime
    Public Property CustomerName As String
    Public Property CustomerAddress As String
    Public Property LineItems As List(Of InvoiceLineItem)

    ' Computed properties for invoice totals
    Public ReadOnly Property Subtotal As Decimal
        Get
            Return LineItems.Sum(Function(item) item.Total)
        End Get
    End Property

    Public Property TaxRate As Decimal = 0.08D ' Default 8% tax rate

    Public ReadOnly Property Tax As Decimal
        Get
            Return Subtotal * TaxRate
        End Get
    End Property

    Public ReadOnly Property Total As Decimal
        Get
            Return Subtotal + Tax
        End Get
    End Property
End Class

' Generates PDF invoices from Invoice objects using HTML templates
Public Class InvoiceGenerator
    Public Function GenerateInvoice(invoice As Invoice) As PdfDocument
        ' Build HTML table rows dynamically from line items
        Dim lineItemsHtml As String = String.Join("", invoice.LineItems.Select(Function(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
        Dim invoiceHtml As String = $"
<!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
        Dim renderer As New ChromePdfRenderer()
        Return renderer.RenderHtmlAsPdf(invoiceHtml)
    End Function
End Class
$vbLabelText   $csharpLabel

Örnek Çıktı

Invoice sinifi, alt toplam, vergi ve toplam icin hesaplanan özelliklerle tüm fatura verilerini kapsar. Jeneratör, bu verileri dize enterpolasyonu kullanarak HTML'ye dönüştürür, ardından PDF'ye işler. Bu sorumlulukların ayrılması, kodun bakımı kolay ve test edilebilir olmasını sağlar.

Faturalara Şirket Markalaması ve Filigranlar Nasıl Eklenir

Profesyonel faturalar, ödeme durumu belirten logolar ve bazı durumlarda filigranlar gibi marka unsurlarına ihtiyaç duyar. IronPDF, hem HTML'de yerleştirilmiş görüntüleri hem de işlendikten sonra programlı olarak filigran eklemeyi destekler.

:path=/static-assets/pdf/content-code-examples/tutorials/csharp-invoice-processing/branding-watermarks.cs
using IronPdf;
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 = @"
E html>


le>
body { font-family: Arial, sans-serif; padding: 40px; }
.logo { width: 200px; margin-bottom: 20px; }
yle>


 style='text-align: center;'>
<img src='https://yourcompany.com/logo.png' alt='Company Logo' class='logo' />
v>
INVOICE</h1>
strong>Invoice Number:</strong> INV-2024-001</p>
strong>Total:</strong> $1,250.00</p>

;

// 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");
using IronPdf;
Imports IronPdf

Dim renderer As New ChromePdfRenderer()

' Invoice HTML template with company logo embedded via URL
' Logo can also be Base64-encoded or a local file path
Dim htmlWithLogo As String = "
<!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' />
        <h1>INVOICE</h1>
        <p><strong>Invoice Number:</strong> INV-2024-001</p>
        <p><strong>Total:</strong> $1,250.00</p>
    </div>
</body>
</html>
"

' Render the HTML to PDF
Dim 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")
$vbLabelText   $csharpLabel

Örnek Çıktı

ApplyWatermark metodu, filigranın görünümü üzerinde tam kontrol sağlayarak HTML içeriğini kabul eder. İhtiyaç duyduğunuz görünümü elde etmek için opaklık, döndürme ve yerleştirme ayarlarını düzenleyebilirsiniz. "ÖDENDİ", "TASLAK" veya "İPTAL EDİLDİ" olarak işaretlemek için tüm belgeyi yeniden oluşturmadan faturaları işaretlemek bu şekilde oldukça faydalıdır.

Ödeme Bağlantıları için Kare Kodları Nasıl Gömerim

Modern faturalar genellikle QR kodları içerir, böylece müşteriler hızlı bir şekilde ödeme yapabilir. IronPDF, PDF oluşturma konusunda odaklanırken, IronQR ile sorunsuz bir şekilde çalışarak barkod oluşturma işlemi sağlar:

:path=/static-assets/pdf/content-code-examples/tutorials/csharp-invoice-processing/qr-code-payment.cs
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 = $@"
E html>


le>
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; }}
yle>


INVOICE {invoiceNumber}</h1>
strong>Amount Due:</strong> ${amount:F2}</p>

 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>
v>

;

// Convert HTML to PDF and save
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(invoiceHtml);
pdf.SaveAs($"invoice-{invoiceNumber}.pdf");
Imports IronPdf
Imports IronQr
Imports IronSoftware.Drawing

Dim invoiceNumber As String = "INV-2026-002"
Dim amount As Decimal = 1500.00D

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

' Generate QR code from the payment URL using IronQR
Dim qrCode As QrCode = QrWriter.Write(paymentUrl)
Dim qrImage As AnyBitmap = 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
Dim invoiceHtml As String = $"
<!DOCTYPE html>
<html>
<head>
    <title>Invoice</title>
    <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
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(invoiceHtml)
pdf.SaveAs($"invoice-{invoiceNumber}.pdf")
$vbLabelText   $csharpLabel

Örnek Çıktı

QR kodu, müşteriler için sürtünmeyi azaltarak ve nakit akışınızı hızlandırarak doğrudan bir ödeme sayfasına bağlanır. Bu desen, URL tabanlı ödeme başlatımını destekleyen herhangi bir ödeme sağlayıcısı ile çalışır.


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

Elektronik faturalandırma, Avrupa genelinde hızla zorunlu hale gelmektedir. Almanya, ZUGFeRD ile öncülük etti ve ardından Fransa, Factur-X ile takip etti. Bu standartlar, PDF faturaları içerisine makine tarafından okunabilir XML verilerini entegre eder ve bu, belgelerin otomatik işlenmesine olanak tanırken, insan tarafından okunabilir belgeleri korur. Bu standartları anlamak ve uygulamak, Avrupa pazarlarında faaliyet gösteren işletmeler için giderek daha önemli hale gelir.

ZUGFeRD Nedir ve Nasıl Çalışır?

ZUGFeRD (Zentraler User Guide des Forums elektronische Rechnung Deutschland), fatura verilerini bir XML dosya eki olarak, PDF/A-3 uyumlu bir doküman içerisine gömen Alman e-fatura standardıdır. Gömülü XML, OCR ya da ayıklama işlemi gerektirmeden otomatik veri çıkarmaya olanak tanır.

Standart, giderek daha fazla yapılandırılmış veri sunan üç uygunluk seviyesi tanımlar:

  • Basic: Basit otomatik işlemeye uygun çekirdek fatura verilerini içerir
  • Comfort: Tam otomatik fatura yönetimini mümkün kılan detaylı bilgi ekler
  • Extended: Sektörler arası karmaşık iş senaryoları için kapsamlı verileri içerir

XML, Avrupa e-faturalama standardizasyonunun temeli haline gelen UN/CEFACT Çapraz Endüstri Fatura (CII) şemasını takip eder.

Factur-X Nedir ve ZUGFeRD'den Nasıl Farklıdır?

Factur-X, aynı temel standardın Fransız uygulamasıdır. ZUGFeRD 2.0 ve Factur-X teknik olarak aynıdır. Avrupa Normu EN 16931'e dayanan aynı XML şeması ve uygunluk profillerini paylaşır. Fark sadece bölgesel adlandırmadadır: ZUGFeRD spesifikasyonlarına göre oluşturulan bir fatura, Factur-X altındayken geçerli olacaktır ve tersi de doğrudur.

PDF/A-3 Faturalarına XML Verisi Nasıl Gömülür

IronPDF, uyumlu e-faturalar oluşturmak için gereken ek yeteneklerini sağlar. Süreç, fatura PDF'nizi oluşturmayı, CII şemasına göre XML verilerini oluşturmayı ve uygun isimlendirme kuralları ile eki olarak XML'i gömmeyi içerir:

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>";
    }
}
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>";
    }
}
Imports System
Imports 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 Sub GenerateZUGFeRDInvoice(invoice As Invoice)
        ' First, create the visual PDF that humans will read
        Dim renderer = New ChromePdfRenderer()
        Dim invoiceHtml As String = BuildInvoiceHtml(invoice)
        Dim pdf = renderer.RenderHtmlAsPdf(invoiceHtml)

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

        ' Build the ZUGFeRD XML structure following the Cross-Industry Invoice schema
        Dim zugferdXml = New XDocument(
            New XDeclaration("1.0", "UTF-8", Nothing),
            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
        Dim xmlPath As String = $"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")
    End Sub

    ' Generates simple HTML for the visual portion of the invoice
    Private Function BuildInvoiceHtml(invoice As Invoice) As String
        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>"
    End Function
End Class
$vbLabelText   $csharpLabel

Örnek Çıktı

Uyumun önemli yönleri, doğru XML ad alanlarını kullanmak, CII şeması yapısını takip etmek ve uygun bir dosya adı ile XML'i gömmektir. TypeCode "380", özellikle dokümanı UN/CEFACT standardı içerisinde ticari fatura olarak tanımlar.

AB Yönergelerine Uygun Olarak Faturaları Geleceğe Hazırlamak

Avrupa Birliği, üye devletlerde e-faturalamayı giderek zorunlu hale getiriyor. İtalya, B2B işlemler için zaten zorunlu tutuyor, Fransa 2026'ya kadar gereklilikleri aşamalı olarak uyguluyor ve Almanya 2025'ten itibaren B2B e-faturalandırmayı zorunlu hale getireceğini duyurdu. Şimdi ZUGFeRD/Factur-X desteği oluşturmak, sisteminizi bu yasal gerekliliklere hazırlayacaktır.

İşte farklı standartları hedefleyebilen bir uyum odaklı fatura jeneratörü modeli:

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>";
    }
}
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>";
    }
}
Imports IronPdf
Imports 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
End Enum

' 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 Function GenerateCompliantInvoice(invoice As Invoice, standard As InvoiceStandard) As PdfDocument
        ' Generate the base PDF from HTML
        Dim renderer As New ChromePdfRenderer()
        Dim html As String = BuildInvoiceHtml(invoice)
        Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf(html)

        ' Attach the appropriate XML format based on target market/regulation
        Select Case standard
            Case InvoiceStandard.ZUGFeRD, InvoiceStandard.FacturX
                ' Both use Cross-Industry Invoice format, just different filenames
                EmbedCIIXmlData(pdf, invoice, standard)
            Case InvoiceStandard.Peppol
                ' Peppol uses Universal Business Language format
                EmbedUBLXmlData(pdf, invoice)
        End Select

        Return pdf
    End Function

    ' Creates and embeds CII-format XML (used by ZUGFeRD and Factur-X)
    Private Sub EmbedCIIXmlData(pdf As PdfDocument, invoice As Invoice, standard As InvoiceStandard)
        Dim xml As String = GenerateCIIXml(invoice)

        ' Filename convention differs between German and French standards
        Dim filename As String = If(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")
    End Sub

    ' Creates and embeds UBL-format XML for Peppol network compliance
    Private Sub EmbedUBLXmlData(pdf As PdfDocument, invoice As Invoice)
        ' UBL (Universal Business Language) is the Peppol standard format
        Dim xml As String = $"<?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")
    End Sub

    ' Generates minimal CII XML structure for demonstration
    Private Function GenerateCIIXml(invoice As Invoice) As String
        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>"
    End Function

    Private Function BuildInvoiceHtml(invoice As Invoice) As String
        Return $"<html><body><h1>Invoice {invoice.InvoiceNumber}</h1></body></html>"
    End Function
End Class
$vbLabelText   $csharpLabel

Bu mimari, çekirdek fatura oluşturma mantığınızı yeniden yapılandırmadan yeni standartlar eklemenize olanak tanır. Enum tabanlı yaklaşım, kullanıcıların veya yapılandırmanın hangi uyum modunu kullanacağını belirlemesini kolaylaştırır.


How to Extract Data from PDF Invoices in C

Fatura oluşturmak, işin sadece yarısıdır. Çoğu işletme ayrıca satıcılardan faturalar alır ve işleme için veri çıkarması gerekir. IronPDF, fatura veri yakalamanın temelini oluşturan güçlü metin çıkarma yetenekleri sağlar.

PDF Faturasından Metin Nasıl Çıkarılır

En temel çıkarma işlemi, bir PDF'den tüm metin içeriğini alır. IronPDF'in ExtractAllText metodu, PDF metin kodlamasinin ve konumlandirmanin zorlugunu ele alir:

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);
        }
    }
}
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);
        }
    }
}
Imports IronPdf
Imports 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 Function ExtractInvoiceText(pdfPath As String) As String
        Dim pdf = PdfDocument.FromFile(pdfPath)

        ' IronPDF handles the complexity of PDF text encoding and positioning
        Dim allText As String = pdf.ExtractAllText()
        Console.WriteLine("Full invoice text:")
        Console.WriteLine(allText)

        Return allText
    End Function

    ' Extracts text page by page - useful for multi-page invoices
    ' Allows you to process header info separately from line items
    Public Sub ExtractTextByPage(pdfPath As String)
        Dim pdf = PdfDocument.FromFile(pdfPath)

        ' Iterate through each page (0-indexed)
        For i As Integer = 0 To pdf.PageCount - 1
            Dim pageText As String = pdf.ExtractTextFromPage(i)
            Console.WriteLine(vbCrLf & "--- Page " & (i + 1).ToString() & " ---")
            Console.WriteLine(pageText)
        Next
    End Sub
End Class
$vbLabelText   $csharpLabel

Sayfa sayfa çıkarma işlemi, özellikle çok sayfalı faturalar için yararlıdır; burada birden fazla sayfaya yayılan satır öğelerini bulmanız gerekirken, başlık bilgisi sadece ilk sayfada görünür.

Çizgi Öğeleri İçin Tablo Verisi Nasıl Çıkarılır

Fatura çizgi öğeleri, genellikle tablo formatında görünür. PDF'ler, doğal bir tablo yapısına sahip değildir, ancak metni çıkarabilir ve tablo verilerini yeniden oluşturmak için ayrıştırabilirsiniz:

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;
    }
}
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;
    }
}
Imports IronPdf
Imports System
Imports System.Collections.Generic

' Data model for a single invoice line item
Public Class InvoiceLineItem
    Public Property Description As String
    Public Property Quantity As Decimal
    Public Property UnitPrice As Decimal
    Public Property Total As Decimal
End Class

' 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 Function ExtractLineItems(pdfPath As String) As List(Of InvoiceLineItem)
        Dim pdf = PdfDocument.FromFile(pdfPath)
        Dim text As String = pdf.ExtractAllText()

        Dim lineItems As New List(Of InvoiceLineItem)()
        Dim lines() As String = text.Split(ControlChars.Lf)

        For Each line As String In lines
            ' Currency symbols indicate potential line items with amounts
            If line.Contains("$") OrElse line.Contains("€") Then
                Console.WriteLine($"Potential line item: {line.Trim()}")

                ' Split on whitespace to separate columns
                ' Actual parsing logic depends on your invoice format
                Dim parts() As String = line.Split(New Char() {ControlChars.Tab, " "c}, StringSplitOptions.RemoveEmptyEntries)

                ' Try to find numeric values that could be amounts
                For Each part As String In parts
                    Dim cleaned As String = part.Replace("$", "").Replace("€", "").Replace(",", "")
                    Dim amount As Decimal
                    If Decimal.TryParse(cleaned, amount) Then
                        Console.WriteLine($"  Found amount: {amount:C}")
                    End If
                Next
            End If
        Next

        Return lineItems
    End Function
End Class
$vbLabelText   $csharpLabel

Ayrıştırma mantığı, fatura formatlarınıza bağlı olarak değişiklik gösterecektir. Bilinen satıcılara ait tutarlı düzenlere sahip faturalar için format-spesifik ayrıştırıcılar oluşturabilirsiniz. Farklı formatlar için, bu makalede daha sonra ele alınan yapay zeka destekli çıkarım seçeneğini düşünebilirsiniz.

Fatura Numaraları, Tarihler ve Toplamlar için Kalıp Eşleştirme Nasıl Kullanılır

Düzenli ifadeler, fatura metninden belirli veri noktalarını çıkarmak için oldukça değerlidir. Fatura numaraları, tarihler ve toplamlar gibi anahtar alanlar genellikle tanınabilir kalıpları izler:

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;
    }
}
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;
    }
}
Imports IronPdf
Imports System
Imports System.Text.RegularExpressions

' Data model for extracted invoice information
Public Class InvoiceData
    Public Property InvoiceNumber As String
    Public Property InvoiceDate As String
    Public Property TotalAmount As Decimal
    Public Property VendorName As String
End Class

' Extracts key invoice fields using regex pattern matching
' Multiple patterns handle variations across different vendors
Public Class InvoiceParser
    Public Function ParseInvoice(pdfPath As String) As InvoiceData
        Dim pdf = PdfDocument.FromFile(pdfPath)
        Dim text As String = pdf.ExtractAllText()

        Dim invoiceData As New InvoiceData()

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

        For Each pattern As String In invoiceNumberPatterns
            Dim match = Regex.Match(text, pattern, RegexOptions.IgnoreCase)
            If match.Success Then
                invoiceData.InvoiceNumber = match.Groups(1).Value
                Console.WriteLine($"Found Invoice Number: {invoiceData.InvoiceNumber}")
                Exit For
            End If
        Next

        ' Date patterns for US, European, and written formats
        Dim datePatterns As String() = {
            "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
        }

        For Each pattern As String In datePatterns
            Dim match = Regex.Match(text, pattern, RegexOptions.IgnoreCase)
            If match.Success Then
                invoiceData.InvoiceDate = match.Groups(1).Value
                Console.WriteLine($"Found Date: {invoiceData.InvoiceDate}")
                Exit For
            End If
        Next

        ' Look for total amount with various labels
        Dim totalPatterns As String() = {
            "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})"
        }

        For Each pattern As String In totalPatterns
            Dim match = Regex.Match(text, pattern, RegexOptions.IgnoreCase)
            If match.Success Then
                ' Remove commas before parsing
                Dim amountStr As String = match.Groups(1).Value.Replace(",", "")
                Dim amount As Decimal
                If Decimal.TryParse(amountStr, amount) Then
                    invoiceData.TotalAmount = amount
                    Console.WriteLine($"Found Total: ${invoiceData.TotalAmount:F2}")
                    Exit For
                End If
            End If
        Next

        Return invoiceData
    End Function
End Class
$vbLabelText   $csharpLabel

Bu kalıp tabanlı yaklaşım, tahmin edilebilir formatlara sahip faturalar için iyi çalışır. Birden fazla kalıp varyasyonu, "Fatura #" ve "Fatura Numarası:" gibi satıcılar arasındaki yaygın format farklarını ele alır.

Taranmış veya Görüntü Tabanlı Faturalar Ne Olacak?

Yukarıda gösterilen metin çıkarma yöntemleri, yerleşik metin içeren PDF'lerle çalışır. Ancak, taranmış belgeler ve görüntü tabanlı PDF'ler çıkarılabilir metne sahip değildir. Temelde, bunlar fatura resimleri gibidir.

Lütfen dikkate alinTaranmış faturaları işlemek için OCR (Optik Karakter Tanıma) yeteneklerine ihtiyaçınız olacak. IronOCR, Iron Suite'in bir parçası olarak, bu senaryolar için IronPDF ile sorunsuz bir şekilde entegre olur. https://ironsoftware.com/csharp/ocr/ adresini ziyaret ederek, taranan belgelerden ve görüntülerden metin çıkarmayı öğrenebilirsiniz.


.NET'te Faturaları İşlemek için AI Nasıl Kullanılır

Geleneksel kalıp eşleştirme, standartlaştırılmış faturalar için iyi çalışır, ancak gerçek dünyadaki alacak hesapları bölümleri, sayısız formatta belgeler alır. İşte bu noktada AI destekli çıkarma parlıyor. Büyük dil modelleri, fatura semantiğini anlayabilir ve tanıdık olmayan düzenlerden bile yapılandırılmış verileri çıkarabilir.

Fatura Ayrıştırma İçin AI Nasıl Entegre Edilir

Yapay zeka destekli fatura işleme deseni, IronPDF'nin metin çıkarımı ile LLM API çağrılarını birleştirir. İşte herhangi bir OpenAI ile uyumlu API ile çalışan genel bir uygulama:

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;
    }
}
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;
    }
}
Imports IronPdf
Imports System
Imports System.Net.Http
Imports System.Text
Imports System.Text.Json
Imports System.Threading.Tasks

' Data model for extracted invoice information
Public Class InvoiceData
    Public Property InvoiceNumber As String
    Public Property InvoiceDate As String
    Public Property VendorName As String
    Public Property TotalAmount As Decimal
End Class

' 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 As HttpClient
    Private ReadOnly _apiKey As String
    Private ReadOnly _apiUrl As String

    Public Sub New(apiKey As String, Optional apiUrl As String = "https://api.openai.com/v1/chat/completions")
        _apiKey = apiKey
        _apiUrl = apiUrl
        _httpClient = New HttpClient()
        _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_apiKey}")
    End Sub

    Public Async Function ParseInvoiceWithAI(pdfPath As String) As Task(Of InvoiceData)
        ' First extract raw text from the PDF using IronPDF
        Dim pdf = PdfDocument.FromFile(pdfPath)
        Dim invoiceText As String = pdf.ExtractAllText()

        ' Construct a prompt that instructs the AI to return structured JSON
        ' Being explicit about the format reduces parsing errors
        Dim prompt As String = $"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
        Dim requestBody = New With {
            .model = "gpt-4",
            .messages = New Object() {
                New With {
                    .role = "system",
                    .content = "You are an invoice data extraction assistant. Extract structured data from invoices and return valid JSON only."
                },
                New With {
                    .role = "user",
                    .content = prompt
                }
            },
            .temperature = 0.1  ' Low temperature ensures consistent, deterministic results
        }

        Dim json As String = JsonSerializer.Serialize(requestBody)
        Dim content As New StringContent(json, Encoding.UTF8, "application/json")

        Dim response = Await _httpClient.PostAsync(_apiUrl, content)
        Dim responseJson As String = Await response.Content.ReadAsStringAsync()

        ' Navigate the API response structure to get the extracted content
        Using doc = JsonDocument.Parse(responseJson)
            Dim messageContent As String = 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
            Dim invoiceData As InvoiceData = JsonSerializer.Deserialize(Of InvoiceData)(messageContent, New JsonSerializerOptions With {.PropertyNameCaseInsensitive = True})

            Return invoiceData
        End Using
    End Function
End Class
$vbLabelText   $csharpLabel

Düşük sıcaklık ayarı (0.1), belirli sonuçları teşvik eder ki bu, aynı giriş için tutarlı sonuçlar istediğiniz veri çıkarma görevlerinde önemlidir.

Faturalardan Yapılandırılmış JSON Verisi Nasıl Çıkarılır

Çizgi öğeleri, satıcı detayları ve müşteri bilgilerine sahip daha karmaşık faturalar için daha zengin bir JSON yapısı isteyebilirsiniz:

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
    }
}
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
    }
}
Imports IronPdf
Imports System
Imports System.Collections.Generic
Imports System.Text.Json
Imports System.Threading.Tasks

' Comprehensive invoice data model with all details
Public Class DetailedInvoiceData
    Public Property InvoiceNumber As String
    Public Property InvoiceDate As DateTime
    Public Property DueDate As DateTime
    Public Property Vendor As VendorInfo
    Public Property Customer As CustomerInfo
    Public Property LineItems As List(Of LineItem)
    Public Property Subtotal As Decimal
    Public Property Tax As Decimal
    Public Property Total As Decimal
End Class

Public Class VendorInfo
    Public Property Name As String
    Public Property Address As String
    Public Property TaxId As String
End Class

Public Class CustomerInfo
    Public Property Name As String
    Public Property Address As String
End Class

Public Class LineItem
    Public Property Description As String
    Public Property Quantity As Decimal
    Public Property UnitPrice As Decimal
    Public Property Total As Decimal
End Class

' Extracts comprehensive invoice data including line items and party details
Public Class StructuredInvoiceExtractor
    Private ReadOnly _aiParser As AIInvoiceParser

    Public Sub New(apiKey As String)
        _aiParser = New AIInvoiceParser(apiKey)
    End Sub

    Public Async Function ExtractDetailedData(pdfPath As String) As Task(Of DetailedInvoiceData)
        Dim pdf = PdfDocument.FromFile(pdfPath)
        Dim text As String = pdf.ExtractAllText()

        ' Define the exact JSON structure we want the AI to return
        ' This schema guides the AI to extract all relevant fields
        Dim jsonSchema As String = "{
  ""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
        Dim prompt As String = $"
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
    End Function
End Class
$vbLabelText   $csharpLabel

Tutarsız Fatura Formatları Nasıl Ele Alınır

AI çıkarımının gerçek gücü, her biri benzersiz formatlara sahip birden fazla satıcıdan gelen faturaları işlerken ortaya çıkar. Akıllı bir işlemci, önce kalıp tabanlı çıkarımı denemeli (daha hızlı ve ücretsizdir) ve yalnızca gerektiğinde AI'ya başvurmalıdır:

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.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;
    }
}
Imports IronPdf
Imports 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 _aiParser As AIInvoiceParser

    Public Sub New(aiApiKey As String)
        _aiParser = New AIInvoiceParser(aiApiKey)
    End Sub

    Public Async Function ProcessAnyInvoice(pdfPath As String) As Task(Of InvoiceData)
        Dim pdf = PdfDocument.FromFile(pdfPath)
        Dim text As String = pdf.ExtractAllText()

        ' First attempt: regex patterns (fast and free)
        Dim patternParser = New InvoiceParser()
        Dim standardResult = patternParser.ParseInvoiceFromText(text)

        ' If pattern matching found all required fields, use that result
        If IsComplete(standardResult) Then
            Console.WriteLine("Pattern extraction successful")
            Return standardResult
        End If

        ' 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")
        Dim aiResult = Await _aiParser.ParseInvoiceWithAI(pdfPath)

        Return aiResult
    End Function

    ' Validates that we have the minimum required fields
    Private Function IsComplete(data As InvoiceData) As Boolean
        Return Not String.IsNullOrEmpty(data.InvoiceNumber) AndAlso
               Not String.IsNullOrEmpty(data.InvoiceDate) AndAlso
               data.TotalAmount > 0
    End Function
End Class
$vbLabelText   $csharpLabel

Alacak Hesapları Otomasyon Boru Hattı Nasıl Oluşturulur

Tüm bu parçaları bir araya getirerek, gelen faturaları işleyen, verileri çıkaran, doğrulayan ve muhasebe sisteminize hazırlayan eksiksiz bir otomasyon boru hattı işte burada:

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}");
            }
        }
    }
}
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}");
            }
        }
    }
}
Imports IronPdf
Imports System
Imports System.IO
Imports System.Threading.Tasks
Imports System.Collections.Generic
Imports System.Linq

' Tracks the outcome of processing each invoice
Public Class ProcessingResult
    Public Property FileName As String
    Public Property Success As Boolean
    Public Property InvoiceNumber As String
    Public Property ErrorMessage As String
End Class

' Complete automation pipeline for accounts payable
' Watches a folder, extracts data, validates, and routes to accounting system
Public Class InvoiceAutomationPipeline
    Private ReadOnly _processor As SmartInvoiceProcessor
    Private ReadOnly _inputFolder As String
    Private ReadOnly _processedFolder As String
    Private ReadOnly _errorFolder As String

    Public Sub New(apiKey As String, inputFolder As String)
        _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)
    End Sub

    ' Main entry point - processes all PDFs in the input folder
    Public Async Function ProcessInvoiceBatch() As Task(Of List(Of ProcessingResult))
        Dim invoiceFiles As String() = Directory.GetFiles(_inputFolder, "*.pdf")
        Console.WriteLine($"Found {invoiceFiles.Length} invoices to process")

        Dim results As New List(Of ProcessingResult)()

        For Each invoicePath As String In invoiceFiles
            Dim fileName As String = Path.GetFileName(invoicePath)

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

                ' Extract data using smart processor (patterns first, then AI)
                Dim invoiceData = Await _processor.ProcessAnyInvoice(invoicePath)

                ' Ensure we have minimum required fields before proceeding
                If ValidateInvoiceData(invoiceData) Then
                    ' Send to accounting system (QuickBooks, Xero, etc.)
                    Await SaveToAccountingSystem(invoiceData)

                    ' Archive successful invoices
                    Dim destPath As String = Path.Combine(_processedFolder, fileName)
                    File.Move(invoicePath, destPath, overwrite:=True)

                    results.Add(New ProcessingResult With {
                        .FileName = fileName,
                        .Success = True,
                        .InvoiceNumber = invoiceData.InvoiceNumber
                    })

                    Console.WriteLine($"✓ Processed: {invoiceData.InvoiceNumber}")
                Else
                    Throw New Exception("Validation failed - missing required fields")
                End If
            Catch ex As Exception
                Console.WriteLine($"✗ Failed: {fileName} - {ex.Message}")

                ' Quarantine failed invoices for manual review
                Dim destPath As String = Path.Combine(_errorFolder, fileName)
                File.Move(invoicePath, destPath, overwrite:=True)

                results.Add(New ProcessingResult With {
                    .FileName = fileName,
                    .Success = False,
                    .ErrorMessage = ex.Message
                })
            End Try
        Next

        GenerateReport(results)
        Return results
    End Function

    ' Checks for minimum required fields
    Private Function ValidateInvoiceData(data As InvoiceData) As Boolean
        Return Not String.IsNullOrEmpty(data.InvoiceNumber) AndAlso
               Not String.IsNullOrEmpty(data.VendorName) AndAlso
               data.TotalAmount > 0
    End Function

    ' Placeholder for accounting system integration
    Private Async Function SaveToAccountingSystem(data As InvoiceData) As Task
        ' 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
    End Function

    ' Outputs a summary of the batch processing results
    Private Sub GenerateReport(results As List(Of ProcessingResult))
        Dim successful As Integer = results.Count(Function(r) r.Success)
        Dim failed As Integer = results.Count(Function(r) Not r.Success)

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

        If failed > 0 Then
            Console.WriteLine(vbCrLf & "Failed invoices requiring review:")
            For Each failure In results.Where(Function(r) Not r.Success)
                Console.WriteLine($"  • {failure.FileName}: {failure.ErrorMessage}")
            Next
        End If
    End Sub
End Class
$vbLabelText   $csharpLabel

Bu boru hattı, tam bir iş akışı uygular: gelen PDF'ler için bir klasörü tarar, her birini işler, çıkarılan verileri doğrular, başarılı çıkarmaları muhasebe sisteminize yönlendirir ve manuel inceleme için hataları karantinaya alır. Özet raporu, işleme sonuçlarına dair görünürlük sağlar.


How to Integrate C# Invoice Processing with Accounting Systems

Çıkarılan fatura verilerinin en nihayetinde, ödeme ve kayıt tutma için muhasebe sistemlerine akması gerekir. Platforma göre ayrıntılar değişiklik gösterir, ancak entegrasyon desenleri tutarlıdır.

QuickBooks, Xero ve SAP için Yaygın Entegrasyon Desenleri Nelerdir?

Çoğu muhasebe platformu, programlı olarak fatura veya fatura oluşturmak için REST API'ler sunar. İşte belirli bir platformunuza uyarlayabileceğiniz bir genel desen:

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}");
    }
}
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}");
    }
}
Imports System
Imports System.Net.Http
Imports System.Text
Imports System.Text.Json
Imports 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 As HttpClient
    Private ReadOnly _apiKey As String
    Private ReadOnly _baseUrl As String

    Public Sub New(apiKey As String, baseUrl As String)
        _apiKey = apiKey
        _baseUrl = baseUrl
        _httpClient = New HttpClient()
        _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_apiKey}")
    End Sub

    ' Creates a Bill in QuickBooks (vendor invoices are called "Bills")
    Public Async Function SendToQuickBooks(invoice As InvoiceData) As Task
        ' QuickBooks Bill structure - see their API docs for full schema
        Dim bill = New With {
            .VendorRef = New With {.name = invoice.VendorName},
            .TxnDate = invoice.InvoiceDate,
            .DocNumber = invoice.InvoiceNumber,
            .TotalAmt = invoice.TotalAmount,
            .Line = New Object() {
                New With {
                    .Amount = invoice.TotalAmount,
                    .DetailType = "AccountBasedExpenseLineDetail",
                    .AccountBasedExpenseLineDetail = New With {
                        .AccountRef = New With {.name = "Accounts Payable"}
                    }
                }
            }
        }

        Await PostToApi("/v3/company/{companyId}/bill", bill)
    End Function

    ' Creates an accounts payable invoice in Xero
    Public Async Function SendToXero(invoice As InvoiceData) As Task
        ' ACCPAY type indicates this is a bill to pay (not a sales invoice)
        Dim bill = New With {
            .Type = "ACCPAY",
            .Contact = New With {.Name = invoice.VendorName},
            .Date = invoice.InvoiceDate,
            .InvoiceNumber = invoice.InvoiceNumber,
            .Total = invoice.TotalAmount
        }

        Await PostToApi("/api.xro/2.0/Invoices", bill)
    End Function

    ' Generic POST helper with error handling
    Private Async Function PostToApi(endpoint As String, payload As Object) As Task
        Dim json As String = JsonSerializer.Serialize(payload)
        Dim content = New StringContent(json, Encoding.UTF8, "application/json")

        Dim response = Await _httpClient.PostAsync($"{_baseUrl}{endpoint}", content)

        If Not response.IsSuccessStatusCode Then
            Dim error As String = Await response.Content.ReadAsStringAsync()
            Throw New Exception($"API Error: {response.StatusCode} - {error}")
        End If

        Console.WriteLine($"Successfully posted to {endpoint}")
    End Function
End Class
$vbLabelText   $csharpLabel

Her platformun kendi kimlik doğrulama mekanizması (QuickBooks ve Xero için OAuth, SAP için çeşitli yöntemler), gerekli alanları ve API konvansiyonları vardır. Belirli ayrıntılar için hedef platformunuzun belgelerine başvurun, ancak çıkarılan fatura verilerinin API yüklerine dönüştürülmesi deseni tutarlıdır.

Yüzlerce Faturayı Bir Arada İşlediğinizde Nasıl Yapılır?

Yüksek hacimli fatura işlemi, eşzamanlılığa ve kaynak yönetimine dikkat gerektirir. İşte kontrollü eşzamanlılık ile paralel işleme kullanan bir desen:

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
            };
        }
    }
}
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
            };
        }
    }
}
Imports System
Imports System.Collections.Concurrent
Imports System.Collections.Generic
Imports System.Linq
Imports System.Threading
Imports System.Threading.Tasks

' Tracks the result of processing a single invoice in a batch
Public Class BatchResult
    Public Property FilePath As String
    Public Property Success As Boolean
    Public Property InvoiceNumber As String
    Public Property Error As String
End Class

' High-volume invoice processor with controlled parallelism
' Prevents overwhelming APIs while maximizing throughput
Public Class BatchInvoiceProcessor
    Private ReadOnly _invoiceProcessor As SmartInvoiceProcessor
    Private ReadOnly _accountingIntegration As AccountingSystemIntegration
    Private ReadOnly _maxConcurrency As Integer

    Public Sub New(aiApiKey As String, accountingApiKey As String, accountingUrl As String, Optional maxConcurrency As Integer = 5)
        _invoiceProcessor = New SmartInvoiceProcessor(aiApiKey)
        _accountingIntegration = New AccountingSystemIntegration(accountingApiKey, accountingUrl)
        _maxConcurrency = maxConcurrency ' Adjust based on API rate limits
    End Sub

    ' Processes multiple invoices in parallel with controlled concurrency
    Public Async Function ProcessInvoiceBatch(invoicePaths As List(Of String)) As Task(Of List(Of BatchResult))
        ' Thread-safe collection for gathering results from parallel tasks
        Dim results = New ConcurrentBag(Of BatchResult)()

        ' Semaphore limits how many invoices process simultaneously
        Dim semaphore = New SemaphoreSlim(_maxConcurrency)

        ' Create a task for each invoice
        Dim tasks = invoicePaths.Select(Async Function(path)
                                            ' Wait for a slot to become available
                                            Await semaphore.WaitAsync()
                                            Try
                                                Dim result = Await ProcessSingleInvoice(path)
                                                results.Add(result)
                                            Finally
                                                ' Release slot for next invoice
                                                semaphore.Release()
                                            End Try
                                        End Function)

        ' Wait for all invoices to complete
        Await Task.WhenAll(tasks)

        ' Output summary statistics
        Dim resultList = results.ToList()
        Dim successful = resultList.Count(Function(r) r.Success)
        Dim failed = resultList.Count(Function(r) Not r.Success)

        Console.WriteLine(vbCrLf & "Batch Processing Complete:")
        Console.WriteLine($"  Total: {resultList.Count}")
        Console.WriteLine($"  Successful: {successful}")
        Console.WriteLine($"  Failed: {failed}")

        Return resultList
    End Function

    ' Processes one invoice: extract data and send to accounting system
    Private Async Function ProcessSingleInvoice(pdfPath As String) As Task(Of BatchResult)
        Try
            Console.WriteLine($"Processing: {pdfPath}")

            Dim invoiceData = Await _invoiceProcessor.ProcessAnyInvoice(pdfPath)
            Await _accountingIntegration.SendToQuickBooks(invoiceData)

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

            Return New BatchResult With {
                .FilePath = pdfPath,
                .Success = True,
                .InvoiceNumber = invoiceData.InvoiceNumber
            }
        Catch ex As Exception
            Console.WriteLine($"✗ Failed: {pdfPath}")

            Return New BatchResult With {
                .FilePath = pdfPath,
                .Success = False,
                .Error = ex.Message
            }
        End Try
    End Function
End Class
$vbLabelText   $csharpLabel

SemaphoreSlim, dış API'ları aşırıya yüklememek veya sistem kaynaklarını tüketmemek için kullanılır. API oran sınırlarınıza ve sunucu kapasitenize göre _maxConcurrency ayarlayın. ConcurrentBag, paralel işlemlerden elde edilen sonuçları güvenli bir şekilde toplar.


Sonraki Adımlar

Fatura otomasyonu, manuel çalışmayı azaltmak, hataları en aza indirmek ve iş süreçlerini hızlandırmak için önemli bir fırsat sunar. Bu kılavuz, sizi tam bir yaşam döngüsünde yönlendirdi: HTML şablonlarından profesyonel faturalar oluşturmak, ZUGFeRD ve Factur-X e-fatura standartlarına uyum sağlamak, gelen faturaların verilerini çıkarmak için hem kalıp eşleştirme hem de yapay zeka destekli işleme kullanmak, ve ölçeklenebilir otomasyon boru hatları oluşturmak.

IronPDF, bu yeteneklerin temelini oluşturur, sağlam HTML-to-PDF dönüştürme, güvenilir metin çıkarma ve PDF/A-3 e-faturalarına uyum için gereken ek özellikleri sağlar. Chrome tabanlı render motoru, faturalarınızın tam olarak tasarlandığı gibi görünmesini sağlarken, çıkarma yöntemleri PDF metin kodlamasının karmaşıklığını otomatik olarak ele alır.

Burada gösterilen desenler başlangıç noktalarıdır. Gerçek uygulamalar, belirli fatura formatlarınız, muhasebe sistemleriniz ve iş kurallarınız için uyarlanmalıdır. Yüksek hacimli senaryolar için, toplu işlem öğreticisi, kontrollü eşzamanlılık ve hata kurtarma ile paralel yürütmeyi kapsamaktadır.

Yapmaya hazır mısınız? IronPDF İndir ve ücretsiz deneme ile deneyin. Kutuphane, fatura oluşturma, veri cikarimi ve üretim lisansı taahhüdünde bulunmadan once PDF rapor yeteneklerini tam olarak degerlendirmeniz icin ücretsiz bir geliştirme lisansi icerir. Fatura otomasyonu veya muhasebe sistemi entegrasyonu hakkinda sorulariniz varsa, mühendislik destek ekibimizle iletisime gecin.

Sıkça Sorulan Sorular

IronPDF, C# fatura işlemede ne için kullanılır?

IronPDF, C# fatura işlemede profesyonel PDF faturaları üretmek, yapılandırılmış veriler çıkarmak ve ZUGFeRD ve Factur-X gibi standartlarla uyumu sağlarken fatura akışlarını otomatikleştirmek için kullanılır.

IronPDF kullanarak C# içinde bir PDF faturası nasıl oluşturabilirim?

IronPDF kullanarak C# içinde bir PDF faturası oluşturabilirsiniz. Bu, bir faturayı oluşturan metin, tablolar ve resimler gibi öğeler eklemeyi içeren PDF belgelerini programlı olarak oluşturma ve özelleştirme API'sini kullanmayı içerir.

ZUGFeRD ve Factur-X nedir ve IronPDF bunları nasıl destekler?

ZUGFeRD ve Factur-X, faturaların hem insan hem de makine tarafından okunabilir olmasını sağlayan e-faturalama standartlarıdır. IronPDF, bu standartlara uygun PDF faturaları oluşturmanıza izin vererek bu standartları destekler.

IronPDF, borç hesapları süreçlerini otomatikleştirmeye nasıl yardımcı olabilir?

IronPDF, faturalardan yapılandırılmış verileri çıkararak ve otomasyon hatlarına entegre ederek, manuel veri girişini azaltarak ve verimliliği artırarak borç hesapları süreçlerini otomatikleştirebilir.

IronPDF mevcut PDF faturalarından veri çıkarabilir mi?

Evet, IronPDF mevcut PDF faturalarından yapılandırılmış veriler çıkarabilir, bu da fatura bilgilerinin otomatik olarak işlenmesini ve analiz edilmesini kolaylaştırır.

IronPDF'yi C# fatura işlemede kullanmanın faydaları nelerdir?

C# fatura işlemede IronPDF'yi kullanmanın faydaları arasında fatura üretiminin kolaylaştırılması, uluslararası fatura standartlarına uyum sağlama, verimli veri çıkarma ve gelişmiş otomasyon yetenekleri yer alır.

IronPDF ile bir PDF faturasının görünümünü özelleştirmek mümkün mü?

Evet, IronPDF, bir PDF faturasının görünümünü logolar, metin biçimlendirme ve marka gereksinimlerini karşılamak için düzen ayarlamaları gibi çeşitli tasarım öğelerini ekleyerek özelleştirmenize olanak tanır.

IronPDF kullanarak fatura işlemlerini otomatikleştirmek için tipik adımlar nelerdir?

IronPDF kullanarak fatura işlemlerini otomatikleştirmek için, genellikle faturayı oluşturur, gerekli verileri çıkarır ve iş akışlarını kolaylaştırmak için diğer sistemlere veya otomasyon araçlarına entegre edersiniz.

IronPDF, farklı fatura formatlarını nasıl işler?

IronPDF, PDF belgelerini oluşturma, manipüle etme ve okuma araçları sağlayarak, yaygın e-faturalama standartlarıyla uyumluluğu sağlayarak çeşitli fatura formatlarını işleyebilir.

Curtis Chau
Teknik Yazar

Curtis Chau, Bilgisayar Bilimleri alanında lisans derecesine sahiptir (Carleton Üniversitesi) ve Node.js, TypeScript, JavaScript ve React konularında uzmanlaşmış ön uç geliştirme üzerine uzmanlaşmıştır. Kullanıcı dostu ve estetik açıdan hoş arayüzler tasarlamaya tutkuyla bağlı olan Curtis, modern çerç...

Daha Fazlasını Oku
Başlamaya Hazır mısınız?
Nuget Indirmeler 18,332,619 | Sürüm: 2026.4 yeni yayınlandı
Still Scrolling Icon

Hala Kaydiriyor musunuz?

Hızlı bir kanit mi istiyorsunuz? PM > Install-Package IronPdf
bir örnek çalıştır HTML'nizin PDF olduğunu izleyin.