C# İle iTextSharp dll’ini Kullanarak PDF Dökümanı Oluşturma

Kimi zaman yazdığımız uygulamalarda raporlara ihtiyaç duyuyoruz. Bu raporları oluşturmak için çeşitli araçlar kullanıyoruz. Basit anlamda bu raporları oluşturup PDF olarak görüntülemek amacıyla iTextsharp adında bir dll’den bahsetmek istiyorum sizlere. Bu dll’i http://www.divshare.com/download/11802445-e3c adresinden indirebilirsiniz.

Yapacağımız uygulamada veritabanı olarak AdventureWorks veritabanını kullandım. http://msftdbprodsamples.codeplex.com/ adresinden Microsoft Sql Server için hazırlanmış örnek veritabanlarını indirip bilgisayarınıza kurabilirsiniz.

Uygulama için gerekli olan veritabanı ve dll’i hazırladıktan sonra artık işin kod kısmına geçebiliriz.

NOT: VS 2010 Express sürümünü kullanarak bir WPF uygulaması açtım.

Uygulamamıza öncelikle Solution Explorer->References->Add Reference diyerek iTextsharp dll’ini ekliyoruz. Daha sonra veritabanına erişim için Add->NewItem->Ado.Net Entity Data Model diyerek EDM’yi ekliyoruz. EDM’nin adını verdikten sonra çıkan Entity Data Model Wizard ekranında Generate From Database’i seçip ilerliyoruz. Bir sonraki ekranda New Connection deyip açılan ekranda Data Source olarak Microsoft SQL Server Database File; Data Provider olarak da .Net Framework Data Provider for SQL Server’ı seçiyoruz. Continue dediğimizde çıkan ekranda browse diyerek AdventureWorks veritabanını seçiyoruz. Dilerseniz Test Connection diyerek bağlantınızın çalışıp çalışmadığını kontrol edebilirsiniz. Bu işlem tamamlandıktan sonra tekrar bağlantı oluşturduğumuz ekrana dönüyoruz ve ilerliyoruz.

Eğer AdventureWorks veritabanı projeyi oluşturduğunuz klasör içinde değilse karşınıza aşağıdaki gibi bir ekran çıkacak ve veritabanının proje klasörüne kopyalayıp bağlantı cümlesini yeniden yapılandırmak isteyip istemediğinizi soracak. Burada seçim size kalmış dilerseniz veritabanını proje klasörüne kopyalayabilirsiniz yalnız bu durumda AdventureWorks MDF dosyasının 175 mb. civarı bir boyutu olduğunu unutmayın 🙂

Bu işlemden sonra karşınıza çıkan ekranda Tables sekmesininden Product ve ProductSubcategory tablolarını seçip EDM’ye dahil ediyoruz ve işlemi tamamlıyoruz.

Şimdi sıra geldi raporumuzu oluşturacak metodumuzu yazmaya. Kod kalabalığını ortadan kaldırmak amacıyla metodu 3 ayrı alt metoda bölmeyi tercih ettim :

  • Tablomuzun başlık kısmını oluşturacak olan GetHeaderTable metodu
  • Tablomuzun kolon başlıklarını oluşturacak olan GetColumnTable metodu
  • Tablomuzun değerlerini getirecek olan GetValueTable metodu

Açtığımız Window’un .cs uzantılı kod kısmına geçiyoruz. Öncelikle gerekli olan global değişkenleri tanımlıyoruz.

BaseFont _bFont;

Phrase _ emptyString;

int _normalFontSize = 7;

AdventureWorks_DataEntities _dt = new AdventureWorks_DataEntities();

Daha sonra Constructor’da gerekli nesneleri örnekliyoruz.

_bFont = BaseFont.CreateFont(@”C:\WINDOWS\Fonts\tahoma.ttf”, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); //BaseFont’u örneklerken bilgisayarımızda bulunan herhangi bir fontu seçiyoruz.

_emptyString = new Phrase(“x”, new Font(_bFont, _normalFontSize, Font.NORMAL, iTextSharp.text.Color.WHITE)); // İçinde veri olmayan bir hücre oluşturmamız gerektiğinde hücrenin değerine bu şekilde bir metin vermemiz gerekiyor. Aksi taktirde boş hücre yok sayılıp bir sonraki hücre onun yerine ekleniyor. Bu da tablomuzu oluştururken hata oluşmasına dolayısıyla tablonun oluşturulamamasına ya da yanlış bir tablo oluşmasına neden oluyor.

Burada BaseFont tipinden bir nesne tanımlayıp örneklememizin ve bundan sonra oluşturacak olduğumuz Font tipinden nesneleri bu base font’tan kalıtacak olmamızın sebebi Türkçe karakter sorununun önüne geçmek.

public void GetHeaderTable(Document document)

