# Invoice Processing in C#: Generate, Extract, and Automate PDF Invoices with .NET
**Fatura işleme** **C# .NET** ile IronPDF, HTML şablonlarından profesyonel **PDF faturaları** oluşturmayı, **ZUGFeRD** ve **Factur-X** uyumlu e-faturalandırma standartları ile uyum sağlamayı, metin ayrıştırma ve **yapay zeka destekli işleme** kullanarak alınan faturalardan yapılandırılmış veri çıkarmayı ve QuickBooks, Xero ve SAP gibi muhasebe sistemleriyle entegre edilen **toplu otomasyon boru hatları** oluşturmaktadır.
~~Kısa-Özet: Hızlı Başlangıç Kılavuzu~~
Bu kılavuz, C# .NET'te fatura oluşturma, çıkarma ve otomasyonu ele alır, e-fatura uyumluluğu, yapay zeka destekli ayrıştırma ve muhasebe sistemi entegrasyonunu içerir.
- **Kimler için:** Fatura modülleri, borç hesaplarını otomatikleştirme veya e-faturalandırma uyumluluğu geliştiren .NET geliştiricileri.
- **Ne geliştireceksiniz:** Satır öğeleri ve vergi hesaplamalarıyla HTML şablonlu fatura oluşturma, ödeme bağlantıları için QR kodlar, ZUGFeRD/Factur-X uyumlu PDF/A-3 çıktısı, regex ile metin çıkarma, yapay zeka destekli fatura ayrıştırma ve muhasebe sistemi entegrasyonu ile toplu işleme.
- **Nerede çalışır:** .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 standartlarına uymanız veya borç hesapları için tedarikçi faturalarından veri çıkarmanız gerektiğinde.
Teknik olarak neden önemlidir: IronPDF, *HTML'i PDF'ye* piksel mükemmel hassasiyetle dönüştürür, gömülü XML için PDF/A-3'ü destekler ve regex veya yapay zeka ile eşleştirilebilen metin çıkarma API'leri sağlar.
İlk PDF faturalarınızı sadece birkaç satır kodla oluşturun:
```cs
:title=Generate an Invoice PDF with IronPDF
var renderer = new IronPdf.ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Invoice #1001</h1><p>Total: $500.00</p>");
pdf.SaveAs("invoice.pdf");
```
IronPDF'yi satın aldıktan veya 30 günlük denemeye kaydolduktan sonra, başvurunuzda lisans anahtarınızı ekleyin.
```cs
IronPdf.License.LicenseKey = "KEY";
```
!!!--LIBRARY_START_TRIAL_BLOCK--!!!
!!!--LIBRARY_NUGET_INSTALL_BLOCK--!!!
~~İçindekiler~~
- **Özet: Hızlı Başlangıç Kılavuzu**
- [Hızlı Özet](#anchor-tldr-quickstart-guide)
- **Profesyonel PDF Faturaları Üretin**
- [Bir Fatura HTML Şablonu Oluşturun](#anchor-build-an-invoice-html-template)
- [Dinamik Satır Öğeleri Ekleyin ve Toplamları Hesaplayın](#anchor-add-dynamic-line-items-and-calculate-totals)
- [Şirket Markalama ve Filigranlarını Ekleyin](#anchor-add-company-branding-and-watermarks)
- [Ödeme Bağlantıları İçin QR Kodları Gömün](#anchor-embed-qr-codes-for-payment-links)
- **E-Fatura Standartları ile Uyumlu Olun**
- [ZUGFeRD Nedir ve Nasıl Çalışır?](#anchor-what-is-zugferd)
- [Factur-X Nedir?](#anchor-what-is-factur-x)
- [XML Verilerini PDF/A-3 Faturalara Gömün](#anchor-embed-xml-data-in-pdfa3)
- [AB Yönetmelikleri İçin Gelecek Kanıt Faturalar](#anchor-future-proof-invoices-for-eu-mandates)
- **PDF Faturalarından Veri Çıkarın**
- [PDF Faturasından Metin Çıkarın](#anchor-extract-text-from-a-pdf-invoice)
- [Satır Öğeleri İçin Tablo Verileri Çıkarın](#anchor-extract-table-data-for-line-items)
- [Fatura Numaraları, Tarihler ve Toplamlar İçin Desen Eşleştirme](#anchor-pattern-matching-for-invoice-data)
- **Yapay Zeka Destekli Fatura İşleme**
- [Fatura Ayrıştırması İçin Yapay Zekayı Entegre Edin](#anchor-integrate-ai-for-invoice-parsing)
- [Yapılandırılmış JSON Verileri Çıkarın](#anchor-extract-structured-json-data)
- [Tutarsız Fatura Formatlarını Yönetin](#anchor-handle-inconsistent-invoice-formats)
- [Borçlu Hesaplar Otomasyon Boru Hattı Oluşturun](#anchor-build-accounts-payable-automation-pipeline)
- **Muhasebe Sistemleriyle Entegre Edin**
- [QuickBooks, Xero ve SAP için Entegrasyon Modelleri](#anchor-integration-patterns-quickbooks-xero-sap)
- [Yüzlerce Faturayı Toplu İşleyin](#anchor-batch-process-hundreds-of-invoices)
!!!--LIBRARY_NUGET_INSTALL_BLOCK--!!!
<a id="anchor-invoice-lifecycle"></a>
## Fatura Yaşam Döngüsü Nedir ve Neden PDF Standart Kalıyor?
Koda dalmadan önce, bir faturanın modern bir iş sistemi boyunca aldığı yolculuğu anlamak faydalı 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şturma ile başlar. Bir işletme, satır öğeleri, fiyatlandırma, vergi hesaplamaları, ödeme koşulları ve markalama içeren bir fatura oluşturur. Fatura profesyonel görünmelidir ve tüm yasal gerekliliklere uygun olmalıdır. Sonra dağıtım gelir, burada fatura müşteri portalı aracılığıyla veya geleneksel posta yoluyla müşteri e-postasına gönderilir. Müşteri aldığında, borç hesapları ekibi belgeyi yakalayıp işlemek üzere hazırlar. Veri çıkarma, fatura, satır öğeleri, toplamlar ve vade tarihleri gibi anahtar bilgileri çıkarır, böylece bunlar satın alma emirlerine karşı kontrol edilebilir ve eşleşebilir. Son olarak, muhasebe entegrasyonu bu verileri QuickBooks, Xero veya SAP gibi finansal sistemlere ödeme ve kayıt tutma için taşır.
Peki PDF bu kadar yıl sonra halen en yaygın olarak kullanılan format neden? Bu, eşsiz bir avantajlar karışımına dayanıyor. PDF'ler, fatura biçimlendirmesini hangi cihaz veya işletim sistemini kullanırsanız kullanın tutarlılıkla korur. Birisi faturalarınızı Windows, Mac veya telefonunda açsa bile, tam olarak tasarladığınız gibi görünecektir. PDF'ler yanlışlıkla değişime karşı da zordur, bu yüzden belgelerinizin bütünlüğünü, Word veya Excel gibi formatlardan daha iyi korurlar. Kimlik doğrulama 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 geldi.
Elbette, burada bir zorluk var. PDF'ler insanların okumalarını kolaylaştırmak için yapılmış, bilgisayarların işlemesi için değil. Bilgiyi yapılandırılmış veri içinde saklamak yerine, bir PDF sayfada göründükleri yere göre metin, çizgiler, şekiller ve görüntüler kaydeder. Bu yüzden IronPDF gibi araçlar son derece yararlıdır, insan dostu belgeleri yazılımın çalışabileceği verilere dönüştürmeyi mümkün kılar.
---
## How to Generate Professional PDF Invoices in C#
Faturaları programatik olarak oluşturmak, müşteri bilgileri, satır öğeler 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 teknolojilerini kullanarak bunu son derece basit hale getirir.
Bu öğretici makalede, gerçek dünyada karşılaşacağınız muhtemel senaryoları inceleyeceğiz. Aşağıda gösterilen projeyi [buradan](/static-assets/pdf/tutorials/csharp-invoice-processing/InvoiceProcessingTutorial.zip) da indirebilirsiniz.
<a id="anchor-build-an-invoice-html-template"></a>
### Fatura HTML Şablonu Nasıl Oluşturulur
IronPDF ile fatura oluşturmanın temeli HTML'dir. Düşük seviyeli PDF çizim komutları ile uğraşmak yerine, standart HTML ve CSS kullanarak faturanızı tasarlar, sonra IronPDF'nin Chrome tabanlı render motorunun onu piksel mükemmel PDF'ye dönüştürmesine izin verirsiniz.
İşte yaklaşımı gösteren temel bir fatura şablonu:
```cs
using IronPdf;
// Define the HTML template for a basic invoice
// Uses inline CSS for styling headers, tables, and totals
string invoiceHtml = @"
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; padding: 40px; }
.header { text-align: right; margin-bottom: 40px; }
.company-name { font-size: 24px; font-weight: bold; color: #333; }
.invoice-title { font-size: 32px; margin: 20px 0; }
.bill-to { margin: 20px 0; }
table { width: 100%; border-collapse: collapse; margin: 20px 0; }
th { background-color: #2A95D5; color: white; padding: 10px; text-align: left; }
td { padding: 10px; border-bottom: 1px solid #ddd; }
.total { text-align: right; font-size: 20px; font-weight: bold; margin-top: 20px; }
</style>
</head>
<body>
<div class='header'>
<div class='company-name'>Your Company Name</div>
<div>123 Business Street</div>
<div>City, State 12345</div>
</div>
<div class='invoice-title'>INVOICE</div>
<div class='bill-to'>
<strong>Bill To:</strong><br>
Customer Name<br>
456 Customer Avenue<br>
City, State 67890
</div>
<table>
<tr>
<th>Description</th>
<th>Quantity</th>
<th>Price</th>
<th>Total</th>
</tr>
<tr>
<td>Web Development Services</td>
<td>10 hours</td>
<td>$100.00</td>
<td>$1,000.00</td>
</tr>
<tr>
<td>Consulting</td>
<td>5 hours</td>
<td>$150.00</td>
<td>$750.00</td>
</tr>
</table>
<div class='total'>Total: $1,750.00</div>
</body>
</html>";
// Initialize the Chrome-based PDF renderer
var renderer = new ChromePdfRenderer();
// Convert the HTML string to a PDF document
var pdf = renderer.RenderHtmlAsPdf(invoiceHtml);
// Save the generated PDF to disk
pdf.SaveAs("basic-invoice.pdf");
```
#### Örnek Çıktı
<iframe loading="lazy" src="/static-assets/pdf/tutorials/csharp-invoice-processing/basic-invoice.pdf"width="100%" height="400px">
</iframe>
Bu yaklaşım muazzam bir esneklik sunar. Chrome'da çalışan herhangi bir CSS PDF'nizde çalışacaktır, flexbox, grid düzenleri ve özel fontlar gibi modern özellikler dahil. URL'ler veya yerel dosya yollarını referans alarak harici stil sayfaları ve görüntüleri bile kullanabilirsiniz.
<a id="anchor-add-dynamic-line-items-and-calculate-totals"></a>
### Dinamik Satır Öğeleri Ekleyin ve Toplamları Hesaplayın
Gerçek faturalar nadiren statik içerik taşır. Satır öğelerini bir veritabanından çıkarmanız, ara toplamları hesaplamanız, vergi oranları uygulamanız ve para birimi değerlerini biçimlendirmenizde gereklidir. Aşağıdaki örnek, dinamik fatura üretimi için üretim hazır bir deseni göstermektedir.
```cs
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);
}
}
```
#### Örnek Çıktı
<iframe loading="lazy" src="/static-assets/pdf/tutorials/csharp-invoice-processing/invoice-INV-2026-001.pdf"width="100%" height="400px">
</iframe>
`Invoice` sınıfı, ara toplam, vergi ve toplam için hesaplanan özelliklerle tüm fatura verilerini kapsar. Üretici, bu verileri dizgi iç içeleme kullanarak HTML'ye dönüştürür, ardından PDF'ye rendeler. Bu ayrımlaşma, kodu sürdürülebilir ve test edilebilir hale getirir.
<a id="anchor-add-company-branding-and-watermarks"></a>
### Şirket Markalama ve Filigranlarını Faturalara Ekleyin
Profesyonel faturalar, logolar gibi markalama unsurlarına ve bazı durumlarda ödeme durumunu belirtmek için filigranlara ihtiyaç duyar. IronPDF, HTML'de gömülü görüntüler ve render sonrası programatik filigranlama desteği sunar.
```cs
using IronPdf;
var renderer = new ChromePdfRenderer();
// Invoice HTML template with company logo embedded via URL
// Logo can also be Base64-encoded or a local file path
string htmlWithLogo = @"
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; padding: 40px; }
.logo { width: 200px; margin-bottom: 20px; }
</style>
</head>
<body>
<div style='text-align: center;'>
<img src='https://yourcompany.com/logo.png' alt='Company Logo' class='logo' />
</div>
<h1>INVOICE</h1>
<p><strong>Invoice Number:</strong> INV-2024-001</p>
<p><strong>Total:</strong> $1,250.00</p>
</body>
</html>";
// Render the HTML to PDF
var pdf = renderer.RenderHtmlAsPdf(htmlWithLogo);
// Apply a diagonal "UNPAID" watermark to mark invoice status
// 30% opacity keeps the content readable while the watermark is visible
pdf.ApplyWatermark("<h1 style='color: red;'>UNPAID</h1>",
opacity: 30,
rotation: 45,
verticalAlignment: IronPdf.Editing.VerticalAlignment.Middle);
pdf.SaveAs("invoice-with-watermark.pdf");
```
#### Örnek Çıktı
<iframe loading="lazy" src="/static-assets/pdf/tutorials/csharp-invoice-processing/invoice-with-watermark.pdf"width="100%" height="400px">
</iframe>
`ApplyWatermark` metodu, sizin işaret filigranının görünümü üzerinde tam kontrol sahibi olmanızı sağlayarak HTML içeriğini kabul eder. İhtiyacınız olan görünümü elde etmek için opaklığı, dönüşü ve konumlandırmayı ayarlayabilirsiniz. Bu, özellikle faturaları "ÖDENMİŞ", "TASLAK" veya "İPTAL EDİLMİŞ" olarak işaretlemek için faydalıdır, belgenin tamamını tekrar üretmeden.
<a id="anchor-embed-qr-codes-for-payment-links"></a>
### Ödeme Bağlantıları İçin QR Kodları Gömün
Modern faturalar genellikle müşterilerin hızlıca ödeme yapması için tarayabileceği QR kodları içerir. IronPDF, PDF oluşturma üzerine odaklanırken, IronQR ile barkod oluşturma konusunda sorunsuz çalışır:
```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 = $@"
<!DOCTYPE html>
<html>
<head>
<style>
body {{ font-family: Arial, sans-serif; padding: 40px; }}
.payment-section {{ margin-top: 40px; text-align: center;
border-top: 2px solid #eee; padding-top: 20px; }}
.qr-code {{ width: 150px; height: 150px; }}
</style>
</head>
<body>
<h1>INVOICE {invoiceNumber}</h1>
<p><strong>Amount Due:</strong> ${amount:F2}</p>
<div class='payment-section'>
<p><strong>Scan to Pay Instantly:</strong></p>
<img src='payment-qr.png' alt='Payment QR Code' class='qr-code' />
<p style='font-size: 12px; color: #666;'>
Or visit: {paymentUrl}
</p>
</div>
</body>
</html>";
// Convert HTML to PDF and save
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(invoiceHtml);
pdf.SaveAs($"invoice-{invoiceNumber}.pdf");
```
#### Örnek Çıktı
<iframe loading="lazy" src="/static-assets/pdf/tutorials/csharp-invoice-processing/invoice-INV-2026-002.pdf"width="100%" height="400px">
</iframe>
QR kodu doğrudan bir ödeme sayfasına bağlanır, müşteriler için sürtüşmeyi azaltır ve nakit akışınızı hızlandırır. Bu desen, URL tabanlı ödeme başlatımını destekleyen herhangi bir ödeme sağlayıcı ile çalışır.
---
## How to Comply with ZUGFeRD and Factur-X E-Invoicing Standards in C#
Elektronik faturalama Avrupa genelinde hızla zorunlu hale geliyor. Öncü olarak ZUGFeRD ile Almanya ve ardından Factur-X ile Fransa geldi. Bu standartlar, PDF faturalar içerisine makine tarafından okunabilir XML verilerini gömerek, otomatik işlem imkanı sunarken, insan tarafından okunabilen belgeleri de muhafaza etmektedir. Bu standartları anlamak ve uygulamak, Avrupa pazarlarında faaliyet gösteren işletmeler için gittikçe daha kritik hale geliyor.
<a id="anchor-what-is-zugferd"></a>
### ZUGFeRD Nedir ve Nasıl Çalışır?
ZUGFeRD (Zentraler User Guide des Forums elektronische Rechnung Deutschland), PDF/A-3 uyumlu bir belgede XML dosya eki olarak fatura verilerini gömen bir Alman e-fatura standardıdır. Gömülü XML, OCR veya ayrıştırma olmadan otomatik veri çıkarımına olanak tanır.
Standart, her biri daha fazla yapılandırılmış veri sunan üç uyum seviyesini tanımlar:
- **Temel:** Basit otomatik işleme için uygun olan temel fatura verilerini içerir
- **Konfor:** Tam otomatik fatura işleme olanağı sağlayan ayrıntılı bilgileri ekler
- **Genişletilmiş:** Endüstrileri kapsayan karmaşık iş senaryoları için kapsamlı veri içerir.
XML, Avrupa e-faturalama standartlaştırmasının temeli haline gelen UN/CEFACT Çapraz-Endüstri Fatura (CII) şemasını izler.
<a id="anchor-what-is-factur-x"></a>
### 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. Aynı XML şeması ve Avrupa Norm EN 16931'a dayalı uyumluluk profillerini paylaşırlar. Fark, tamamen bölgesel adlandırmadır: ZUGFeRD spesifikasyonlarına uygun olarak oluşturulmuş bir fatura, Factur-X altında geçerli olacak ve tam tersi.
<a id="anchor-embed-xml-data-in-pdfa3"></a>
### XML Verilerini PDF/A-3 Faturalarına Nasıl Gömülür
IronPDF, uyumlu e-faturalar oluşturmak için gerekli olan ekleme yeteneklerini sağlar. Süreç, fatura PDF'nizi oluşturmayı, XML verilerini CII şemasına göre oluşturmayı ve XML'i uygun adlandırma kuralları ile bir ek olarak gömmeyi içerir:
```cs
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>";
}
}
```
#### Örnek Çıktı
<iframe loading="lazy" src="/static-assets/pdf/tutorials/csharp-invoice-processing/invoice-DE-2026-001-zugferd.pdf"width="100%" height="400px">
</iframe>
Uyumun temel yönleri, doğru XML ad alanlarını kullanmak, CII şema yapısını izlemek ve XML'i uygun bir dosya adıyla gömmektir. TypeCode "380" belgenin UN/CEFACT standardı içinde ticari bir fatura olarak belirlenmesini sağlar.
<a id="anchor-future-proof-invoices-for-eu-mandates"></a>
### AB Talimatlarına Göre Faturaları Geleceğe Hazırlama Yolları
Avrupa Birliği, üye devletlerde kademeli olarak e-faturalamayı zorunlu hale getiriyor. İtalya, B2B işlemleri için zaten bu gerekliliği uyguluyor; Fransa, 2026 yılına kadar gereksinimleri aşamalı olarak uyguluyor ve Almanya, 2025'te zorunlu B2B e-faturalamayı duyurdu. Şimdi ZUGFeRD/Factur-X desteği oluşturmak, sisteminizi bu düzenleyici gereksinimlere hazırlar.
İşte farklı standartları hedefleyebilen uyum bilincine sahip bir fatura jeneratörü için bir model:
```csharp
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>";
}
}
```
Bu mimari, çekirdek fatura oluşturma mantığınızı yeniden yapılandırmadan ortaya çıkan yeni standartları eklemenizi sağlar. Enum tabanlı yaklaşım, hangi uyum modunun kullanılacağını kullanıcıların veya yapılandırmanın belirlemesini kolaylaştırır.
---
## How to Extract Data from PDF Invoices in C#
Faturaların oluşturulması sadece denklemin yarısıdır. Çoğu işletme ayrıca tedarikçilerden fatura alır ve işlemler için veri çıkarmaları gerekir. IronPDF, fatura verilerini yakalamak için temel oluşturan güçlü metin çıkarma yetenekleri sağlar.
<a id="anchor-extract-text-from-a-pdf-invoice"></a>
### Bir PDF Faturasından Metin Çıkarmayı Nasıl Yapılır
En temel çıkarma işlemi, bir PDF'den tüm metin içeriğini almaktır. IronPDF'ün `ExtractAllText` metodu, PDF metin kodlaması ve konumlandırmasının karmaşıklığını ele alır:
```csharp
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);
}
}
}
```
Sayfa bazında çıkarım, birden fazla sayfaya yayılan satır öğelerini bulmak gibi belirli bölümleri bulmanız gerektiğinde özellikle çok sayfalı faturalar için yararlıdır, oysa başlık bilgileri yalnızca ilk sayfada görünür.
<a id="anchor-extract-table-data-for-line-items"></a>
### Satır Ögeleri İçin Tablo Verilerini Nasıl Çıkarılır
Fatura satır ögeleri genellikle tablosal biçimde görünür. PDF'lerin yerel bir tablo yapısı yoktur, ancak metni çıkarabilir ve tablo verilerini yeniden oluşturmak için ayrıştırabilirsiniz:
```csharp
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;
}
}
```
Ayrıştırma mantığı, fatura formatlarınıza bağlı olarak değişecektir. Bilinir satıcılardan gelen tutarlı formatlara sahip faturalar için formatlara spesifik ayrıştırıcılar oluşturabilirsiniz. Çeşitli formatlar için, makalenin ilerleyen kısımlarında ele alınan AI destekli çıkarma yöntemlerini düşünün.
<a id="anchor-pattern-matching-for-invoice-data"></a>
### Fatura Numaraları, Tarihler, ve Toplamlar İçin Desen Eşlemeyi Nasıl Kullanılır
Düzenli ifadeler, fatura metninden belirli veri noktalarını çıkarmak için değerli araçlardır. Fatura numaraları, tarihler ve toplamlar gibi anahtar alanlar genellikle tanınabilir desenleri takip eder:
```csharp
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;
}
}
```
Bu desen tabanlı yaklaşım, tahmin edilebilir formatlara sahip faturalar için iyi çalışır. Çeşitli desen varyasyonları, "Invoice #" ve "Invoice Number:" gibi satıcılar arasındaki yaygın formatlama farklılıklarını ele alır.
### Taranmış veya Görüntü Tabanlı Faturalar Ne Olacak?
Yukarıda gösterilen metin çıkarma yöntemleri, gömülü metin içeren PDF'lerle çalışır. Ancak taranmış belgeler ve görüntü tabanlı PDF'ler çıkarılabilir metne sahip değildir. Esasen fatura resimleri gibidirler.
[[i:(Tarama yapılan faturaları işlemek için, OCR (Optik Karakter Tanımlama) yeteneklerine ihtiyacınız olacak. IronOCR, Iron Suite'nin bir parçası olarak bu tür senaryolarda IronPDF ile sorunsuz bir şekilde entegre olur. Taranan belgeler ve görüntülerden metin çıkarmayı öğrenmek için [https://ironsoftware.com/csharp/ocr/](https://ironsoftware.com/csharp/ocr/) adresini ziyaret edin.)]]
---
## AI Tabanlı Fatura İşlemlerini .NET İle Nasıl Kullanılır
Geleneksel desen eşleme, standartlaştırılmış faturalar için iyi çalışır, ancak gerçek dünya hesapları ödenecek departmanlar sayısız formatta belgeler alır. AI destekli çıkarmanın öne çıktığı yer burasıdır. Büyük dil modelleri, fatura semantiğini anlayabilir ve tanıdık olmayan düzenlerden bile yapılandırılmış veriler çıkarabilir.
<a id="anchor-integrate-ai-for-invoice-parsing"></a>
### AI Tabanlı Fatura Ayrıştırmayı Nasıl Entegre Edilir
AI destekli fatura işleme için desen, IronPDF'nin metin çıkarımıyla LLM API çağrılarını birleştirir. İşte OpenAI uyumlu herhangi bir API ile çalışan genel bir gerçekleştirme:
```csharp
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;
}
}
```
Düşük sıcaklık ayarı (0.1) determiniztik çıktıları teşvik eder, bu, aynı girdi için tutarlı sonuçlar istediğiniz veri çıkarma görevlerinde önemlidir.
<a id="anchor-extract-structured-json-data"></a>
### Faturalardan Yapılandırılmış JSON Verisi Nasıl Çıkarılır
Satır ögeleri, satıcı detayları ve müşteri bilgilerini içeren daha karmaşık faturalar için daha zengin bir JSON yapısı talep edebilirsiniz:
```csharp
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
}
}
```
<a id="anchor-handle-inconsistent-invoice-formats"></a>
### Çelişkili Fatura Formatları Nasıl Yönetilir
Aynı anda birden fazla satıcıdan gelen, her birinin benzersiz formatları olan faturaları işlerken AI çıkarmanın gerçek gücü ortaya çıkar. Akıllı bir işlemci, önce desen tabanlı çıkarımı uygulayabilir (daha hızlı ve ücretsiz) ve gerektiğinde yalnızca AI'ya geri dönebilir.
```csharp
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;
}
}
```
<a id="anchor-build-accounts-payable-automation-pipeline"></a>
### Ödenecek Hesaplar Otomasyon Hattı Nasıl Kurulur
Tüm bu parçaları bir araya getirdiğinizde, gelen faturaları işleyen, verileri çıkaran, doğrulayan ve muhasebe sisteminize hazırlayan eksiksiz bir otomasyon hattı:
```csharp
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}");
}
}
}
}
```
Bu hat, eksiksiz bir iş akışını uygular: Gelen PDF'leri içeren bir klasörü tarar, her birini işler, çıkarılan verileri doğrular, başarılı çıkarımları muhasebe sisteminize yönlendirir ve hataları manuel inceleme için karantinaya alır. Özet rapor, işleme sonuçlarına dair görünürlük sağlar.
---
## How to Integrate C# Invoice Processing with Accounting Systems
Sonuç olarak, çıkarılan fatura verileri ödeme ve kayıt tutma amaçlı muhasebe sistemlerine akmalıdır. Özellikler platforma göre değişir, ancak entegrasyon desenleri tutarlıdır.
<a id="anchor-integration-patterns-quickbooks-xero-sap"></a>
### QuickBooks, Xero ve SAP İçin Yaygın Entegrasyon Desenleri Neler?
Çoğu muhasebe platformu, fatura veya faturaları programlı olarak oluşturmak için REST API'leri sunar. İşte özel platformunuza uyarlayabileceğiniz genel bir desen:
```csharp
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}");
}
}
```
Her platformun kendi kimlik doğrulama mekanizması (QuickBooks ve Xero için OAuth, SAP için çeşitli yöntemler), gerekli alanlar ve API kuralları vardır. Hedef platformunuzun belgelerine başvurun, ancak çıkarılan fatura verilerini API yüklerine dönüştürme deseni tutarlıdır.
<a id="anchor-batch-process-hundreds-of-invoices"></a>
### Yüzlerce Faturayı Toplu İşleme Nasıl Yapılır
Yüksek hacimli fatura işleme, eşzamanlılık ve kaynak yönetimine özen göstermeyi gerektirir. Kontrollü eşzamanlılıkla paralel işlemeyi kullanan bir desen:
```csharp
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
// Tracks the result of processing a single invoice in a batch
public class BatchResult
{
public string FilePath { get; set; }
public bool Success { get; set; }
public string InvoiceNumber { get; set; }
public string Error { get; set; }
}
// High-volume invoice processor with controlled parallelism
// Prevents overwhelming APIs while maximizing throughput
public class BatchInvoiceProcessor
{
private readonly SmartInvoiceProcessor _invoiceProcessor;
private readonly AccountingSystemIntegration _accountingIntegration;
private readonly int _maxConcurrency;
public BatchInvoiceProcessor(string aiApiKey, string accountingApiKey,
string accountingUrl, int maxConcurrency = 5)
{
_invoiceProcessor = new SmartInvoiceProcessor(aiApiKey);
_accountingIntegration = new AccountingSystemIntegration(accountingApiKey, accountingUrl);
_maxConcurrency = maxConcurrency; // Adjust based on API rate limits
}
// Processes multiple invoices in parallel with controlled concurrency
public async Task<List<BatchResult>> ProcessInvoiceBatch(List<string> invoicePaths)
{
// Thread-safe collection for gathering results from parallel tasks
var results = new ConcurrentBag<BatchResult>();
// Semaphore limits how many invoices process simultaneously
var semaphore = new SemaphoreSlim(_maxConcurrency);
// Create a task for each invoice
var tasks = invoicePaths.Select(async path =>
{
// Wait for a slot to become available
await semaphore.WaitAsync();
try
{
var result = await ProcessSingleInvoice(path);
results.Add(result);
}
finally
{
// Release slot for next invoice
semaphore.Release();
}
});
// Wait for all invoices to complete
await Task.WhenAll(tasks);
// Output summary statistics
var resultList = results.ToList();
int successful = resultList.Count(r => r.Success);
int failed = resultList.Count(r => !r.Success);
Console.WriteLine($"\nBatch Processing Complete:");
Console.WriteLine($" Total: {resultList.Count}");
Console.WriteLine($" Successful: {successful}");
Console.WriteLine($" Failed: {failed}");
return resultList;
}
// Processes one invoice: extract data and send to accounting system
private async Task<BatchResult> ProcessSingleInvoice(string pdfPath)
{
try
{
Console.WriteLine($"Processing: {pdfPath}");
var invoiceData = await _invoiceProcessor.ProcessAnyInvoice(pdfPath);
await _accountingIntegration.SendToQuickBooks(invoiceData);
Console.WriteLine($"✓ Completed: {invoiceData.InvoiceNumber}");
return new BatchResult
{
FilePath = pdfPath,
Success = true,
InvoiceNumber = invoiceData.InvoiceNumber
};
}
catch (Exception ex)
{
Console.WriteLine($"✗ Failed: {pdfPath}");
return new BatchResult
{
FilePath = pdfPath,
Success = false,
Error = ex.Message
};
}
}
}
```
`SemaphoreSlim`, harici API'ları aşırı yüklememenizi veya sistem kaynaklarını tüketmemenizi sağlar. `_maxConcurrency`, API hız limitlerinize ve sunucu kapasitenize göre ayarlayın. `ConcurrentBag`, paralel işlemlerden güvenle sonuç toplar.
---
## Sonraki Adımlar
Fatura otomasyonu, manuel çalışmayı azaltma, hataları en aza indirme ve iş süreçlerini hızlandırma açısından önemli bir fırsat sunar. Bu kılavuz, profesyonel faturalar oluşturmaktan [HTML şablonlarından](/tutorials/html-to-pdf/), [ZUGFeRD ve Factur-X](/product-updates/milestones-pdf-a3-zugferd/) e-faturalama standartlarına uygun hale getirmeye, [verileri çıkarmaktan](/how-to/extract-text-and-images/) alınan faturalar, desen eşleştirme ve [AI destekli çıkartma](/tutorials/ai-powered-pdf-processing-csharp/) kullanarak ve ölçeklenebilir otomasyon hatları oluşturmaya kadar eksiksiz bir yaşam döngüsü sunar.
IronPDF, bu yeteneklerin temeli olarak hizmet verir, sağlam HTML'den PDF'e dönüştürme, güvenilir [metin çıkarma](/how-to/csharp-parse-pdf/) ve gereksinim duyulan ekleme özelliklerini sağlayarak [PDF/A-3 e-faturalama uygunluğu](/how-to/pdfa/) sağlar. Chrome tabanlı rendering motoru, faturalarınızın tam olarak tasarlandığı gibi görünmesini sağlarken, çıkarım yöntemleri PDF metin kodlamasının karmaşıklığını otomatik olarak ele alır.
Burada görülen modeller başlangıç noktalarıdır. Gerçek uygulamalar, belirli fatura formatlarınız, muhasebe sistemleriniz ve iş kurallarınız için uyarlama gerektirecektir. Yüksek hacimli senaryolar için, [toplu işlem eğitimi](/tutorials/batch-pdf-processing-csharp/), kontrollü eşzamanlılık ve hata kurtarma ile paralel uygulamayı ele alır.
İşe başlamaya hazır mısınız? [IronPDF'i İndirin](download-modal) ve ücretsiz bir deneme ile deneyin. Kütüphane, fatura oluşturma, veri çıkarma, ve [PDF rapor özelliklerini](/how-to/csharp-pdf-reports/) değerlendirebilmeniz için ücretsiz bir geliştirme lisansı içerir, üretim lisansı almadan önce. Eğer fatura otomasyonu veya muhasebe sistemi entegrasyonu hakkında sorularınız varsa, [mühendislik destek ekibimize ulaşın](/troubleshooting/engineering-request-pdf/).
Fatura işlemeC# .NET ile IronPDF, HTML şablonlarından profesyonel PDF faturaları oluşturmayı, ZUGFeRD ve Factur-X uyumlu e-faturalandırma standartları ile uyum sağlamayı, metin ayrıştırma ve yapay zeka destekli işleme kullanarak alınan faturalardan yapılandırılmış veri çıkarmayı ve QuickBooks, Xero ve SAP gibi muhasebe sistemleriyle entegre edilen toplu otomasyon boru hatları oluşturmaktadır.
Kısa-Özet: Hızlı Başlangıç Kılavuzu
Bu kılavuz, C# .NET'te fatura oluşturma, çıkarma ve otomasyonu ele alır, e-fatura uyumluluğu, yapay zeka destekli ayrıştırma ve muhasebe sistemi entegrasyonunu içerir.
Ne geliştireceksiniz: Satır öğeleri ve vergi hesaplamalarıyla HTML şablonlu fatura oluşturma, ödeme bağlantıları için QR kodlar, ZUGFeRD/Factur-X uyumlu PDF/A-3 çıktısı, regex ile metin çıkarma, yapay zeka destekli fatura ayrıştırma ve muhasebe sistemi entegrasyonu ile toplu işleme.
Nerede çalışır: .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 standartlarına uymanız veya borç hesapları için tedarikçi faturalarından veri çıkarmanız gerektiğinde.
Teknik olarak neden önemlidir: IronPDF, HTML'i PDF'ye piksel mükemmel hassasiyetle dönüştürür, gömülü XML için PDF/A-3'ü destekler ve regex veya yapay zeka ile eşleştirilebilen metin çıkarma API'leri sağlar.
İlk PDF faturalarınızı sadece birkaç satır kodla oluşturun:
1Install IronPDF with NuGet Package Manager
PM > Install-Package IronPdf
Install-Package IronPdf
2Bu kod parçacığını kopyalayın ve ç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");
var renderer = new IronPdf.ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Invoice #1001</h1><p>Total: $500.00</p>");
pdf.SaveAs("invoice.pdf");
Dim renderer = New IronPdf.ChromePdfRenderer()Dim pdf = renderer.RenderHtmlAsPdf("<h1>Invoice #1001</h1><p>Total: $500.00</p>")pdf.SaveAs("invoice.pdf")
Dim renderer = New IronPdf.ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Invoice #1001</h1><p>Total: $500.00</p>")
pdf.SaveAs("invoice.pdf")
3Canlı ortamınızda test için dağıtım yapın
Ücretsiz deneme ile bugün projenizde IronPDF kullanmaya başlayın
IronPDF'yi satın aldıktan veya 30 günlük denemeye kaydolduktan sonra, başvurunuzda lisans anahtarınızı ekleyin.
Install IronPDF by running the command above in the NuGet Package Manager Console, or search for the package in the NuGet Package Manager.
Fatura Yaşam Döngüsü Nedir ve Neden PDF Standart Kalıyor?
Koda dalmadan önce, bir faturanın modern bir iş sistemi boyunca aldığı yolculuğu anlamak faydalı 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şturma ile başlar. Bir işletme, satır öğeleri, fiyatlandırma, vergi hesaplamaları, ödeme koşulları ve markalama içeren bir fatura oluşturur. Fatura profesyonel görünmelidir ve tüm yasal gerekliliklere uygun olmalıdır. Sonra dağıtım gelir, burada fatura müşteri portalı aracılığıyla veya geleneksel posta yoluyla müşteri e-postasına gönderilir. Müşteri aldığında, borç hesapları ekibi belgeyi yakalayıp işlemek üzere hazırlar. Veri çıkarma, fatura, satır öğeleri, toplamlar ve vade tarihleri gibi anahtar bilgileri çıkarır, böylece bunlar satın alma emirlerine karşı kontrol edilebilir ve eşleşebilir. Son olarak, muhasebe entegrasyonu bu verileri QuickBooks, Xero veya SAP gibi finansal sistemlere ödeme ve kayıt tutma için taşır.
Peki PDF bu kadar yıl sonra halen en yaygın olarak kullanılan format neden? Bu, eşsiz bir avantajlar karışımına dayanıyor. PDF'ler, fatura biçimlendirmesini hangi cihaz veya işletim sistemini kullanırsanız kullanın tutarlılıkla korur. Birisi faturalarınızı Windows, Mac veya telefonunda açsa bile, tam olarak tasarladığınız gibi görünecektir. PDF'ler yanlışlıkla değişime karşı da zordur, bu yüzden belgelerinizin bütünlüğünü, Word veya Excel gibi formatlardan daha iyi korurlar. Kimlik doğrulama 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 geldi.
Elbette, burada bir zorluk var. PDF'ler insanların okumalarını kolaylaştırmak için yapılmış, bilgisayarların işlemesi için değil. Bilgiyi yapılandırılmış veri içinde saklamak yerine, bir PDF sayfada göründükleri yere göre metin, çizgiler, şekiller ve görüntüler kaydeder. Bu yüzden IronPDF gibi araçlar son derece yararlıdır, insan dostu belgeleri yazılımın çalışabileceği verilere dönüştürmeyi mümkün kılar.
How to Generate Professional PDF Invoices in C#
Faturaları programatik olarak oluşturmak, müşteri bilgileri, satır öğeler 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 teknolojilerini kullanarak bunu son derece basit hale getirir.
Bu öğretici makalede, gerçek dünyada karşılaşacağınız muhtemel senaryoları inceleyeceğ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ı ile uğraşmak yerine, standart HTML ve CSS kullanarak faturanızı tasarlar, sonra IronPDF'nin Chrome tabanlı render motorunun onu piksel mükemmel PDF'ye dönüştürmesine izin verirsiniz.
İşte yaklaşımı gösteren temel bir fatura şablonu:
using IronPdf;// Define the HTML template for a basic invoice// Uses inline CSS for styling headers, tables, and totalsstring invoiceHtml = @"<!DOCTYPE html><html><head><style>body { font-family: Arial, sans-serif; padding: 40px; }.header { text-align: right; margin-bottom: 40px; }.company-name { font-size: 24px; font-weight: bold; color: #333; }.invoice-title { font-size: 32px; margin: 20px 0; }.bill-to { margin: 20px 0; }table { width: 100%; border-collapse: collapse; margin: 20px 0; }th { background-color: #2A95D5; color: white; padding: 10px; text-align: left; }td { padding: 10px; border-bottom: 1px solid #ddd; }.total { text-align: right; font-size: 20px; font-weight: bold; margin-top: 20px; }</style></head><body><div class='header'><div class='company-name'>Your Company Name</div><div>123 Business Street</div><div>City, State 12345</div></div><div class='invoice-title'>INVOICE</div><div class='bill-to'><strong>Bill To:</strong><br>Customer Name<br>456 Customer Avenue<br>City, State 67890</div><table><tr> <th>Description</th> <th>Quantity</th> <th>Price</th> <th>Total</th></tr><tr> <td>Web Development Services</td> <td>10 hours</td> <td>$100.00</td> <td>$1,000.00</td></tr><tr> <td>Consulting</td> <td>5 hours</td> <td>$150.00</td> <td>$750.00</td></tr></table><div class='total'>Total: $1,750.00</div></body></html>";// Initialize the Chrome-based PDF renderervar renderer = new ChromePdfRenderer();// Convert the HTML string to a PDF documentvar pdf = renderer.RenderHtmlAsPdf(invoiceHtml);// Save the generated PDF to diskpdf.SaveAs("basic-invoice.pdf");
using IronPdf;
// Define the HTML template for a basic invoice
// Uses inline CSS for styling headers, tables, and totals
string invoiceHtml = @"
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; padding: 40px; }
.header { text-align: right; margin-bottom: 40px; }
.company-name { font-size: 24px; font-weight: bold; color: #333; }
.invoice-title { font-size: 32px; margin: 20px 0; }
.bill-to { margin: 20px 0; }
table { width: 100%; border-collapse: collapse; margin: 20px 0; }
th { background-color: #2A95D5; color: white; padding: 10px; text-align: left; }
td { padding: 10px; border-bottom: 1px solid #ddd; }
.total { text-align: right; font-size: 20px; font-weight: bold; margin-top: 20px; }
</style>
</head>
<body>
<div class='header'>
<div class='company-name'>Your Company Name</div>
<div>123 Business Street</div>
<div>City, State 12345</div>
</div>
<div class='invoice-title'>INVOICE</div>
<div class='bill-to'>
<strong>Bill To:</strong><br>
Customer Name<br>
456 Customer Avenue<br>
City, State 67890
</div>
<table>
<tr>
<th>Description</th>
<th>Quantity</th>
<th>Price</th>
<th>Total</th>
</tr>
<tr>
<td>Web Development Services</td>
<td>10 hours</td>
<td>$100.00</td>
<td>$1,000.00</td>
</tr>
<tr>
<td>Consulting</td>
<td>5 hours</td>
<td>$150.00</td>
<td>$750.00</td>
</tr>
</table>
<div class='total'>Total: $1,750.00</div>
</body>
</html>";
// Initialize the Chrome-based PDF renderer
var renderer = new ChromePdfRenderer();
// Convert the HTML string to a PDF document
var pdf = renderer.RenderHtmlAsPdf(invoiceHtml);
// Save the generated PDF to disk
pdf.SaveAs("basic-invoice.pdf");
ImportsIronPdf' Define the HTML template for a basic invoice' Uses inline CSS for styling headers, tables, and totalsDim invoiceHtml AsString = "<!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 rendererDim renderer = New ChromePdfRenderer()' Convert the HTML string to a PDF documentDim pdf = renderer.RenderHtmlAsPdf(invoiceHtml)' Save the generated PDF to diskpdf.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 = 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")
Örnek Çıktı
Bu yaklaşım muazzam bir esneklik sunar. Chrome'da çalışan herhangi bir CSS PDF'nizde çalışacaktır, flexbox, grid düzenleri ve özel fontlar gibi modern özellikler dahil. URL'ler veya yerel dosya yollarını referans alarak harici stil sayfaları ve görüntüleri bile kullanabilirsiniz.
Dinamik Satır Öğeleri Ekleyin ve Toplamları Hesaplayın
Gerçek faturalar nadiren statik içerik taşır. Satır öğelerini bir veritabanından çıkarmanız, ara toplamları hesaplamanız, vergi oranları uygulamanız ve para birimi değerlerini biçimlendirmenizde gereklidir. Aşağıdaki örnek, dinamik fatura üretimi için üretim hazır bir deseni göstermektedir.
using IronPdf;using System;using System.Collections.Generic;using System.Linq;// Represents a single line item on an invoicepublic class InvoiceLineItem{ public stringDescription { get; set; } public decimalQuantity { get; set; } public decimalUnitPrice { get; set; } // Auto-calculates line total from quantity and unit price public decimalTotal => Quantity * UnitPrice;}// Represents a complete invoice with customer details and line itemspublic class Invoice{ public stringInvoiceNumber { get; set; } public DateTimeInvoiceDate { get; set; } public stringCustomerName { get; set; } public stringCustomerAddress { get; set; } public List<InvoiceLineItem> LineItems { get; set; } // Computed properties for invoice totals public decimalSubtotal => LineItems.Sum(item => item.Total); public decimalTaxRate { get; set; } = 0.08m; // Default 8% tax rate public decimalTax => Subtotal * TaxRate; public decimalTotal => Subtotal + Tax;}// Generates PDF invoices from Invoice objects using HTML templatespublic class InvoiceGenerator{ public PdfDocumentGenerateInvoice(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);
}
}
ImportsIronPdfImportsSystemImportsSystem.Collections.GenericImportsSystem.Linq' Represents a single line item on an invoicePublic Class InvoiceLineItem Public Property DescriptionAsString Public Property QuantityAsDecimal Public Property UnitPriceAsDecimal ' Auto-calculates line total from quantity and unit price PublicReadOnlyPropertyTotalAsDecimal Get ReturnQuantity * UnitPriceEnd Get End PropertyEnd Class' Represents a complete invoice with customer details and line itemsPublic Class Invoice Public Property InvoiceNumberAsString Public Property InvoiceDateAsDateTime Public Property CustomerNameAsString Public Property CustomerAddressAsString Public Property LineItemsAsList(OfInvoiceLineItem) ' Computed properties for invoice totals PublicReadOnlyPropertySubtotalAsDecimal Get ReturnLineItems.Sum(Function(item) item.Total)End Get End Property Public Property TaxRateAsDecimal = 0.08D ' Default 8% tax rate PublicReadOnlyPropertyTaxAsDecimal Get ReturnSubtotal * TaxRateEnd Get End Property PublicReadOnlyPropertyTotalAsDecimal Get ReturnSubtotal + TaxEnd Get End PropertyEnd Class' Generates PDF invoices from Invoice objects using HTML templatesPublic Class InvoiceGenerator Public Function GenerateInvoice(invoice AsInvoice) AsPdfDocument ' Build HTML table rows dynamically from line items Dim lineItemsHtml AsString = 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 AsString = $"<!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 = New ChromePdfRenderer() Return renderer.RenderHtmlAsPdf(invoiceHtml) End FunctionEnd Class
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 = New ChromePdfRenderer()
Return renderer.RenderHtmlAsPdf(invoiceHtml)
End Function
End Class
Örnek Çıktı
Invoice sınıfı, ara toplam, vergi ve toplam için hesaplanan özelliklerle tüm fatura verilerini kapsar. Üretici, bu verileri dizgi iç içeleme kullanarak HTML'ye dönüştürür, ardından PDF'ye rendeler. Bu ayrımlaşma, kodu sürdürülebilir ve test edilebilir hale getirir.
Şirket Markalama ve Filigranlarını Faturalara Ekleyin
Profesyonel faturalar, logolar gibi markalama unsurlarına ve bazı durumlarda ödeme durumunu belirtmek için filigranlara ihtiyaç duyar. IronPDF, HTML'de gömülü görüntüler ve render sonrası programatik filigranlama desteği sunar.
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 pathstring htmlWithLogo = @"<!DOCTYPE html><html><head><style>body { font-family: Arial, sans-serif; padding: 40px; }.logo { width: 200px; margin-bottom: 20px; }</style></head><body><div style='text-align: center;'><img src='https://yourcompany.com/logo.png' alt='Company Logo' class='logo' /></div><h1>INVOICE</h1><p><strong>Invoice Number:</strong> INV-2024-001</p><p><strong>Total:</strong> $1,250.00</p></body></html>";// Render the HTML to PDFvar pdf = renderer.RenderHtmlAsPdf(htmlWithLogo);// Apply a diagonal "UNPAID" watermark to mark invoice status// 30% opacity keeps the content readable while the watermark is visiblepdf.ApplyWatermark("<h1 style='color: red;'>UNPAID</h1>", opacity: 30, rotation: 45, verticalAlignment: IronPdf.Editing.VerticalAlignment.Middle);pdf.SaveAs("invoice-with-watermark.pdf");
using IronPdf;
var renderer = new ChromePdfRenderer();
// Invoice HTML template with company logo embedded via URL
// Logo can also be Base64-encoded or a local file path
string htmlWithLogo = @"
<!DOCTYPE html>
<html>
<head>
<style>
body { font-family: Arial, sans-serif; padding: 40px; }
.logo { width: 200px; margin-bottom: 20px; }
</style>
</head>
<body>
<div style='text-align: center;'>
<img src='https://yourcompany.com/logo.png' alt='Company Logo' class='logo' />
</div>
<h1>INVOICE</h1>
<p><strong>Invoice Number:</strong> INV-2024-001</p>
<p><strong>Total:</strong> $1,250.00</p>
</body>
</html>";
// Render the HTML to PDF
var pdf = renderer.RenderHtmlAsPdf(htmlWithLogo);
// Apply a diagonal "UNPAID" watermark to mark invoice status
// 30% opacity keeps the content readable while the watermark is visible
pdf.ApplyWatermark("<h1 style='color: red;'>UNPAID</h1>",
opacity: 30,
rotation: 45,
verticalAlignment: IronPdf.Editing.VerticalAlignment.Middle);
pdf.SaveAs("invoice-with-watermark.pdf");
ImportsIronPdfDim renderer = New ChromePdfRenderer()' Invoice HTML template with company logo embedded via URL' Logo can also be Base64-encoded or a local file pathDim htmlWithLogo AsString = "<!DOCTYPE html><html><head><style>body { font-family: Arial, sans-serif; padding: 40px; }.logo { width: 200px; margin-bottom: 20px; }</style></head><body><div style='text-align: center;'><img src='https://yourcompany.com/logo.png' alt='Company Logo' class='logo' /></div><h1>INVOICE</h1><p><strong>Invoice Number:</strong> INV-2024-001</p><p><strong>Total:</strong> $1,250.00</p></body></html>"' Render the HTML to PDFDim pdf = renderer.RenderHtmlAsPdf(htmlWithLogo)' Apply a diagonal "UNPAID" watermark to mark invoice status' 30% opacity keeps the content readable while the watermark is visiblepdf.ApplyWatermark("<h1 style='color: red;'>UNPAID</h1>", opacity:=30, rotation:=45, verticalAlignment:=IronPdf.Editing.VerticalAlignment.Middle)pdf.SaveAs("invoice-with-watermark.pdf")
Imports IronPdf
Dim renderer = 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' />
</div>
<h1>INVOICE</h1>
<p><strong>Invoice Number:</strong> INV-2024-001</p>
<p><strong>Total:</strong> $1,250.00</p>
</body>
</html>"
' Render the HTML to PDF
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")
Örnek Çıktı
ApplyWatermark metodu, sizin işaret filigranının görünümü üzerinde tam kontrol sahibi olmanızı sağlayarak HTML içeriğini kabul eder. İhtiyacınız olan görünümü elde etmek için opaklığı, dönüşü ve konumlandırmayı ayarlayabilirsiniz. Bu, özellikle faturaları "ÖDENMİŞ", "TASLAK" veya "İPTAL EDİLMİŞ" olarak işaretlemek için faydalıdır, belgenin tamamını tekrar üretmeden.
Ödeme Bağlantıları İçin QR Kodları Gömün
Modern faturalar genellikle müşterilerin hızlıca ödeme yapması için tarayabileceği QR kodları içerir. IronPDF, PDF oluşturma üzerine odaklanırken, IronQR ile barkod oluşturma konusunda sorunsuz çalışır:
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 parametersstring paymentUrl = $"https://yourcompany.com/pay?invoice={invoiceNumber}&amount={amount}";// Generate QR code from the payment URL using IronQRQrCode 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 phonestring invoiceHtml = $@"<!DOCTYPE html><html><head><style>body {{ font-family: Arial, sans-serif; padding: 40px; }}.payment-section {{ margin-top: 40px; text-align: center; border-top: 2px solid #eee; padding-top: 20px; }}.qr-code {{ width: 150px; height: 150px; }}</style></head><body><h1>INVOICE {invoiceNumber}</h1><p><strong>Amount Due:</strong> ${amount:F2}</p><div class='payment-section'><p><strong>Scan to Pay Instantly:</strong></p><img src='payment-qr.png' alt='Payment QR Code' class='qr-code' /><p style='font-size: 12px; color: #666;'> Or visit: {paymentUrl}</p></div></body></html>";// Convert HTML to PDF and savevar renderer = new ChromePdfRenderer();var pdf = renderer.RenderHtmlAsPdf(invoiceHtml);pdf.SaveAs($"invoice-{invoiceNumber}.pdf");
using IronPdf;
using IronQr;
using IronSoftware.Drawing;
string invoiceNumber = "INV-2026-002";
decimal amount = 1500.00m;
// Create a payment URL with invoice details as query parameters
string paymentUrl = $"https://yourcompany.com/pay?invoice={invoiceNumber}&amount={amount}";
// Generate QR code from the payment URL using IronQR
QrCode qrCode = QrWriter.Write(paymentUrl);
AnyBitmap qrImage = qrCode.Save();
qrImage.SaveAs("payment-qr.png", AnyBitmap.ImageFormat.Png);
// Build invoice HTML with the QR code image embedded
// Customers can scan the QR to pay directly from their phone
string invoiceHtml = $@"
<!DOCTYPE html>
<html>
<head>
<style>
body {{ font-family: Arial, sans-serif; padding: 40px; }}
.payment-section {{ margin-top: 40px; text-align: center;
border-top: 2px solid #eee; padding-top: 20px; }}
.qr-code {{ width: 150px; height: 150px; }}
</style>
</head>
<body>
<h1>INVOICE {invoiceNumber}</h1>
<p><strong>Amount Due:</strong> ${amount:F2}</p>
<div class='payment-section'>
<p><strong>Scan to Pay Instantly:</strong></p>
<img src='payment-qr.png' alt='Payment QR Code' class='qr-code' />
<p style='font-size: 12px; color: #666;'>
Or visit: {paymentUrl}
</p>
</div>
</body>
</html>";
// Convert HTML to PDF and save
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(invoiceHtml);
pdf.SaveAs($"invoice-{invoiceNumber}.pdf");
ImportsIronPdfImportsIronQrImportsIronSoftware.DrawingDim invoiceNumber AsString = "INV-2026-002"Dim amount AsDecimal = 1500.0D' Create a payment URL with invoice details as query parametersDim paymentUrl AsString = $"https://yourcompany.com/pay?invoice={invoiceNumber}&amount={amount}"' Generate QR code from the payment URL using IronQRDim qrCode AsQrCode = QrWriter.Write(paymentUrl)Dim qrImage AsAnyBitmap = 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 phoneDim invoiceHtml AsString = $"<!DOCTYPE html><html><head><style>body {{ font-family: Arial, sans-serif; padding: 40px; }}.payment-section {{ margin-top: 40px; text-align: center; border-top: 2px solid #eee; padding-top: 20px; }}.qr-code {{ width: 150px; height: 150px; }}</style></head><body><h1>INVOICE {invoiceNumber}</h1><p><strong>Amount Due:</strong> ${amount:F2}</p><div class='payment-section'><p><strong>Scan to Pay Instantly:</strong></p><img src='payment-qr.png' alt='Payment QR Code' class='qr-code' /><p style='font-size: 12px; color: #666;'> Or visit: {paymentUrl}</p></div></body></html>"' Convert HTML to PDF and saveDim renderer = New ChromePdfRenderer()Dim 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.0D
' 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>
<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 = New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(invoiceHtml)
pdf.SaveAs($"invoice-{invoiceNumber}.pdf")
Örnek Çıktı
QR kodu doğrudan bir ödeme sayfasına bağlanır, müşteriler için sürtüşmeyi azaltır ve nakit akışınızı hızlandırır. Bu desen, URL tabanlı ödeme başlatımını destekleyen herhangi bir ödeme sağlayıcı ile çalışır.
How to Comply with ZUGFeRD and Factur-X E-Invoicing Standards in C#
Elektronik faturalama Avrupa genelinde hızla zorunlu hale geliyor. Öncü olarak ZUGFeRD ile Almanya ve ardından Factur-X ile Fransa geldi. Bu standartlar, PDF faturalar içerisine makine tarafından okunabilir XML verilerini gömerek, otomatik işlem imkanı sunarken, insan tarafından okunabilen belgeleri de muhafaza etmektedir. Bu standartları anlamak ve uygulamak, Avrupa pazarlarında faaliyet gösteren işletmeler için gittikçe daha kritik hale geliyor.
ZUGFeRD Nedir ve Nasıl Çalışır?
ZUGFeRD (Zentraler User Guide des Forums elektronische Rechnung Deutschland), PDF/A-3 uyumlu bir belgede XML dosya eki olarak fatura verilerini gömen bir Alman e-fatura standardıdır. Gömülü XML, OCR veya ayrıştırma olmadan otomatik veri çıkarımına olanak tanır.
Standart, her biri daha fazla yapılandırılmış veri sunan üç uyum seviyesini tanımlar:
Temel: Basit otomatik işleme için uygun olan temel fatura verilerini içerir
Konfor: Tam otomatik fatura işleme olanağı sağlayan ayrıntılı bilgileri ekler
Genişletilmiş: Endüstrileri kapsayan karmaşık iş senaryoları için kapsamlı veri içerir.
XML, Avrupa e-faturalama standartlaştırmasının temeli haline gelen UN/CEFACT Çapraz-Endüstri Fatura (CII) şemasını izler.
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. Aynı XML şeması ve Avrupa Norm EN 16931'a dayalı uyumluluk profillerini paylaşırlar. Fark, tamamen bölgesel adlandırmadır: ZUGFeRD spesifikasyonlarına uygun olarak oluşturulmuş bir fatura, Factur-X altında geçerli olacak ve tam tersi.
XML Verilerini PDF/A-3 Faturalarına Nasıl Gömülür
IronPDF, uyumlu e-faturalar oluşturmak için gerekli olan ekleme yeteneklerini sağlar. Süreç, fatura PDF'nizi oluşturmayı, XML verilerini CII şemasına göre oluşturmayı ve XML'i uygun adlandırma kuralları ile bir ek olarak 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 PDFpublic class ZUGFeRDInvoiceGenerator{ public voidGenerateZUGFeRDInvoice(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 stringBuildInvoiceHtml(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>";
}
}
ImportsSystemImportsSystem.Xml.Linq' Generates ZUGFeRD-compliant invoices by embedding structured XML data' ZUGFeRD allows automated processing while keeping a human-readable PDFPublic Class ZUGFeRDInvoiceGenerator Public Sub GenerateZUGFeRDInvoice(invoice AsInvoice) ' First, create the visual PDF that humans will read Dim renderer = New ChromePdfRenderer() Dim invoiceHtml AsString = 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 AsXNamespace = "urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" Dim ram AsXNamespace = "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" Dim udt AsXNamespace = "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 AsString = $"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 AsInvoice) AsString 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 FunctionEnd Class
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
Örnek Çıktı
Uyumun temel yönleri, doğru XML ad alanlarını kullanmak, CII şema yapısını izlemek ve XML'i uygun bir dosya adıyla gömmektir. TypeCode "380" belgenin UN/CEFACT standardı içinde ticari bir fatura olarak belirlenmesini sağlar.
AB Talimatlarına Göre Faturaları Geleceğe Hazırlama Yolları
Avrupa Birliği, üye devletlerde kademeli olarak e-faturalamayı zorunlu hale getiriyor. İtalya, B2B işlemleri için zaten bu gerekliliği uyguluyor; Fransa, 2026 yılına kadar gereksinimleri aşamalı olarak uyguluyor ve Almanya, 2025'te zorunlu B2B e-faturalamayı duyurdu. Şimdi ZUGFeRD/Factur-X desteği oluşturmak, sisteminizi bu düzenleyici gereksinimlere hazırlar.
İşte farklı standartları hedefleyebilen uyum bilincine sahip bir fatura jeneratörü için bir model:
using IronPdf;using System;// Enum representing supported European e-invoicing standardspublic enum InvoiceStandard{None,ZUGFeRD, // German standard - uses CII XML formatFacturX, // French standard - technically identical to ZUGFeRD 2.0Peppol// 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 logicpublic class CompliantInvoiceGenerator{ public PdfDocumentGenerateCompliantInvoice(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 filenamesEmbedCIIXmlData(pdf, invoice, standard); break; case InvoiceStandard.Peppol: // Peppol uses Universal Business Language formatEmbedUBLXmlData(pdf, invoice); break; } return pdf; } // Creates and embeds CII-format XML (used by ZUGFeRD and Factur-X) private voidEmbedCIIXmlData(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 voidEmbedUBLXmlData(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 stringGenerateCIIXml(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 stringBuildInvoiceHtml(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>";
}
}
ImportsIronPdfImportsSystem' Enum representing supported European e-invoicing standardsPublicEnumInvoiceStandardNoneZUGFeRD' German standard - uses CII XML formatFacturX' French standard - technically identical to ZUGFeRD 2.0Peppol' Pan-European standard - uses UBL XML formatEndEnum' Factory class that generates invoices compliant with different e-invoicing standards' Allows switching between standards without changing core invoice generation logicPublic Class CompliantInvoiceGenerator Public Function GenerateCompliantInvoice(invoice AsInvoice, standard AsInvoiceStandard) AsPdfDocument ' Generate the base PDF from HTML Dim renderer As New ChromePdfRenderer() Dim html AsString = BuildInvoiceHtml(invoice) Dim pdf AsPdfDocument = renderer.RenderHtmlAsPdf(html) ' Attach the appropriate XML format based on target market/regulation Select Case standard CaseInvoiceStandard.ZUGFeRD, InvoiceStandard.FacturX ' Both use Cross-Industry Invoice format, just different filenamesEmbedCIIXmlData(pdf, invoice, standard) CaseInvoiceStandard.Peppol ' Peppol uses Universal Business Language formatEmbedUBLXmlData(pdf, invoice) End Select Return pdf End Function ' Creates and embeds CII-format XML (used by ZUGFeRD and Factur-X) Private Sub EmbedCIIXmlData(pdf AsPdfDocument, invoice AsInvoice, standard AsInvoiceStandard) Dim xml AsString = GenerateCIIXml(invoice) ' Filename convention differs between German and French standards Dim filename AsString = 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 AsPdfDocument, invoice AsInvoice) ' UBL (Universal Business Language) is the Peppol standard format Dim xml AsString = $"<?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 AsInvoice) AsString 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 AsInvoice) AsString Return $"<html><body><h1>Invoice {invoice.InvoiceNumber}</h1></body></html>" End FunctionEnd Class
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
Bu mimari, çekirdek fatura oluşturma mantığınızı yeniden yapılandırmadan ortaya çıkan yeni standartları eklemenizi sağlar. Enum tabanlı yaklaşım, hangi uyum modunun kullanılacağını kullanıcıların veya yapılandırmanın belirlemesini kolaylaştırır.
Bu türden favori kütüphanem IronPDF'dir. PDF dosyalarının hızlı ve verimli bir şekilde işlenmesine olanak tanır. Ayrıca, PDF/A formatına dışa aktarma ve dijital imzalama gibi birçok değerli özelliğe sahiptir.
IronOCR, manuel işleme maliyetinden yıllık 40.000 USD tasarruf etmemizi sağlıyor, üretkenliği artırıyor ve yüksek etkili görevler için kaynakları serbest bırakıyor. Kesinlikle tavsiye ederim.
Faturaların oluşturulması sadece denklemin yarısıdır. Çoğu işletme ayrıca tedarikçilerden fatura alır ve işlemler için veri çıkarmaları gerekir. IronPDF, fatura verilerini yakalamak için temel oluşturan güçlü metin çıkarma yetenekleri sağlar.
Bir PDF Faturasından Metin Çıkarmayı Nasıl Yapılır
En temel çıkarma işlemi, bir PDF'den tüm metin içeriğini almaktır. IronPDF'ün ExtractAllText metodu, PDF metin kodlaması ve konumlandırmasının karmaşıklığını ele alır:
using IronPdf;using System;// Extracts raw text content from PDF invoices for further processingpublic class InvoiceTextExtractor{ // Extracts all text from a PDF in one operation // Best for single-page invoices or when you need the complete content public stringExtractInvoiceText(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 voidExtractTextByPage(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);
}
}
}
ImportsIronPdfImportsSystem' Extracts raw text content from PDF invoices for further processingPublic 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 AsString) AsString Dim pdf = PdfDocument.FromFile(pdfPath) ' IronPDF handles the complexity of PDF text encoding and positioning Dim allText AsString = 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 AsString) Dim pdf = PdfDocument.FromFile(pdfPath) ' Iterate through each page (0-indexed) For i AsInteger = 0 To pdf.PageCount - 1 Dim pageText AsString = pdf.ExtractTextFromPage(i)Console.WriteLine(vbCrLf & "--- Page " & (i + 1).ToString() & " ---")Console.WriteLine(pageText) Next End SubEnd Class
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
Sayfa bazında çıkarım, birden fazla sayfaya yayılan satır öğelerini bulmak gibi belirli bölümleri bulmanız gerektiğinde özellikle çok sayfalı faturalar için yararlıdır, oysa başlık bilgileri yalnızca ilk sayfada görünür.
Satır Ögeleri İçin Tablo Verilerini Nasıl Çıkarılır
Fatura satır ögeleri genellikle tablosal biçimde görünür. PDF'lerin yerel bir tablo yapısı yoktur, 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 itempublic class InvoiceLineItem{ public stringDescription { get; set; } public decimalQuantity { get; set; } public decimalUnitPrice { get; set; } public decimalTotal { get; set; }}// Extracts tabular line item data from PDF invoices// Note: PDFs don't have native table structure, so this uses text parsingpublic 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;
}
}
ImportsIronPdfImportsSystemImportsSystem.Collections.Generic' Data model for a single invoice line itemPublic Class InvoiceLineItem Public Property DescriptionAsString Public Property QuantityAsDecimal Public Property UnitPriceAsDecimal Public Property TotalAsDecimalEnd Class' Extracts tabular line item data from PDF invoices' Note: PDFs don't have native table structure, so this uses text parsingPublic Class InvoiceTableExtractor Public Function ExtractLineItems(pdfPath AsString) AsList(OfInvoiceLineItem) Dim pdf = PdfDocument.FromFile(pdfPath) Dim text AsString = pdf.ExtractAllText() Dim lineItems As New List(OfInvoiceLineItem)() Dim lines() AsString = text.Split(ControlChars.Lf) For Each line AsStringIn lines ' Currency symbols indicate potential line items with amounts If line.Contains("$") OrElse line.Contains("€") ThenConsole.WriteLine($"Potential line item: {line.Trim()}") ' Split on whitespace to separate columns ' Actual parsing logic depends on your invoice format Dim parts() AsString = line.Split(New Char() {ControlChars.Tab, " "c}, StringSplitOptions.RemoveEmptyEntries) ' Try to find numeric values that could be amounts For Each part AsStringIn parts Dim cleaned AsString = part.Replace("$", "").Replace("€", "").Replace(",", "") Dim amount AsDecimal IfDecimal.TryParse(cleaned, amount) ThenConsole.WriteLine($" Found amount: {amount:C}") End If Next End If Next Return lineItems End FunctionEnd Class
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
Ayrıştırma mantığı, fatura formatlarınıza bağlı olarak değişecektir. Bilinir satıcılardan gelen tutarlı formatlara sahip faturalar için formatlara spesifik ayrıştırıcılar oluşturabilirsiniz. Çeşitli formatlar için, makalenin ilerleyen kısımlarında ele alınan AI destekli çıkarma yöntemlerini düşünün.
Fatura Numaraları, Tarihler, ve Toplamlar İçin Desen Eşlemeyi Nasıl Kullanılır
Düzenli ifadeler, fatura metninden belirli veri noktalarını çıkarmak için değerli araçlardır. Fatura numaraları, tarihler ve toplamlar gibi anahtar alanlar genellikle tanınabilir desenleri takip eder:
using IronPdf;using System;using System.Text.RegularExpressions;// Data model for extracted invoice informationpublic class InvoiceData{ public stringInvoiceNumber { get; set; } public stringInvoiceDate { get; set; } public decimalTotalAmount { get; set; } public stringVendorName { get; set; }}// Extracts key invoice fields using regex pattern matching// Multiple patterns handle variations across different vendorspublic class InvoiceParser{ public InvoiceDataParseInvoice(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;
}
}
ImportsIronPdfImportsSystemImportsSystem.Text.RegularExpressions' Data model for extracted invoice informationPublic Class InvoiceData Public Property InvoiceNumberAsString Public Property InvoiceDateAsString Public Property TotalAmountAsDecimal Public Property VendorNameAsStringEnd Class' Extracts key invoice fields using regex pattern matching' Multiple patterns handle variations across different vendorsPublic Class InvoiceParser Public Function ParseInvoice(pdfPath AsString) AsInvoiceData Dim pdf = PdfDocument.FromFile(pdfPath) Dim text AsString = 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 AsString() = { "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 AsStringIn invoiceNumberPatterns Dim match = Regex.Match(text, pattern, RegexOptions.IgnoreCase) If match.SuccessThen invoiceData.InvoiceNumber = match.Groups(1).ValueConsole.WriteLine($"Found Invoice Number: {invoiceData.InvoiceNumber}") Exit For End If Next ' Date patterns for US, European, and written formats Dim datePatterns AsString() = { "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 AsStringIn datePatterns Dim match = Regex.Match(text, pattern, RegexOptions.IgnoreCase) If match.SuccessThen invoiceData.InvoiceDate = match.Groups(1).ValueConsole.WriteLine($"Found Date: {invoiceData.InvoiceDate}") Exit For End If Next ' Look for total amount with various labels Dim totalPatterns AsString() = { "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 AsStringIn totalPatterns Dim match = Regex.Match(text, pattern, RegexOptions.IgnoreCase) If match.SuccessThen ' Remove commas before parsing Dim amountStr AsString = match.Groups(1).Value.Replace(",", "") Dim amount AsDecimal IfDecimal.TryParse(amountStr, amount) Then invoiceData.TotalAmount = amountConsole.WriteLine($"Found Total: ${invoiceData.TotalAmount:F2}") Exit For End If End If Next Return invoiceData End FunctionEnd Class
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
Bu desen tabanlı yaklaşım, tahmin edilebilir formatlara sahip faturalar için iyi çalışır. Çeşitli desen varyasyonları, "Invoice #" ve "Invoice Number:" gibi satıcılar arasındaki yaygın formatlama farklılıklarını ele alır.
Taranmış veya Görüntü Tabanlı Faturalar Ne Olacak?
Yukarıda gösterilen metin çıkarma yöntemleri, gömülü metin içeren PDF'lerle çalışır. Ancak taranmış belgeler ve görüntü tabanlı PDF'ler çıkarılabilir metne sahip değildir. Esasen fatura resimleri gibidirler.
Lütfen dikkate alın: Tarama yapılan faturaları işlemek için, OCR (Optik Karakter Tanımlama) yeteneklerine ihtiyacınız olacak. IronOCR, Iron Suite'nin bir parçası olarak bu tür senaryolarda IronPDF ile sorunsuz bir şekilde entegre olur. Taranan belgeler ve görüntülerden metin çıkarmayı öğrenmek için https://ironsoftware.com/csharp/ocr/ adresini ziyaret edin.
AI Tabanlı Fatura İşlemlerini .NET İle Nasıl Kullanılır
Geleneksel desen eşleme, standartlaştırılmış faturalar için iyi çalışır, ancak gerçek dünya hesapları ödenecek departmanlar sayısız formatta belgeler alır. AI destekli çıkarmanın öne çıktığı yer burasıdır. Büyük dil modelleri, fatura semantiğini anlayabilir ve tanıdık olmayan düzenlerden bile yapılandırılmış veriler çıkarabilir.
AI Tabanlı Fatura Ayrıştırmayı Nasıl Entegre Edilir
AI destekli fatura işleme için desen, IronPDF'nin metin çıkarımıyla LLM API çağrılarını birleştirir. İşte OpenAI uyumlu herhangi bir API ile çalışan genel bir gerçekleştirme:
using IronPdf;using System;using System.Net.Http;using System.Text;using System.Text.Json;using System.Threading.Tasks;// Data model for extracted invoice informationpublic class InvoiceData{ public stringInvoiceNumber { get; set; } public stringInvoiceDate { get; set; } public stringVendorName { get; set; } public decimalTotalAmount { get; set; }}// Leverages AI/LLM APIs to extract structured data from any invoice format// Works with OpenAI or any compatible API endpointpublic class AIInvoiceParser{ private readonly HttpClient _httpClient; private readonly string _apiKey; private readonly string _apiUrl; publicAIInvoiceParser(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;
}
}
ImportsIronPdfImportsSystemImportsSystem.Net.HttpImportsSystem.TextImportsSystem.Text.JsonImportsSystem.Threading.Tasks' Data model for extracted invoice informationPublic Class InvoiceData Public Property InvoiceNumberAsString Public Property InvoiceDateAsString Public Property VendorNameAsString Public Property TotalAmountAsDecimalEnd Class' Leverages AI/LLM APIs to extract structured data from any invoice format' Works with OpenAI or any compatible API endpointPublic Class AIInvoiceParser PrivateReadOnly _httpClient AsHttpClient PrivateReadOnly _apiKey AsString PrivateReadOnly _apiUrl AsString Public Sub New(apiKey AsString, Optional apiUrl AsString = "https://api.openai.com/v1/chat/completions") _apiKey = apiKey _apiUrl = apiUrl _httpClient = New HttpClient() _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_apiKey}") End Sub PublicAsync Function ParseInvoiceWithAI(pdfPath AsString) AsTask(OfInvoiceData) ' First extract raw text from the PDF using IronPDF Dim pdf = PdfDocument.FromFile(pdfPath) Dim invoiceText AsString = pdf.ExtractAllText() ' Construct a prompt that instructs the AI to return structured JSON ' Being explicit about the format reduces parsing errors Dim prompt AsString = $"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 AsString = JsonSerializer.Serialize(requestBody) Dim content As New StringContent(json, Encoding.UTF8, "application/json") Dim response = Await _httpClient.PostAsync(_apiUrl, content) Dim responseJson AsString = Awaitresponse.Content.ReadAsStringAsync() ' Navigate the API response structure to get the extracted contentUsing doc = JsonDocument.Parse(responseJson) Dim messageContent AsString = 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 AsInvoiceData = JsonSerializer.Deserialize(OfInvoiceData)(messageContent, New JsonSerializerOptionsWith {.PropertyNameCaseInsensitive = True}) Return invoiceDataEndUsing End FunctionEnd Class
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
Düşük sıcaklık ayarı (0.1) determiniztik çıktıları teşvik eder, bu, aynı girdi için tutarlı sonuçlar istediğiniz veri çıkarma görevlerinde önemlidir.
Faturalardan Yapılandırılmış JSON Verisi Nasıl Çıkarılır
Satır ögeleri, satıcı detayları ve müşteri bilgilerini içeren daha karmaşık faturalar için daha zengin bir JSON yapısı talep edebilirsiniz:
using IronPdf;using System;using System.Collections.Generic;using System.Text.Json;using System.Threading.Tasks;// Comprehensive invoice data model with all detailspublic class DetailedInvoiceData{ public stringInvoiceNumber { get; set; } public DateTimeInvoiceDate { get; set; } public DateTimeDueDate { get; set; } public VendorInfoVendor { get; set; } public CustomerInfoCustomer { get; set; } public List<LineItem> LineItems { get; set; } public decimalSubtotal { get; set; } public decimalTax { get; set; } public decimalTotal { get; set; }}public class VendorInfo{ public stringName { get; set; } public stringAddress { get; set; } public stringTaxId { get; set; }}public class CustomerInfo{ public stringName { get; set; } public stringAddress { get; set; }}public class LineItem{ public stringDescription { get; set; } public decimalQuantity { get; set; } public decimalUnitPrice { get; set; } public decimalTotal { get; set; }}// Extracts comprehensive invoice data including line items and party detailspublic class StructuredInvoiceExtractor{ private readonly AIInvoiceParser _aiParser; publicStructuredInvoiceExtractor(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
}
}
ImportsIronPdfImportsSystemImportsSystem.Collections.GenericImportsSystem.Text.JsonImportsSystem.Threading.Tasks' Comprehensive invoice data model with all detailsPublic Class DetailedInvoiceData Public Property InvoiceNumberAsString Public Property InvoiceDateAsDateTime Public Property DueDateAsDateTime Public Property VendorAsVendorInfo Public Property CustomerAsCustomerInfo Public Property LineItemsAsList(OfLineItem) Public Property SubtotalAsDecimal Public Property TaxAsDecimal Public Property TotalAsDecimalEnd ClassPublic Class VendorInfo Public Property NameAsString Public Property AddressAsString Public Property TaxIdAsStringEnd ClassPublic Class CustomerInfo Public Property NameAsString Public Property AddressAsStringEnd ClassPublic Class LineItem Public Property DescriptionAsString Public Property QuantityAsDecimal Public Property UnitPriceAsDecimal Public Property TotalAsDecimalEnd Class' Extracts comprehensive invoice data including line items and party detailsPublic Class StructuredInvoiceExtractor PrivateReadOnly _aiParser AsAIInvoiceParser Public Sub New(apiKey AsString) _aiParser = New AIInvoiceParser(apiKey) End Sub PublicAsync Function ExtractDetailedData(pdfPath AsString) AsTask(OfDetailedInvoiceData) Dim pdf = PdfDocument.FromFile(pdfPath) Dim text AsString = 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 AsString = "{ ""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 AsString = $"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 FunctionEnd Class
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
Çelişkili Fatura Formatları Nasıl Yönetilir
Aynı anda birden fazla satıcıdan gelen, her birinin benzersiz formatları olan faturaları işlerken AI çıkarmanın gerçek gücü ortaya çıkar. Akıllı bir işlemci, önce desen tabanlı çıkarımı uygulayabilir (daha hızlı ve ücretsiz) ve gerektiğinde yalnızca AI'ya geri dönebilir.
using IronPdf;using System.Threading.Tasks;// Hybrid processor that optimizes for cost and capability// Tries fast regex patterns first, uses AI only when patterns failpublic class SmartInvoiceProcessor{ private readonly AIInvoiceParser _aiParser; publicSmartInvoiceProcessor(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 layoutConsole.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 boolIsComplete(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;
}
}
ImportsIronPdfImportsSystem.Threading.Tasks' Hybrid processor that optimizes for cost and capability' Tries fast regex patterns first, uses AI only when patterns failPublic Class SmartInvoiceProcessor PrivateReadOnly _aiParser AsAIInvoiceParser Public Sub New(aiApiKey AsString) _aiParser = New AIInvoiceParser(aiApiKey) End Sub PublicAsync Function ProcessAnyInvoice(pdfPath AsString) AsTask(OfInvoiceData) Dim pdf = PdfDocument.FromFile(pdfPath) Dim text AsString = 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 IfIsComplete(standardResult) ThenConsole.WriteLine("Pattern extraction successful") Return standardResult End If ' Fallback: use AI for complex or unusual invoice formats ' This costs money but handles any layoutConsole.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 AsInvoiceData) AsBoolean ReturnNotString.IsNullOrEmpty(data.InvoiceNumber) AndAlsoNotString.IsNullOrEmpty(data.InvoiceDate) AndAlso data.TotalAmount > 0 End FunctionEnd Class
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
Ödenecek Hesaplar Otomasyon Hattı Nasıl Kurulur
Tüm bu parçaları bir araya getirdiğinizde, gelen faturaları işleyen, verileri çıkaran, doğrulayan ve muhasebe sisteminize hazırlayan eksiksiz bir otomasyon hattı:
using IronPdf;using System;using System.IO;using System.Threading.Tasks;using System.Collections.Generic;using System.Linq;// Tracks the outcome of processing each invoicepublic class ProcessingResult{ public stringFileName { get; set; } public boolSuccess { get; set; } public stringInvoiceNumber { get; set; } public stringErrorMessage { get; set; }}// Complete automation pipeline for accounts payable// Watches a folder, extracts data, validates, and routes to accounting systempublic class InvoiceAutomationPipeline{ private readonly SmartInvoiceProcessor _processor; private readonly string _inputFolder; private readonly string _processedFolder; private readonly string _errorFolder; publicInvoiceAutomationPipeline(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 existDirectory.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.) awaitSaveToAccountingSystem(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 boolValidateInvoiceData(InvoiceData data) { return !string.IsNullOrEmpty(data.InvoiceNumber) && !string.IsNullOrEmpty(data.VendorName) && data.TotalAmount > 0; } // Placeholder for accounting system integration private async TaskSaveToAccountingSystem(InvoiceData data) { // Integrate with your accounting system here // Examples: QuickBooks API, Xero API, SAP, or database storageConsole.WriteLine($" Saved invoice {data.InvoiceNumber} to accounting system"); awaitTask.CompletedTask; } // Outputs a summary of the batch processing results private voidGenerateReport(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}");
}
}
}
}
ImportsIronPdfImportsSystemImportsSystem.IOImportsSystem.Threading.TasksImportsSystem.Collections.GenericImportsSystem.Linq' Tracks the outcome of processing each invoicePublic Class ProcessingResult Public Property FileNameAsString Public Property SuccessAsBoolean Public Property InvoiceNumberAsString Public Property ErrorMessageAsStringEnd Class' Complete automation pipeline for accounts payable' Watches a folder, extracts data, validates, and routes to accounting systemPublic Class InvoiceAutomationPipeline PrivateReadOnly _processor AsSmartInvoiceProcessor PrivateReadOnly _inputFolder AsString PrivateReadOnly _processedFolder AsString PrivateReadOnly _errorFolder AsString Public Sub New(apiKey AsString, inputFolder AsString) _processor = New SmartInvoiceProcessor(apiKey) _inputFolder = inputFolder _processedFolder = Path.Combine(inputFolder, "processed") _errorFolder = Path.Combine(inputFolder, "errors") ' Create output directories if they don't existDirectory.CreateDirectory(_processedFolder)Directory.CreateDirectory(_errorFolder) End Sub ' Main entry point - processes all PDFs in the input folder PublicAsync Function ProcessInvoiceBatch() AsTask(OfList(OfProcessingResult)) Dim invoiceFiles AsString() = Directory.GetFiles(_inputFolder, "*.pdf")Console.WriteLine($"Found {invoiceFiles.Length} invoices to process") Dim results As New List(OfProcessingResult)() For Each invoicePath AsStringIn invoiceFiles Dim fileName AsString = Path.GetFileName(invoicePath)TryConsole.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 IfValidateInvoiceData(invoiceData) Then ' Send to accounting system (QuickBooks, Xero, etc.)AwaitSaveToAccountingSystem(invoiceData) ' Archive successful invoices Dim destPath AsString = Path.Combine(_processedFolder, fileName)File.Move(invoicePath, destPath, overwrite:=True) results.Add(New ProcessingResultWith { .FileName = fileName, .Success = True, .InvoiceNumber = invoiceData.InvoiceNumber })Console.WriteLine($"✓ Processed: {invoiceData.InvoiceNumber}") ElseThrow New Exception("Validation failed - missing required fields") End IfCatch ex AsExceptionConsole.WriteLine($"✗ Failed: {fileName} - {ex.Message}") ' Quarantine failed invoices for manual review Dim destPath AsString = Path.Combine(_errorFolder, fileName)File.Move(invoicePath, destPath, overwrite:=True) results.Add(New ProcessingResultWith { .FileName = fileName, .Success = False, .ErrorMessage = ex.Message })EndTry NextGenerateReport(results) Return results End Function ' Checks for minimum required fields Private Function ValidateInvoiceData(data AsInvoiceData) AsBoolean ReturnNotString.IsNullOrEmpty(data.InvoiceNumber) AndAlsoNotString.IsNullOrEmpty(data.VendorName) AndAlso data.TotalAmount > 0 End Function ' Placeholder for accounting system integration PrivateAsync Function SaveToAccountingSystem(data AsInvoiceData) AsTask ' Integrate with your accounting system here ' Examples: QuickBooks API, Xero API, SAP, or database storageConsole.WriteLine($" Saved invoice {data.InvoiceNumber} to accounting system")AwaitTask.CompletedTask End Function ' Outputs a summary of the batch processing results Private Sub GenerateReport(results AsList(OfProcessingResult)) Dim successful AsInteger = results.Count(Function(r) r.Success) Dim failed AsInteger = 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 ThenConsole.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 SubEnd Class
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
Bu hat, eksiksiz bir iş akışını uygular: Gelen PDF'leri içeren bir klasörü tarar, her birini işler, çıkarılan verileri doğrular, başarılı çıkarımları muhasebe sisteminize yönlendirir ve hataları manuel inceleme için karantinaya alır. Özet rapor, işleme sonuçlarına dair görünürlük sağlar.
How to Integrate C# Invoice Processing with Accounting Systems
Sonuç olarak, çıkarılan fatura verileri ödeme ve kayıt tutma amaçlı muhasebe sistemlerine akmalıdır. Özellikler platforma göre değişir, ancak entegrasyon desenleri tutarlıdır.
QuickBooks, Xero ve SAP İçin Yaygın Entegrasyon Desenleri Neler?
Çoğu muhasebe platformu, fatura veya faturaları programlı olarak oluşturmak için REST API'leri sunar. İşte özel platformunuza uyarlayabileceğiniz genel bir 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 platformpublic class AccountingSystemIntegration{ private readonly HttpClient _httpClient; private readonly string _apiKey; private readonly string _baseUrl; publicAccountingSystemIntegration(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 TaskSendToQuickBooks(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" } } } } }; awaitPostToApi("/v3/company/{companyId}/bill", bill); } // Creates an accounts payable invoice in Xero public async TaskSendToXero(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 }; awaitPostToApi("/api.xro/2.0/Invoices", bill); } // Generic POST helper with error handling private async TaskPostToApi(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}");
}
}
ImportsSystemImportsSystem.Net.HttpImportsSystem.TextImportsSystem.Text.JsonImportsSystem.Threading.Tasks' Generic integration layer for pushing invoice data to accounting systems' Adapt the API calls based on your specific platformPublic Class AccountingSystemIntegration PrivateReadOnly _httpClient AsHttpClient PrivateReadOnly _apiKey AsString PrivateReadOnly _baseUrl AsString Public Sub New(apiKey AsString, baseUrl AsString) _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") PublicAsync Function SendToQuickBooks(invoice AsInvoiceData) AsTask ' 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"} } } } }AwaitPostToApi("/v3/company/{companyId}/bill", bill) End Function ' Creates an accounts payable invoice in Xero PublicAsync Function SendToXero(invoice AsInvoiceData) AsTask ' 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 }AwaitPostToApi("/api.xro/2.0/Invoices", bill) End Function ' Generic POST helper with error handling PrivateAsync Function PostToApi(endpoint AsString, payload AsObject) AsTask Dim json AsString = JsonSerializer.Serialize(payload) Dim content = New StringContent(json, Encoding.UTF8, "application/json") Dim response = Await _httpClient.PostAsync($"{_baseUrl}{endpoint}", content) IfNotresponse.IsSuccessStatusCodeThen Dim error AsString = Awaitresponse.Content.ReadAsStringAsync()Throw New Exception($"API Error: {response.StatusCode} - {error}") End IfConsole.WriteLine($"Successfully posted to {endpoint}") End FunctionEnd Class
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
Her platformun kendi kimlik doğrulama mekanizması (QuickBooks ve Xero için OAuth, SAP için çeşitli yöntemler), gerekli alanlar ve API kuralları vardır. Hedef platformunuzun belgelerine başvurun, ancak çıkarılan fatura verilerini API yüklerine dönüştürme deseni tutarlıdır.
Yüzlerce Faturayı Toplu İşleme Nasıl Yapılır
Yüksek hacimli fatura işleme, eşzamanlılık ve kaynak yönetimine özen göstermeyi gerektirir. Kontrollü eşzamanlılıkla paralel işlemeyi 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 batchpublic class BatchResult{ public stringFilePath { get; set; } public boolSuccess { get; set; } public stringInvoiceNumber { get; set; } public stringError { get; set; }}// High-volume invoice processor with controlled parallelism// Prevents overwhelming APIs while maximizing throughputpublic class BatchInvoiceProcessor{ private readonly SmartInvoiceProcessor _invoiceProcessor; private readonly AccountingSystemIntegration _accountingIntegration; private readonly int _maxConcurrency; publicBatchInvoiceProcessor(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 = awaitProcessSingleInvoice(path); results.Add(result); } finally { // Release slot for next invoice semaphore.Release(); } }); // Wait for all invoices to complete awaitTask.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
};
}
}
}
ImportsSystemImportsSystem.Collections.ConcurrentImportsSystem.Collections.GenericImportsSystem.LinqImportsSystem.ThreadingImportsSystem.Threading.Tasks' Tracks the result of processing a single invoice in a batchPublic Class BatchResult Public Property FilePathAsString Public Property SuccessAsBoolean Public Property InvoiceNumberAsString Public Property ErrorAsStringEnd Class' High-volume invoice processor with controlled parallelism' Prevents overwhelming APIs while maximizing throughputPublic Class BatchInvoiceProcessor PrivateReadOnly _invoiceProcessor AsSmartInvoiceProcessor PrivateReadOnly _accountingIntegration AsAccountingSystemIntegration PrivateReadOnly _maxConcurrency AsInteger Public Sub New(aiApiKey AsString, accountingApiKey AsString, accountingUrl AsString, Optional maxConcurrency AsInteger = 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 PublicAsync Function ProcessInvoiceBatch(invoicePaths AsList(OfString)) AsTask(OfList(OfBatchResult)) ' Thread-safe collection for gathering results from parallel tasks Dim results = New ConcurrentBag(OfBatchResult)() ' 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 availableAwait semaphore.WaitAsync()Try Dim result = AwaitProcessSingleInvoice(path) results.Add(result)Finally ' Release slot for next invoice semaphore.Release()EndTry End Function) ' Wait for all invoices to completeAwaitTask.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 PrivateAsync Function ProcessSingleInvoice(pdfPath AsString) AsTask(OfBatchResult)TryConsole.WriteLine($"Processing: {pdfPath}") Dim invoiceData = Await _invoiceProcessor.ProcessAnyInvoice(pdfPath)Await _accountingIntegration.SendToQuickBooks(invoiceData)Console.WriteLine($"✓ Completed: {invoiceData.InvoiceNumber}") Return New BatchResultWith { .FilePath = pdfPath, .Success = True, .InvoiceNumber = invoiceData.InvoiceNumber }Catch ex AsExceptionConsole.WriteLine($"✗ Failed: {pdfPath}") Return New BatchResultWith { .FilePath = pdfPath, .Success = False, .Error = ex.Message }EndTry End FunctionEnd Class
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
SemaphoreSlim, harici API'ları aşırı yüklememenizi veya sistem kaynaklarını tüketmemenizi sağlar. _maxConcurrency, API hız limitlerinize ve sunucu kapasitenize göre ayarlayın. ConcurrentBag, paralel işlemlerden güvenle sonuç toplar.
Sonraki Adımlar
Fatura otomasyonu, manuel çalışmayı azaltma, hataları en aza indirme ve iş süreçlerini hızlandırma açısından önemli bir fırsat sunar. Bu kılavuz, profesyonel faturalar oluşturmaktan HTML şablonlarından, ZUGFeRD ve Factur-X e-faturalama standartlarına uygun hale getirmeye, verileri çıkarmaktan alınan faturalar, desen eşleştirme ve AI destekli çıkartma kullanarak ve ölçeklenebilir otomasyon hatları oluşturmaya kadar eksiksiz bir yaşam döngüsü sunar.
IronPDF, bu yeteneklerin temeli olarak hizmet verir, sağlam HTML'den PDF'e dönüştürme, güvenilir metin çıkarma ve gereksinim duyulan ekleme özelliklerini sağlayarak PDF/A-3 e-faturalama uygunluğu sağlar. Chrome tabanlı rendering motoru, faturalarınızın tam olarak tasarlandığı gibi görünmesini sağlarken, çıkarım yöntemleri PDF metin kodlamasının karmaşıklığını otomatik olarak ele alır.
Burada görülen modeller başlangıç noktalarıdır. Gerçek uygulamalar, belirli fatura formatlarınız, muhasebe sistemleriniz ve iş kurallarınız için uyarlama gerektirecektir. Yüksek hacimli senaryolar için, toplu işlem eğitimi, kontrollü eşzamanlılık ve hata kurtarma ile paralel uygulamayı ele alır.
İşe başlamaya hazır mısınız? IronPDF'i İndirin ve ücretsiz bir deneme ile deneyin. Kütüphane, fatura oluşturma, veri çıkarma, ve PDF rapor özelliklerini değerlendirebilmeniz için ücretsiz bir geliştirme lisansı içerir, üretim lisansı almadan önce. Eğer fatura otomasyonu veya muhasebe sistemi entegrasyonu hakkında sorularınız varsa, mühendislik destek ekibimize ulaşın.
Sıkça Sorulan Sorular
IronPDF, C# fatura işleme süreçlerinde ne için kullanılır?
IronPDF, profesyonel PDF faturaları oluşturmak, yapılandırılmış verileri çıkarmak ve ZUGFeRD ve Factur-X gibi standartlara uyumu sağlarken fatura iş akışlarını otomatikleştirmek için C# fatura işleme sürecinde kullanılır.
IronPDF kullanarak C# ile nasıl PDF fatura oluşturabilirim?
C# dilinde IronPDF kullanarak API'sini kullanabilir ve PDF belgelerini programlı olarak oluşturup özelleştirerek bir PDF fatura üretebilirsiniz. Bu, bir faturayı oluşturan metin, tablo ve resimler gibi öğelerin eklenmesini 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-fatura standartlarıdır. IronPDF, bu standartları destekleyerek bu spesifikasyonlara uygun PDF faturaları oluşturmanıza olanak tanır.
IronPDF, ödenecek hesap süreçlerinin otomasyonunda nasıl yardımcı olabilir?
IronPDF, faturalar üzerinden yapılandırılmış verileri çıkararak ve otomasyon hatları ile entegre ederek hesap ödenebilir süreçlerini otomatikleştirebilir, manuel veri girişini azaltır ve verimliliği artırır.
IronPDF mevcut PDF faturalarından veri çıkarabilir mi?
Evet, IronPDF mevcut PDF faturalarından yapılandırılmış verileri çıkarabilir, bu da fatura bilgilerini otomatik olarak işlemenizi ve analiz etmenizi kolaylaştırır.
C# ile fatura işlemede IronPDF kullanmanın faydaları nelerdir?
C# içinde fatura işleme için IronPDF kullanmanın faydaları arasında kolaylaştırılmış fatura oluşturma, uluslararası fatura standartlarına uyum, verimli veri çıkarımı ve geliştirilmiş otomasyon yetenekleri yer alır.
IronPDF ile bir PDF faturanın görünümünü özelleştirmek mümkün mü?
Evet, IronPDF, marka gereksinimlerini karşılamak için logolar, metin biçimlendirme ve düzen ayarlamaları gibi çeşitli tasarım unsurları ekleyerek bir PDF faturanın görünümünü özelleştirmenize olanak tanır.
IronPDF kullanarak fatura işleme otomasyonunda tipik adımlar nelerdir?
Fatura işleme sürecini otomatikleştirmek için IronPDF kullanarak, genellikle faturayı oluşturarak, gerekli verileri çıkarır ve iş akışlarını düzene sokmak için diğer sistemler veya otomasyon araçları ile entegre edersiniz.
IronPDF, farklı fatura formatlarını nasıl işler?
IronPDF, PDF belgeleri oluşturmak, düzenlemek ve okumak için araçlar sağlayarak, çeşitli fatura formatlarını işleyebilir ve yaygın e-fatura standartlarıyla uyumluluğu sağlar.
What is a recommended technology stack for invoice processing in .NET?
A recommended technology stack for invoice processing in .NET includes IronPDF for PDF manipulation, IronQR for embedding QR codes, and integration with AI models for advanced data parsing.
Curtis Chau, Bilgisayar Bilimleri alanında Lisans Derecesine (Carleton Üniversitesi) sahip ve Node.js, TypeScript, JavaScript ve React konularında uzmanlaşmış ön uç geliştirmeyle ilgileniyor. Sezgisel ve estetik açıdan hoş kullanıcı arayüzleri oluşturma tutkunu, Curtis modern çerçevelerle çalışmayı ve iyi yapılandırılmış, görsel olarak çekici kılavuzlar oluşturmayı seviyor.