QuestPDF ile Dinamik Fatura PDF’leri Oluşturma (Creating Dynamic Invoice PDFs with QuestPDF)
Günümüzde yazılım projelerinin pek çoğunda PDF raporlaması yaygın bir ihtiyaç haline gelmiştir. Özellikle e-ticaret, muhasebe veya…
QuestPDF ile Dinamik Fatura PDF’leri Oluşturma (Creating Dynamic Invoice PDFs with QuestPDF)

Günümüzde yazılım projelerinin pek çoğunda PDF raporlaması yaygın bir ihtiyaç haline gelmiştir. Özellikle e-ticaret, muhasebe veya faturalandırma sistemlerinde PDF üretimi oldukça önemlidir. Bu makalemde .NET Core 8.0 ile birlikte kullanılan QuestPDF kütüphanesi sayesinde dinamik veri kaynaklarından nasıl PDF oluşturabileceğinizi öğreneceksiniz. Ayrıca PDF üretme sürecini nasıl dinamik hale getirebiliriz bundan bahsedeceğim.
QuestPDF Nedir?
QuestPDF, .NET platformu üzerinde çalışan, açık kaynaklı ve güçlü bir PDF oluşturma kütüphanesidir. PDF dokümanlarını programatik olarak oluşturmanıza olanak sağlar. Document sınıfı ile dokümanın yapısını tanımlayıp, düzenli bir şekilde PDF’leri oluşturarak çıktısı alabiliriz. Bu yazıda, QuestPDF ile bir fatura şablonunu nasıl dinamik hale getireceğinizi adım adım anlatacağım.
İlk olarak QuestPDF’i projenize eklemek için NuGet paketi üzerinden aşağıdaki komutu kullanarak projemize ekleyelim.
Install-Package QuestPDF
QuestPDF, lisanslı bir kütüphanedir ancak topluluk sürümünü (Community License) kullanarak ücretsiz bir şekilde faturalandırma gibi işlemler için PDF dokümanları oluşturabilirsiniz.
Ben bu senaryo için bir fatura yapısını ele aldım. Faturada olması gereken 2 grup data vardır. Master ve detay veriler. Bu verileri saklamak için DataTable kullandım. Bu verileri üretmek içinde bir helper sınıfı kullandım.
public class Helper
{
public static async Task<(DataTable masterTable, DataTable detayTable)> FaturaVerisiOlusturAsync()
{
return await Task.Run(() =>
{
DataTable dtMaster = new DataTable();
dtMaster.Columns.Add("FaturaNo", typeof(string));
dtMaster.Columns.Add("FaturaTarihi", typeof(DateTime));
dtMaster.Columns.Add("CariAdi", typeof(string));
dtMaster.Columns.Add("ToplamTutar", typeof(decimal));
DataTable dtDetay = new DataTable();
dtDetay.Columns.Add("FaturaNo", typeof(string));
dtDetay.Columns.Add("UrunAdi", typeof(string));
dtDetay.Columns.Add("Miktar", typeof(int));
dtDetay.Columns.Add("BirimFiyat", typeof(decimal));
dtDetay.Columns.Add("Tutar", typeof(decimal));
string faturaNo = "FTR20240001";
DataRow masterRow = dtMaster.NewRow();
masterRow["FaturaNo"] = faturaNo;
masterRow["FaturaTarihi"] = DateTime.Now;
masterRow["CariAdi"] = "ABC Ticaret Ltd.";
masterRow["ToplamTutar"] = 0;
dtMaster.Rows.Add(masterRow);
decimal toplamTutar = 0;
for (int i = 1; i <= 30; i++)
{
DataRow detayRow = dtDetay.NewRow();
detayRow["FaturaNo"] = faturaNo;
detayRow["UrunAdi"] = "Ürün " + i;
detayRow["Miktar"] = i * 2;
detayRow["BirimFiyat"] = 10 + i;
detayRow["Tutar"] = (int)detayRow["Miktar"] * (decimal)detayRow["BirimFiyat"];
toplamTutar += (decimal)detayRow["Tutar"];
dtDetay.Rows.Add(detayRow);
}
dtMaster.Rows[0]["ToplamTutar"] = toplamTutar;
return (dtMaster, dtDetay);
});
}
}
Şimdi bu verileri alarak QuestPDF ile bir PDF dosyası oluşturalım. Master verileri (fatura no, tarih, cari adı ve toplam tutar) ve detay verileri (ürün adı, miktar, birim fiyat, tutar) olacak şekilde tasarlayacağız.
var (master, detail) = await Helper.FaturaVerisiOlusturAsync();
QuestPDF.Settings.License = LicenseType.Community;
var document = Document.Create(container =>
{
container.Page(page =>
{
page.Size(PageSizes.A4);
page.Margin(10);
page.Header().Element(c => GeneratePdf.ComposeHeader(c, request.UpHeader, request.SubHeader));
page.Content().Column(column =>
{
column.Item().PaddingVertical(2);
column.Item().Text(text =>
{
text.Span("Fatura No: ").Bold().FontSize(_fontSize);
text.Span(master.Rows[0]["FaturaNo"].ToString()).FontSize(_fontSize);
});
column.Item().Text(text =>
{
text.Span("Fatura Tarihi: ").Bold().FontSize(_fontSize);
text.Span(Convert.ToDateTime(master.Rows[0]["FaturaTarihi"]).ToString("dd.MM.yyyy")).FontSize(12);
});
column.Item().Text(text =>
{
text.Span("Cari Adı: ").Bold().FontSize(_fontSize);
text.Span(master.Rows[0]["CariAdi"].ToString()).FontSize(_fontSize);
});
column.Item().Text(text =>
{
text.Span("Toplam Tutar: ").Bold().FontSize(_fontSize);
text.Span(master.Rows[0]["ToplamTutar"].ToString()).FontSize(_fontSize);
});
column.Item().PaddingVertical(5);
column.Item().Element(c => GeneratePdf.ComposeDataTable(c, detail));
});
page.Footer().Element(GeneratePdf.ComposeFooter);
});
});
var pdfBytes = document.GeneratePdf();
response.Cevap = Convert.ToBase64String(pdfBytes);
Yukarıdaki örnekte ilk göze çarpan master veriler, Detay veri, Header ve Footer gibi kısımları oluşturmak için yeni helper içinde GeneratePdf metodlarını kullandım. Böylelikle kod tekrarından kurtulmuş oldum.
public abstract class GeneratePdf
{
public static void ComposeHeader(IContainer container, string? upHeader, string? subHeader)
{
container.Row(row =>
{
row.ConstantItem(66).Image("wwwroot/images/logo-300-300.png");
row.RelativeItem().Column(column =>
{
column.Item().AlignCenter().Text(upHeader)
.Style(TextStyle.Default.FontSize(20).SemiBold().FontColor(Colors.Blue.Medium));
column.Item().AlignCenter().Text(DateTime.Now.Year.ToString()).FontSize(12).Bold();
column.Item().AlignCenter().Text(subHeader).FontSize(12);
});
row.ConstantItem(66).Image("wwwroot/images/logo-300-300.jpg");
});
}
public static void ComposeFooter(IContainer container)
{
container.Container()
.Background(Colors.Grey.Lighten3)
.Padding(3)
.AlignCenter()
.Text(x =>
{
x.Span("Sayfa ").FontSize(10);
x.CurrentPageNumber().FontSize(10);
x.Span(" / ").FontSize(10);
x.TotalPages().FontSize(10);
});
}
public static void ComposeDataTable(IContainer container, DataTable dataTable)
{
const float borderLine = (float)0.10;
const float fontSize = 12;
container
.PaddingLeft(0)
.PaddingRight(0)
.Container()
.Background(Colors.Grey.Lighten3)
.Table(table =>
{
table.ColumnsDefinition(columns =>
{
for (var i = 0; i < dataTable.Columns.Count; i++)
{
columns.RelativeColumn();
}
});
table.Header(header =>
{
foreach (DataColumn column in dataTable.Columns)
{
header.Cell()
.Border(1)
.PaddingLeft(2)
.AlignCenter()
.AlignMiddle()
.Text(column.ColumnName)
.Bold()
.FontSize(fontSize);
}
});
foreach (DataRow row in dataTable.Rows)
{
foreach (DataColumn column in dataTable.Columns)
{
var cellValue = row[column];
var cellText = cellValue switch
{
DateTime dateTimeValue => dateTimeValue.ToString("dd.MM.yyyy HH:mm"),
int or long or decimal => cellValue.ToString(),
_ => cellValue.ToString()
};
table.Cell()
.BorderBottom(borderLine)
.BorderVertical(1)
.PaddingLeft(2)
.AlignCenter()
.Text(cellText)
.FontSize(fontSize);
}
}
for (var i = 0; i < dataTable.Columns.Count; i++)
{
table.Cell().BorderBottom(1);
}
});
}
}

