IronPDF Kullanarak .NET İçinde PDF Dosyaları Nasıl Üretilir (C# Eğitimi)
Manuel Tekrarlayan Raporlarla İlgili Sorun
Her organizasyonda aynı Pazartesi sabahı ritüelinin bir versiyonu vardır: bir analist raporlama veritabanını açar, geçen hafta çalıştırdığı sorguları çalıştırır, sayıları bir Excel şablonuna kopyalar, tabloları biçimlendirir, PDF formatına aktarır ve dosyanın gönderildiğinden emin olarak liderlik dağıtım listesine e-posta gönderir, hiçbir şeyin bozulmaması ve dosyanın 09:00 standup toplantısından önce gönderilmesi umuduyla. Çalıştığı zaman, birinin sabahının görünmez bir vergisidir. Çalışmadığı zaman, örneğin bir sekmede bırakılan bayat veriler, özet satırında bir formül hatası, 07:00 yerine 10:30'da gelen bir rapor, tam da yanlış izleyici kitlesine görünür hale gelir.
Mevcut BI araçları planlanmış teslimat sunar, ancak genellikle bir kontrol panelinin ekran görüntüleri veya giriş gerektiren gömülü bağlantılar olarak gelir. Yola çıkarken bir Satış VP'si, telefonunda bir BI aracına kimlik doğrulamak istemez, tabletinde okuyabileceği, bir müşteriye iletebileceği veya kurul toplantısından önce yazdırabileceği bir PDF raporu ister. Planlanmış SSRS abonelikleri bağımsız PDF belgeleri üretir, ancak çıktılar 2010'dan kalmış kurumsal bir yazılım gibi görünür ve şablonu güncellemek, çoğu güncel .NET ekibinin artık uzman olmadığı bir rapor tasarımcısında gezinmeyi gerektirir.
Sıfırdan özel bir yapı hattı oluşturmak doğru mimari çözümdür, ancak bu, bir zamanlayıcı, sorgu katmanı, şablon motoru ve e-posta gönderici gibi potansiyel her bir hata noktasıyla başa çıkmak anlamına gelir, bu da CFO'nun haftalık Gelir&Gider özetinin gelmemesi durumunda sabah 6'da birini uyarır.
Çözüm: IronPDF ile Planlanan Bir Yapı Hattı Olarak İşleme Adımı
IronPDF, veritabanına karşı SQL sorgularını çalıştıran, sonuçları bir HTML ve CSS şablonuna eşleyen ve tamamlanan PDF'yi bir cron programında dağıtım listesine e-posta ile gönderen planlı bir .NET arka plan işinde bir işleme motoru olarak görev yapan bir .NET PDF kütüphanesidir, manuel adımlar yoktur, analist gerekmez.
Hangfire, Quartz.NET veya bir BackgroundService işi tetikler. ADO.NET veya Dapper numaraları çeker. HTML şablonu bunları markalı bir rapora dönüştürür. ChromePdfRenderer PDF'yi üretir. E-posta, hiç kimse dizüstü bilgisayarını açmadan önce gönderilir. Hiçbir BI aracı ekran görüntüsü, SSRS rapor tanımı veya rapor başına API ücreti yoktur. İşleme mevcut .NET uygulaması içinde çalışır, bir NuGet paketi, harici işlem yok.
Pratikte Nasıl Çalışır?
1. Cron Zamanlaması İşi Tetikler
Her raporun kendi zamanlaması vardır: satış kanalının anlık görüntüsü her gün saat 06:30'da, Gelir&Gider özeti Pazartesi saat 06:00'da, aylık yönetici kontrol paneli ise 1. günde çalışır. İş, uygulama başlangıcında Hangfire veya Quartz.NET'e kendi cron ifadesi ile kaydedilir veya daha basit dağıtımlar için bir zamanlanmış BackgroundService olarak uygulanır.
İş çalıştığında, raporlama veritabanına bir bağlantı açar ve dönem, gelir ve gider rakamları, KPI ölçümleri, hata aşaması hesapları, dönüşüm oranları veya rapor türüne bağlı olarak yerine getirme istatistikleri için ilgili SQL sorgularını veya saklı prosedürleri çalıştırır.
2. Sorgu Sonuçları HTML Şablonunu Besler
Sorgu sonuçları bir modele veya sözlüğe eşlenir ve HTML şablonuna enjekte edilir. Şablon, raporun görünümü hakkında her şeyi tanımlar: şirket logosuyla markalı başlık, bir dönem etiketi ("27 Mart 2025 Haftası"), üstteki özet metrik kartlar, alternatif sıra renklerine sahip bir veya daha fazla veri tablosu ve oluşturma zaman damgası ve gizlilik bildirimi içeren bir alt bilgi. Bu IronPDF örnek kodu, tam olarak bunu gösteren PDF dosyaları oluşturacaktır.
using Dapper;
using IronPdf;
using System.Data.SqlClient;
var reportData = new List<dynamic>();
using (var conn = new SqlConnection(_connectionString))
{
reportData = (await conn.QueryAsync(@"
SELECT Region, SUM(Revenue) AS Revenue, COUNT(OrderId) AS Orders
FROM SalesOrders
WHERE OrderDate >= @Start AND OrderDate < @End
GROUP BY Region ORDER BY Revenue DESC",
new { Start = weekStart, End = weekStart.AddDays(7) })).ToList();
}
var tableRows = string.Concat(reportData.Select(r =>
$"<tr><td>{r.Region}</td><td>{r.Revenue:C}</td><td>{r.Orders}</td></tr>"));
string html = (await File.ReadAllTextAsync("Templates/sales-weekly.html"))
.Replace("{{Period}}", $"Week of {weekStart:MMMM d, yyyy}")
.Replace("{{TotalRevenue}}", reportData.Sum(r => (decimal)r.Revenue).ToString("C"))
.Replace("{{TableRows}}", tableRows);
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Letter;
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
PdfDocument report = renderer.RenderHtmlAsPdf(html);
using Dapper;
using IronPdf;
using System.Data.SqlClient;
var reportData = new List<dynamic>();
using (var conn = new SqlConnection(_connectionString))
{
reportData = (await conn.QueryAsync(@"
SELECT Region, SUM(Revenue) AS Revenue, COUNT(OrderId) AS Orders
FROM SalesOrders
WHERE OrderDate >= @Start AND OrderDate < @End
GROUP BY Region ORDER BY Revenue DESC",
new { Start = weekStart, End = weekStart.AddDays(7) })).ToList();
}
var tableRows = string.Concat(reportData.Select(r =>
$"<tr><td>{r.Region}</td><td>{r.Revenue:C}</td><td>{r.Orders}</td></tr>"));
string html = (await File.ReadAllTextAsync("Templates/sales-weekly.html"))
.Replace("{{Period}}", $"Week of {weekStart:MMMM d, yyyy}")
.Replace("{{TotalRevenue}}", reportData.Sum(r => (decimal)r.Revenue).ToString("C"))
.Replace("{{TableRows}}", tableRows);
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Letter;
renderer.RenderingOptions.MarginTop = 20;
renderer.RenderingOptions.MarginBottom = 20;
PdfDocument report = renderer.RenderHtmlAsPdf(html);
Imports Dapper
Imports IronPdf
Imports System.Data.SqlClient
Dim reportData As New List(Of Object)()
Using conn As New SqlConnection(_connectionString)
reportData = (Await conn.QueryAsync("
SELECT Region, SUM(Revenue) AS Revenue, COUNT(OrderId) AS Orders
FROM SalesOrders
WHERE OrderDate >= @Start AND OrderDate < @End
GROUP BY Region ORDER BY Revenue DESC",
New With {.Start = weekStart, .End = weekStart.AddDays(7)})).ToList()
End Using
Dim tableRows = String.Concat(reportData.Select(Function(r)
$"<tr><td>{r.Region}</td><td>{r.Revenue:C}</td><td>{r.Orders}</td></tr>"))
Dim html As String = (Await File.ReadAllTextAsync("Templates/sales-weekly.html")) _
.Replace("{{Period}}", $"Week of {weekStart:MMMM d, yyyy}") _
.Replace("{{TotalRevenue}}", reportData.Sum(Function(r) CType(r.Revenue, Decimal)).ToString("C")) _
.Replace("{{TableRows}}", tableRows)
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.PaperSize = IronPdf.Rendering.PdfPaperSize.Letter
renderer.RenderingOptions.MarginTop = 20
renderer.RenderingOptions.MarginBottom = 20
Dim report As PdfDocument = renderer.RenderHtmlAsPdf(html)
Üretilen PDF Dosyası

3. PDF Belgesi E-postayla Gönderildi ve Arşivlendi
using System.Net.Mail;
using System.IO;
var recipients = await _configService.GetDistributionListAsync("sales-weekly");
string subject = $"Weekly Sales Report — {weekStart:MMM d, yyyy}";
using var stream = new MemoryStream(report.BinaryData);
using var attachment = new Attachment(stream, $"Sales-Report-{weekStart:yyyyMMdd}.pdf", "application/pdf");
var message = new MailMessage
{
From = new MailAddress("reports@yourcompany.com"),
Subject = subject,
Body = $"Please find the weekly sales report for the week of {weekStart:MMMM d, yyyy} attached."
};
foreach (var recipient in recipients)
message.To.Add(recipient);
message.Attachments.Add(attachment);
using var smtp = new SmtpClient("smtp.yourprovider.com");
await smtp.SendMailAsync(message);
// Archive to blob storage for historical access
string archivePath = $"reports/sales-weekly/{weekStart:yyyy/MM/dd}.pdf";
report.SaveAs(archivePath);
using System.Net.Mail;
using System.IO;
var recipients = await _configService.GetDistributionListAsync("sales-weekly");
string subject = $"Weekly Sales Report — {weekStart:MMM d, yyyy}";
using var stream = new MemoryStream(report.BinaryData);
using var attachment = new Attachment(stream, $"Sales-Report-{weekStart:yyyyMMdd}.pdf", "application/pdf");
var message = new MailMessage
{
From = new MailAddress("reports@yourcompany.com"),
Subject = subject,
Body = $"Please find the weekly sales report for the week of {weekStart:MMMM d, yyyy} attached."
};
foreach (var recipient in recipients)
message.To.Add(recipient);
message.Attachments.Add(attachment);
using var smtp = new SmtpClient("smtp.yourprovider.com");
await smtp.SendMailAsync(message);
// Archive to blob storage for historical access
string archivePath = $"reports/sales-weekly/{weekStart:yyyy/MM/dd}.pdf";
report.SaveAs(archivePath);
Imports System.Net.Mail
Imports System.IO
Dim recipients = Await _configService.GetDistributionListAsync("sales-weekly")
Dim subject As String = $"Weekly Sales Report — {weekStart:MMM d, yyyy}"
Using stream As New MemoryStream(report.BinaryData)
Using attachment As New Attachment(stream, $"Sales-Report-{weekStart:yyyyMMdd}.pdf", "application/pdf")
Dim message As New MailMessage With {
.From = New MailAddress("reports@yourcompany.com"),
.Subject = subject,
.Body = $"Please find the weekly sales report for the week of {weekStart:MMMM d, yyyy} attached."
}
For Each recipient In recipients
message.To.Add(recipient)
Next
message.Attachments.Add(attachment)
Using smtp As New SmtpClient("smtp.yourprovider.com")
Await smtp.SendMailAsync(message)
End Using
End Using
End Using
' Archive to blob storage for historical access
Dim archivePath As String = $"reports/sales-weekly/{weekStart:yyyy/MM/dd}.pdf"
report.SaveAs(archivePath)
Ekte PDF Olan Örnek E-posta
Dağıtım listeleri sabit kodlanmış yerine yapılandırma tablosundan çekilmiştir, bu nedenle haftalık satış raporuna yeni bir alıcı eklemek kod değişikliği veya yeniden dağıtım gerektirmez. Her arşivlenmiş PDF, geçmiş raporların paylaşılan bir sürücüden veya dahili bir portaldan erişilebilir bir kütüphane oluşturmasını sağlayarak rapor adı ve tarihe göre anahtarlanır.
İş, yapılandırılmış loglamaya sorgu süresi, işleme zamanı, e-posta gönderme sonucu ve varsa hatalar gibi çalışma durumunu kaydeder. İşin tamamlanmaması durumunda bir uyarı tetiklenir, böylece bir sorunun ilk belirtisi, yöneticilere neden raporlarının ulaşmadığını sormak değildir.
Gerçek Dünya Faydaları
Sıfır manuel çaba. Raporlar program dahilinde kendilerini üretir ve teslim eder. Pazartesi sabahı sorguları çalıştıran bir analist yok, tablo biçimlendiren kimse yok, göndermeyi hatırlayan kimse yok. Süreç çalıştığında görünmezdir ve çalışmadığında uyarılabilir.
Zamanında. Rapor çalışma günü başlamadan önce gelen kutularına ulaşır. Ofise giderken e-posta kontrol eden bir CFO'nun, herhangi bir toplantıdan önce kendilerine gereken Gelir&Gider rakamlarına erişimi olur, bir analistin kahvesini bitirmesinden sonra değil.
Çevrimdışı okunabilirlik. Yöneticilerin uçakta okuyabilmesi için bağımsız bir PDF, bir yönetim kurulu toplantısı için yazdırılabilir veya alıcının herhangi bir sisteme giriş yapmasını gerektirmeden iletilebilir. Hiçbir kontrol paneli URL'si, kimlik doğrulama duvarı yok, "bu bağlantı sadece kurumsal ağda çalışır" ifadesi yok.
Marka tutarlılığı. Yapı hattı tarafından üretilen her rapor, aynı onaylı HTML ve CSS şablonunu, tüm haftalık, günlük ve aylık raporlar boyunca aynı logo yerleşimini, tipografi, tablo stilini ve altbilgi dilini kullanır.
Tarihi arşiv. Her üretilen PDF tarihine göre yapılandırılmış bir yolla depolanır. Altı aylık haftalık satış raporları, trend incelemesi veya denetim isteği için bir klasör taraması kadar yakındır; hiçbir BI aracı sorgusuna gerek yoktur.
Rapor başına maliyetler yoktur. İşleme, mevcut .NET uygulaması içinde işlem içi çalışır. Zamanlanmış teslimat için gerekli BI aracı premium koltuğu yoktur ve rapor hacmi veya dağıtım listesi boyutu ile ölçeklenen bir rapor API ölçümü yoktur.
Kapanış
Çalışma günü başlamadan önce güvenilir bir şekilde varış yapan tekrarlayan bir rapor, kararların nasıl alındığını etkileyen küçük bir operasyonel ayrıntıdır. Sabah standup toplantısından önce rakamlarını alan liderlik, bir analistin tabloyu biçimlendirmesi tamamlanana kadar bekleyen liderlikten farklı bir toplantı yürütür.
Oraya ulaşmak için olan yapı hattı — zamanlayıcı, sorgu, şablon, işleme, e-posta — tek bir .NET arka plan işine rahatça sığar. IronPDF, C#'ta PDF oluşturmanın tüm yaşam döngüsünü ironpdf.com'da, HTML şablonlarını işlemekten kaydetmeye, yayına ve belgeleri manipüle etmeye kadar yönetir. Manuel raporlama sürecini kendi kendine çalışan bir süreçle değiştirmeye hazırsanız, ücretsiz 30 günlük deneme sürenizi başlatın, planlanan bir yapı hattı oluşturmak, onu veritabanınıza bağlamak ve doğru PDF'lerin doğru kutulara zamanında ulaştığını onaylamak için yeterli zamandır.