{

#region Fields

iTextSharp.text.Color _headerColor = new iTextSharp.text.Color(000, 019, 127);

Font _headerFont = new Font(_bFont, 14, Font.BOLD, _headerColor);

#endregion

#region Başlık

PdfPTable header = new PdfPTable(new float[] { 500 });

PdfPCell cell = new PdfPCell(new Phrase(string.Format(“ÜRÜN LİSTESİ”), _headerFont)); // Phrase nesnesini oluşturarak hücreye yazılacak metni oluşturuyoruz.

cell.HorizontalAlignment = Element.ALIGN_CENTER;

cell.Border = iTextSharp.text.Rectangle.NO_BORDER;

header.AddCell(cell);

#region Boşluk

cell = new PdfPCell(_bosluk);

cell.Border = iTextSharp.text.Rectangle.NO_BORDER;

header.AddCell(cell);

#endregion

#endregion

document.Add(header);

}

Tablo içindeki hücrelerin genişliklerini tabloyu örneklerken verebileceğimiz gibi daha sora SetWidths metodunu kullanarak da verebiliriz.

PdfPTable header = new PdfPTable(new float[] { 500 });

Ya da

PdfPTable header = new PdfPTable(1); //buradaki 1 değeri tablonun kaç hücreli olduğunu gösterir.

header.SetWidths(new float[] { 500 });

public void GetColumnTable(Document document)

{

#region Fields

iTextSharp.text.Color _columnHeaderColor = new iTextSharp.text.Color(000, 019, 127);

Font _columnHeaderFont = new Font(_bFont, _normalFontSize, Font.BOLD, _columnHeaderColor);

#endregion

#region MainTable

#region MainTable

PdfPTable mainTable = new PdfPTable(new float[] { 50, 150, 300 });

mainTable.DefaultCell.BorderWidth = 1;

mainTable.DefaultCell.BorderColor = iTextSharp.text.Color.BLACK;

#endregion

#region CellProperties

PdfPCell cell = new PdfPCell();

cell.HorizontalAlignment = Element.ALIGN_CENTER;

cell.VerticalAlignment = Element.ALIGN_MIDDLE;

#endregion

#region Order

cell.Phrase = new Phrase(“SIRA NO”, _columnHeaderFont);

mainTable.AddCell(cell);

#endregion

#region SubCategory

cell.Phrase = new Phrase(“ALT KATEGORİ”, _columnHeaderFont);

mainTable.AddCell(cell);

#endregion

#region productTable

#region productTable Details

PdfPTable productTable = new PdfPTable(new float[] { 200, 100 });

#endregion

#region Product

cell.Phrase = new Phrase(“ÜRÜN”, _columnHeaderFont);

cell.Colspan = 2;

productTable.AddCell(cell);

#endregion

cell.Colspan = 1;// her seferinde yeni bir cell nesnesi örneklemediğimiz için Colspan property’sini 1 yapıyoruz.

#region ProductName

cell.Phrase = new Phrase(“ADI”, _columnHeaderFont);

cell.Rotation = 90;

cell.Rotate();

productTable.AddCell(cell);

#endregion

#region ListPrice

cell.Phrase = new Phrase(“LİSTE FİYATI”, _columnHeaderFont);

productTable.AddCell(cell);

#endregion

#endregion

mainTable.AddCell(productTable);

#endregion

document.Add(mainTable);

}

Tablo oluştururken bazen resimdeki gibi, bir hücreyi iki veya daha fazla satır ya da kolona bölmemiz gerekebilir.