Örnek Fatura Çıktısı
Bu makalemde .NET Core 8.0 üzerinde QuestPDF kütüphanesini kullanarak dinamik veri kaynaklarından PDF oluşturmayı anlatmaya çalıştım. Herhangi bir PDF oluşturma işlemlerini nasıl basit ve esnek bir şekilde gerçekleştirebileceğinizi inceledik.
Keyifli okumalar 😊 Makelemde bahsettiğim kodlara https://github.com/ertugrulakdag/QuestExampleApi adresinden ulaşabilirsiniz.
메타데이터
- post_id
- 67b34db82f32
- slug
- questpdf-ile-dinamik-fatura-pdfleri-oluşturma-creating-dynamic-invoice-pdfs-with-questpdf-67b34db82f32
- url
- https://medium.com/@ertugrulakdag/questpdf-ile-dinamik-fatura-pdfleri-olu%C5%9Fturma-creating-dynamic-invoice-pdfs-with-questpdf-67b34db82f32
- canonical_url
- https://medium.com/@ertugrulakdag/questpdf-ile-dinamik-fatura-pdfleri-olu%C5%9Fturma-creating-dynamic-invoice-pdfs-with-questpdf-67b34db82f32
- author_url
- https://medium.com/@ertugrulakdag
- status
- ok
- fetched_at
- 2026-07-22 10:25:21