Bu durumda şöyle bir yol izliyoruz: Öncelikle yeni bir tablo oluşturup (#region productTable ile başlayan alt tablomuz) bu tablonun değerlerini set ediyoruz.Daha sonrasında yine ana tablomuzda hücreleri oluşturduğumuz yolla bu tablo için de gerekli hücreleri oluşturup tabloya ekliyoruz.

Bir hücreyi birleştirmek amacıyla HTML tablolarında kullandığımız Colspan attribute’u gibi burada da Colspan property’si mevcut.

cell.Colspan = 2; şeklinde bir atama ile bu işlemi gerçekleştirebilirsiniz.

Ayrıca tablo içindeki bir hücrenin metninin dikey olmasını da sağlayabilirsiniz, bunun için yapmanız gereken cell.Rotation = 90; şeklinde bir atama işlemi ile Rotation property’sinin değerini set etmek ve ardından cell.Rotate(); metodunu çağırmak.

NOT: Rotation property’sine sadece 90 ve katları değerler verebilirsiniz aksi taktirde uygulama exception fırlatır.

Alt tabloyla ilgili işlemleri tamamladıktan sonra ana tablomuza bu tabloyu ekliyoruz.

mainTable.AddCell(productTable);

Son olarak da tablomuza değerlerin eklendiği metodun içeriğini inceliyoruz.

public void GetValueTable(Document document)

{

#region Fields

int order = 1;

Font _nFont = new Font(_bFont, _normalFontSize);

#endregion

#region MainTable

#region MainTable Details

PdfPTable mainTable = new PdfPTable(new float[] { 50, 150, 300 });

mainTable.DefaultCell.BorderWidth = 1;

mainTable.DefaultCell.BorderColor = iTextSharp.text.Color.BLACK;

#endregion

#region CellProperties

PdfPCell cell = new PdfPCell();

cell.HorizontalAlignment = Element.ALIGN_CENTER;

cell.VerticalAlignment = Element.ALIGN_MIDDLE;

#endregion

foreach (var subCategory in _dt.ProductSubcategory)

{

#region Order

cell.Phrase = new Phrase(order.ToString(), _nFont);

mainTable.AddCell(cell);

#endregion

#region SubCategoryName

cell.Phrase = new Phrase(subCategory.Name, _nFont);

mainTable.AddCell(cell);

#endregion

#region productTable

#region productTable Details

PdfPTable productTable = new PdfPTable(new float[] { 200, 100 });

#endregion

foreach (var product in subCategory.Product)

{

#region ProductName

cell.Phrase = new Phrase(product.Name, _nFont);

productTable.AddCell(cell);

#endregion

#region ListPrice

cell.Phrase = new Phrase(product.ListPrice.ToString(“F2″), _nFont);

productTable.AddCell(cell);

#endregion

}

#endregion

mainTable.AddCell(productTable);

order++;

}

#endregion

document.Add(mainTable);

}

Burada yukarıda örneklediğimiz _dt (AdventureWorks_DataEntities) nesnesinin ProdcuctSubcategory tablosu içinde foreach döngüsüyle gezerek her bir alt kategoriye bağlı bulunan ürünlerin adını ve liste fiyatını tablomuza ekliyoruz. Ürünlerin adını ve liste fiyatını tabloya eklerken yine productTable adında bir alt tablo oluşturarak mainTable tablomuzun ilgili hücresine her döngüde bu alt tabloyu ekliyoruz.

Son olarak da tüm bu metotları toplayıp PDF dökümanımızı oluşturan metodumuz;

public string GetTable()

{

Document document = new Document(PageSize.A4);

#region Fields

string _fileName = string.Format(@”{0}Ürün Listesi.pdf”, AppDomain.CurrentDomain.BaseDirectory);

#endregion

try

{

PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(_fileName, FileMode.Create));

document.Open();

GetHeaderTable(document);

GetColumnTable(document);

GetValueTable(document);

return _fileName;

}

catch (DocumentException docEx)

{

MessageBox.Show(string.Format(“Hata:{0}”, docEx.Message), “Hata”, MessageBoxButton.OK, MessageBoxImage.Error);

return string.Empty;

}

finally

{

document.Close();

}

}

Burada öncelikle Document nesnesi aracılığıyla PDF dökümanımızı oluşturuyoruz. Document nesnemizi örneklerken PageSize enum’ını kullanarak hangi tip sayfada göstereceğinizi belirtebilirsiniz.

Document document = new Document(PageSize.A4);

Document nesnesinin PageSize property’si readonly only olduğu için sayfa tipini daha sonradan verme şansımız yok. Ayrıca burada aşağıdaki gibi bir kullanımla tabloyu sayfaya yatay olarak da yerleştirebilirsiniz.

Document document = new Document(PageSize.A4.Rotate());

PDF dosyasını istediğiniz bir yere kaydedip buradan gösterebilirsiniz. Ben uygulamanın olduğu Debug klasörünün içine kaydettim.

NOT: Klasik Windows uygulamalarından hatırlayacaksınız bir uygulamanın bulunduğu yolu almak için Application.StartupPath property’sini kullanıyorduk; ancak WPF uygulamalarında durum biraz değişmiş. WPF’ de yeni olduğum için ben de bu uygulama sayesinde bunu öğrenmiş oldum 🙂 Uygulamanın bulunduğu yolu AppDomain.CurrentDomain.BaseDirectory property’sinden elde ediyoruz.

Uygulamayı kaydetmek amacıyla aşağıdaki gibi bir PdfPWriter nesnesi örnekliyoruz.

PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(_fileName, FileMode.Create));

Document nesnemizi açıp tabloları oluşturmak için yazdığımız 3 metodu çağırıyoruz ve document nesnesiyle işimiz bittiğinde kapatıyoruz.

Bu kadar koddan sonra şimdi sıra geldi oluşturduğumuz PDF dökümanını görüntülemeye. Bunun için Designer kısmına geçip ekrana bir Button bir de WebBrowser nesnesi ekliyoruz. Daha sonra butonun Click eventinde aşağıdaki kodu yazıyoruz.

string path = GetTable();

wbReport.Navigate(new Uri(path));
NOT: WebBrowser kontrolünün Navigate metoduna parametre olarak path nesnesini verdiğinizde aşağıdaki gibi bir hata ile karşılaşıyorsunuz. Bu nedenle bir Uri nesnesi örnekleyip path değişkenini bu uri’ye parametre olarak verip oluşturduğunuz bu Uri nesnesini de WebBrowser kontrolünün Navigate metoduna parametre olarak vermeniz gerekiyor.


Tüm bu işlemlerin sonunda aşağıdaki gibi bir ekran görüntüsü elde ediyoruz.

NOT: PDF görüntülemek için Foxit Reader programını kullanmayı tercih ediyorum. Oluşturduğumuz tabloları görüntülemede Adobe Reader’dan daha başarılı buluyorum.

Böylece ilk yazımızın sonuna geldik. Anlatımdan kaynaklanan eksikliklerden dolayı şimdiden  affınıza sığınıyorum. Bir sonraki yazıda görüşmek dileğiyle hoşçakalın.

Reklamlar

8 thoughts on “C# İle iTextSharp dll’ini Kullanarak PDF Dökümanı Oluşturma

  1. c^# da acemiyim o yüzden constructor’da örneklediğin bölümü açar mısın. o kodları neyin içine yazıyoruz.

    1. constructor bir tipi örneklemizi sağlayan yapıcı metotdur. Örneğin elimizde bir personel sınıfı var. Bu personel sınıfı ve constructor’u aşağıdaki gibidir.

         21 public class Personel

         22 {

         23     public int Id { get; set; }

         24     public string Ad { get; set; }

         25 

         26     public Personel()

         27     {

         28 

         29     }

         30 }

      Constructor’da o sınıf için yapılmasını istediğin çeşitli işlemleri yapabilirsin. Yukarıda yazıda constructor’da yazıyoruz dediğim kısım da aslında WPF formunun constructor’ı.

      public MainWindow()
      {
      InitializeComponent();
      _bFont = BaseFont.CreateFont(@”C:\WINDOWS\Fonts\tahoma.ttf”, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); //Türkçe karakter sorununu çözmek amacıyla dökümanımızda kullanmak üzere bilgisayarımızda bulunan fontlardan birini seçiyoruz ve base font olarak olarak tanımlıyoruz. Daha sonra oluşturacağımız tüm fontları bu base fonttan kalıtıyoruz.
      _emptyString = new Phrase(“x”, new Font(_bFont, _normalFontSize, Font.NORMAL,BaseColor.WHITE));// İçinde veri olmayan bir hücre oluşturmamız gerektiğinde hücrenin değerine bu şekilde bir metin vermemiz gerekiyor. Aksi taktirde boş hücre yok sayılıp bir sonraki hücre onun yerine ekleniyor. Bu da tablomuzu oluştururken hata oluşmasına dolayısıyla tablonun oluşturulamamasına ya da yanlış bir tablo oluşmasına neden oluyor.
      }

  2. Merhaba; Paylaşım için teşekkürler. Bu uygulamayı asp.net sayfam için tasarlıyorum.
    string _fileName = string.Format(@”{0}Ürün Listesi.pdf”, AppDomain.CurrentDomain.BaseDirectory); burada kodların bulunduğu yere kaydediyor kullanıcıya pdf dosyasını nasıl gösterebilirim??

  3. Yada açılmış halini göstermeden indirme seçeneği şeklinde nasıl gösterebilirim ekranda? Cevaplarsanız çok sevinirim.

    1. Asp.net’te nasıl gösterebileceğimiz konusunda ben de fikir sahibi değildim açıkcası. Sayenizde bana da yararı oldu 🙂
      Kolay olan iki yöntem buldum. Bu iki kodda da göstermeden indirme seçeneği sunuyor.
      İlki çok basit ve bilindik bir şey aslında :

         23 Response.Redirect("~/Ürün Listesi.pdf");

      İkincisi :

         26 string path = Server.MapPath("~/Ürün Listesi.pdf");

         27         WebClient client = new WebClient();

         28         Byte[] buffer = client.DownloadData(path);

         29         Response.ContentType = "application/pdf";

         30         Response.AddHeader("content-length", buffer.Length.ToString());

         31         Response.BinaryWrite(buffer);

      Umarım işinizi görür.

Bir Cevap Yazın

Aşağıya bilgilerinizi girin veya oturum açmak için bir simgeye tıklayın:

WordPress.com Logosu

WordPress.com hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Twitter resmi

Twitter hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Facebook fotoğrafı

Facebook hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Google+ fotoğrafı

Google+ hesabınızı kullanarak yorum yapıyorsunuz. Çıkış  Yap / Değiştir )

Connecting to %s