Ajax Gridview Tabloyu Excel Tablosuna dönüştürmek
Asp.Net'te Web uygulaması geliştirirken GridView tablosu içindeki veriyi
Excel Tablosuna dönüştürme zorunluluğu çok sık karşılaştığımız bir ihtiyaçtır.
Bu makalemizde ışık tutacağımız senaryoları şöyle sıralayabiliriz.
- GridView içindeki verinin tamamını Excele dönüştürme.
- GridView içindeki verinin göründüğü sayfayı Excele dönüştürmek
- GridView içinden seçilen rasgele satırı Excele Dönüştürmek
- GridView üzerindeki resim kolonunu Excel Tabloya dönüştürmek
- GridView içindeki sayı ve tarih sütünlarını Excel'e özel format
tanımlayarak dönüşüm yapmak
Bu amaçla MS Management Studio içinde bir tablo oluşturarak başlayalım.
CREATE TABLE [dbo].[Personel](
[PersonelId] [int] IDENTITY(1,1) NOT NULL,
[Adi] [nvarchar](50) NULL,
[Yasi] [nvarchar](50) NULL,
[Eposta] [nvarchar](50) NULL,
[Sayi] [nvarchar](50) NULL,
[Bugun] [datetime] NULL,
[ImageURL] [nvarchar](250) NULL
) ON [PRIMARY]
|
Daha sonraki adımda Visual Studio içinde AJAX Enabled WebApplication açarak
ihtiyacımız olan bileşenleri oluşturmaya başlıyoruz.
Yapmayı istediğimiz şey database üzerindeki verileri bir
sayfada tablo halinde göstererek kullanıcının istediği satırları, tüm tabloyu
yada seçili sayfayı Excel Tablosuna dönüştürmek. Bunun için bizim en başta bir
Update Panel'e ihtiyacımız var. Çünkü seçim yapılacak bir sayfamız var ve her
seçimde sayfamızın yenilenmesini istemeyiz. Default.aspx sayfası içine
sürüklediğimiz UpdatePanel içine GridView yerleştirdikten sonra, sütünları
aşağıdaki gibi düzenliyoruz. Burda iki tane TemplateField, beş tanede BoundField
ekeleyerek DataField'larını düzenliyoruz.
Düzenlemeleri yaptıktan sonra üç tane buton sürükleyerek UpdatePanel'in
tetikleyicisine bu butonları verebiliriz. Düzenlemeler yapıldıktan sonra
Default.aspx sayfası içinde kodlar aşağıdaki gibi görülecektir.
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<table width="100%">
<tr>
<td>
<asp:GridView ID="GridView1" runat="server" Width="100%"
OnPageIndexChanging="GridView1_PageIndexChanging"
PageSize="10" AllowPaging="True"
AutoGenerateColumns="False" OnRowDataBound="GridView1_RowDataBound"
DataKeyNames="PersonelId">
<Columns>
<asp:TemplateField HeaderText="Select">
<ItemTemplate>
<asp:CheckBox ID="chkSecim" runat="server"} />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Adi" HeaderText="Adı" />
<asp:BoundField DataField="Yasi" HeaderText="Yaşı" />
<asp:BoundField DataField="Eposta" HeaderText="Eposta" />
<asp:BoundField DataField="Sayi" HeaderText="Sayı" />
<asp:BoundField DataField="Bugun" HeaderText="Bugün" />
<asp:TemplateField HeaderText="Sevdiği">
<ItemTemplate>
<asp:Image ID="Image1" runat="server" ImageUrl='<%# Bind("ImageURL")
%>'></asp:Image>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</td>
</tr>
<tr>
<td>
<table width="100%">
<tr>
<td width="25%">
<asp:Button ID="TumTabloyuDonustur" OnClick="TumTabloyuDonustur_Click" runat="server"
Text="Tüm Satırları Dönüştür" />
</td>
<td width="25%">
<asp:Button ID="SeciliSatirlariDonustur" OnClick="SeciliSatirlariDonustur_Click" runat="server"
Text="Seçili Satırları Dönüştür"/>
</td>
<td width="25%">
<asp:Button ID="SayfayiDonustur" OnClick="SayfayiDonustur_Click" runat="server"
Text="Mevcut Sayfayı Dönüştür"/>
</td>
</tr>
</table>
</td>
</tr>
</table>
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger
ControlID="TumTabloyuDonustur" />
<asp:PostBackTrigger
ControlID="SeciliSatirlariDonustur" />
<asp:PostBackTrigger
ControlID="SayfayiDonustur" />
</Triggers>
</asp:UpdatePanel> |
Dönüştürme işlemine başlamadan önce GridView için yapmamız gereken üç
kontrolümüz var. Bunlar:
1. Personel tablomuzu GridView içine taşımak
2. GridView içinde sayfalanmasına izin vermek
3. Seçim kutusunun işaretlendiği değerleri koruyarak başka sayfaya
yönlendirme yapmak
1. Personel Tablosunu GridView içine doldurmak
Bu işlem sırasında kullanılan ConnectionString cümlesini metot dışında
tanımlamak daha sağlıklı olduğu için aşağıdaki şekilde kullanıyoruz.
private string cnstr =
ConfigurationManager.ConnectionStrings["PersonelConnectionString"].ConnectionString;
private string sql=string.Empty; |
private void GridDoldur()
{
string sql = "Select PersonelId, Adi, Yasi, Eposta,
Sayi, Bugun, ImgUrl From Personel";
SqlDataAdapter da = new SqlDataAdapter(sql, "PersonelConnectionString");
DataTable dt = new DataTable();
da.Fill(dt);
GridView1.DataSource = dt;
GridView1.DataBind();
} |
Yukarıda private bir metotla sql bağlantısını kurup veri tabanındaki tablomuzu bir
DataTable üzerine alarak, GridView içine bağlıyoruz. Sayfa açıklırken
yüklenmesini sağlıyoruz.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GridDoldur();
}
} |
2. PageIndexChanging olayında sayfanın görüntülenmesi
Seçilen satırlardaki verileri göstermek için ayrı bir GridView oluşturmadan
ortak kullanımla sayfalama yoluna gitmek için aşağıdaki düzenlemeyi yapmamız
gerekiyor. Biz GridView özelliklerinden
AllowPaging özelliğini "true" yaptığımızda bu aslında bu kullanımı sağlayabiliyoruz. Ama
burda dikkat etmemiz gereken şey bu gösterimin sadece seçilen satırlar için
olması gerektiği.
protected void GridView1_PageIndexChanging(object sender,
GridViewPageEventArgs e)
{
SecilenListeyiGetir();
GridView1.PageIndex = e.NewPageIndex;
BindGrid();
} |
Bu yüzden seçilen satırları geçici bir ArrayList değişkeninde
tutarak ViewState içinde muhafaza edilmesini sağlayacağız. Kullanıcı diğer
sayfaları gezerken seçilen değerler saklı kalacak.
3. Seçilen satırlardaki değerlerin korunması
Bu işlemi yapabilmek için bir tane ArrayList değişkenine ihtiyaç duyarız.
Bunun için System.IO alanını projemize referans etmeliyiz.
using System.IO;
ArrayList arrlist = new ArrayList(); |
Daha sonraki adımda SecilenListeyiGetir metodunu oluşturacağız. Bu metot
içinde yaptığımızı kısaca açıklamak gerekirse; ViewState içinde bir ArrayList
değişkeni tanımlıyoruz, daha sonra bir foreach döngüsü ile GridView satırları
içinde dönerek find kontrolü ile tespit ettiğimiz chkSecim olarak
adlandırdığımız CheckBox kontrolünün seçili olanlarını değişken üzerine
atıyoruz.
private void SecilenListeyiGetir()
{
if (this.ViewState["ArrList"] != null)
{
arrlist = (ArrayList)this.ViewState["ArrList"];
}
foreach (GridViewRow gvr in GridView1.Rows)
{
CheckBox chkSecim = (CheckBox)gvr.FindControl("chkSecim");
if (chkSecim.Checked)
{
if
(!arrlist.Contains(GridView1.DataKeys[gvr.RowIndex].Value.ToString()))
arrlist.Add(GridView1.DataKeys[gvr.RowIndex].Value.ToString());
}
else
{
if (arrlist.Contains(GridView1.DataKeys[gvr.RowIndex].Value.ToString()))
arrlist.Remove(GridView1.DataKeys[gvr.RowIndex].Value.ToString());
}
}
if (arrlist.Count > 0)
{
this.ViewState["ArrList"] = arrlist;
}
} |
GridView'un RowDataBound Olayı
Seçilmiş CheckBox'ları seçili tutmak için GridView kontrolün RowDataBound
olayında ArrayList'in seçili herhangi bir değer içerip içermediğini
kontrol ediyoruz. Eğer öyle bir değer içeriyorsa CheckBox'un Checked
özelliğini "true" olarak set ediyoruz;
protected void
GridView1_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
if
(arrlist.Contains(GridView1.DataKeys[e.Row.RowIndex].Value.ToString()))
{
CheckBox
chkSelect = (CheckBox)e.Row.FindControl("chkSelect");
chkSelect.Checked = true;
}
}
}
|
Şimdi internet tarayıcısında sayfa çalıştırıldığında GridView içine tablo
verilerinin dolduğunu görebiliriz ve sayfalar arasında gezinebiliriz. Seçilen
herhangi bir sayfadaki herhangi bir seçim kutusu, başka sayfalar görüntülenirken
bizim için saklı tutulacaktır.
GridView'u Excel'e Aktarım
Şimdi makalemizin ana amacına geldik. GridView içindeki verileri Excel
sayfası olarak görüntülemek. Bunu başarmak için GridView sınıfından bir nesne
oluşturmamız gerekir. Bu nesnenin sütunları, veri tabanından
getirerek GridView kontrolü içinde gösterdiğimiz tablo sütunları ile aynı olmalı. GridView sınıfının, RenderControl metodu
yardımıyla, verileri bir html olarak yazdıracağız. Daha sonra FileStream
kullanarak, bir Excel dosyası oluşturup, içerisini oluşturduğumuz html ile
dolduracağız. Bu arada Tarih ve sayı kolonları için format düzenlemesi
yapacağız. Şimdi bunları adım adım yapalım:
1: GridView Instance oluşturup DataTable'a bağlayalım
private void GridExceleDonsun(DataTable dtData)
{
StringWriter strWriter = new StringWriter();
HtmlTextWriter htmlWriter = new HtmlTextWriter(strWriter);
BoundField PerId = new BoundField();
BoundField PerAdi = new BoundField();
BoundField PerYasi = new BoundField();
BoundField PerEposta = new BoundField();
BoundField KesirliSayi = new BoundField();
BoundField BugunTarihi = new BoundField();
ImageField ImgField = new ImageField();
PerAdi.HeaderText = " Personel Id";
PerAdi.HeaderText = "Adı";
PerYasi.HeaderText = "Yaşı";
PerEposta.HeaderText = "Eposta";
KesirliSayi.HeaderText = "Kesirli Sayı";
BugunTarihi.HeaderText = "Bugün";
ImgField.HeaderText = "Sevdiği";
ImgField.ItemStyle.Height = Unit.Pixel(100);
ImgField.ItemStyle.Width = Unit.Pixel(150);
PerId.DataField = "PersonelId";
PerAdi.DataField = "Adi";
PerYasi.DataField = "Yasi";
PerEposta.DataField = "Eposta";
KesirliSayi.DataField = "Sayi";
BugunTarihi.DataField = "Bugun";
ImgField.DataImageUrlField = "ImgURL";
ImgField.DataImageUrlFormatString =
"http://localhost/Makaleler/ExportingData/{0}";
GridView g = new GridView();
g.AutoGenerateColumns = false;
g.RowDataBound += new
GridViewRowEventHandler(g_RowDataBound);
g.Columns.Insert(0, PerId);
g.Columns.Insert(1, PerAdi);
g.Columns.Insert(2, PerYasi);
g.Columns.Insert(3, PerEposta);
g.Columns.Insert(4, KesirliSayi);
g.Columns.Insert(5, BugunTarihi);
g.Columns.Insert(6, ImgField);
g.DataSource = dtData;
g.DataBind();
} |
Yukarıdaki kodda altı tane BoundField ve bir tane ImageField
kolonu oluşturduk, başlıklarını hazırladık. Herbirinin FieldName'ini
beirttik. Son sütundaki DataImageUrlField ve DataImageUrlFormatString
belirttik. DataImageUrlFormatString içine resmin tam yerinin URL'sini
verdik. Resmin genişliği ve yüksekliğini ayarladık.
Yeni bir GridView
instance oluşturup AutoGenerateColumns özelliğini "false"
yapıyoruz. BoundField ve ImageField' larımızı içine yerleştiriyoruz. Daha
sonra GridView içine DataTable 'dtData' bağlayarak Excel sayfasına
dönüştürüyoruz.
Oluşturduğumuz GridView instance'ı RowDataBound olayı ile başlatıyoruz.
Bunun sebebi bazı sütunların özel format gerektirmesidir.
protected void g_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
e.Row.Cells[4].Attributes.Add("class", "text");
e.Row.Cells[5].Attributes.Add("class", "tarihformat");
}
} |
2: StringWriter Instance Oluşturmak
StringWriter strwriter = new StringWriter();
HtmlTextWriter htmlwriter = new HtmlTextWriter(strwriter);
g.RenderControl(htmlwriter);
string htmlmarkup = strwriter.ToString(); |
Yukardaki kodu anlamak kolaydır. StringWriter ve HtmlTextWriter instance
yaratıp GridView instance içeriğini html olarak dönüştürür. Artık elimizden
'htmlmarkup' denilen bir HTML kaynağı vardır.
3: FileStream Nesnesi Oluşturmak
Excel dosya adı oluşturarak 'Dosya1.xls' FileStream nesnesinin
içini htmlmarkup içeriği ile dolduruyoruz.
FileStream fs = new FileStream(Server.MapPath("Dosya1.xls"),
FileMode.Create);
try
{
Byte[] bContent =
System.Text.Encoding.GetEncoding("utf-8").GetBytes(htmlmarkup);
fs.Write(bContent, 0,
bContent.Length);
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
finally
{
fs.Close();
fs.Dispose();
} |
4: Sayı ve Tarih sütunlarının Excel Sayfası için
formatlanması
Bir Cascading Style Sheet (CSS) (basamaklı biçim deposu) yaratarak
kesirli sayı ve tarih kolonları için Excel sayfasına göre formatlıyoruz.
string style = @"<style> .text { mso-number-format:0\.00; } ";
style += ".tarihformat {mso-number-format:\"Short Date\"}";
style += " </script>";
Response.Write(style);
|
5: Excel Sayfasında indirildi mesaj kutusu
Tablo içerisinden indirilmesi istenen kısımların nereye ve hangi
adla kaydedilmesi gerektiği kullanıcıdan dinamik olarak sorgulanması gereken
bir görevdir.İşin bu kısmınıda aşağıdaki gibi yapabiliyoruz.
Response.AppendHeader("content-disposition",
"attachment;filename=File1.xls");
Response.WriteFile("File1.xls");
Response.End(); |
Son düzenlemelerden sonra
GridView bir tabloyu Excel Sayfası olarak nasıl görüntüleyip, Excel
Dökümanı olarak nasıl kaydedebileceğimizi örneğimiz üzerinde ayrıntılı
şakilde anlamaya çalıştık. Tüm düzenlemelerden sonra kodlarımız bütün olarak
aşağıdaki gibi görünmektedir.
private ArrayList arrlist = new ArrayList();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
GridDoldur();
}
}
private string cnstr =
ConfigurationManager.ConnectionStrings["PersonelConnectionString"].ConnectionString;
private string sql;
private void GridDoldur()
{
string sql = "Select PersonelId, Adi, Yasi, Eposta, Sayi,
Bugun, ImageURL From Personel";
SqlDataAdapter da = new SqlDataAdapter(sql, cnstr);
DataTable dt = new DataTable();
da.Fill(dt);
GridView1.DataSource = dt;
GridView1.DataBind();
}
protected void GridView1_PageIndexChanging(object sender,
GridViewPageEventArgs e)
{
SecilenListeyiGetir();
GridView1.PageIndex = e.NewPageIndex;
GridDoldur();
}
private void GridExceleDonussun(DataTable dtData)
{
StringWriter strWriter = new StringWriter();
HtmlTextWriter htmlWriter = new HtmlTextWriter(strWriter);
BoundField PerId = new BoundField();
BoundField PerAdi = new BoundField();
BoundField PerYasi = new BoundField();
BoundField PerEposta = new BoundField();
BoundField KesirliSayi = new BoundField();
BoundField BugunTarihi = new BoundField();
ImageField ImgField = new ImageField();
PerAdi.HeaderText = " Personel Id";
PerAdi.HeaderText = "Adı";
PerYasi.HeaderText = "Yaşı";
PerEposta.HeaderText = "Eposta";
KesirliSayi.HeaderText = "Kesirli Sayı";
BugunTarihi.HeaderText = "Bugün";
ImgField.HeaderText = "Sevdiği";
ImgField.ItemStyle.Height = Unit.Pixel(100);
ImgField.ItemStyle.Width = Unit.Pixel(150);
PerId.DataField = "PersonelId";
PerAdi.DataField = "Adi";
PerYasi.DataField = "Yasi";
PerEposta.DataField = "Eposta";
KesirliSayi.DataField = "Sayi";
BugunTarihi.DataField = "Bugun";
ImgField.DataImageUrlField = "ImgUrl";
//AdresDüzenlenecek
ImgField.DataImageUrlFormatString =
"http://localhost/Makaleler/ExportingData/{0}";
GridView g = new GridView();
g.AutoGenerateColumns = false;
g.RowDataBound += new
GridViewRowEventHandler(g_RowDataBound);
g.Columns.Insert(0, PerId);
g.Columns.Insert(1, PerAdi);
g.Columns.Insert(2, PerYasi);
g.Columns.Insert(3, PerEposta);
g.Columns.Insert(4, KesirliSayi);
g.Columns.Insert(5, BugunTarihi);
g.Columns.Insert(6, ImgField);
g.DataSource = dtData;
g.DataBind();
g.RenderControl(htmlWriter);
string htmlmarkup = strWriter.ToString();
FileStream fs = new FileStream(Server.MapPath("Dosya1.xls"),
FileMode.Create);
try
{
Byte[] bContent =
System.Text.Encoding.GetEncoding("utf-8").GetBytes(htmlmarkup);
fs.Write(bContent, 0,
bContent.Length);
}
catch (Exception ex)
{
Response.Write(ex.Message);
}
finally
{
fs.Close();
fs.Dispose();
}
string style = @"<style> .text { mso-number-format:0\.00; }
";
style += ".tarihformat {mso-number-format:\"Short Date\"}";
style += " </script>";
Response.Write(style);
Response.AppendHeader("content-disposition",
"attachment;filename=Dosya1.xls");
Response.WriteFile("Dosya1.xls");
Response.End();
}
protected void g_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
e.Row.Cells[4].Attributes.Add("class", "text");
e.Row.Cells[5].Attributes.Add("class", "tarihformat");
}
}
private void SecilenListeyiGetir()
{
if (this.ViewState["ArrList"] !=null)
{
arrlist =
(ArrayList)this.ViewState["ArrList"];
}
foreach (GridViewRow grv in GridView1.Rows)
{
CheckBox chkSecim =
(CheckBox)grv.FindControl("chkSecim");
if (chkSecim.Checked)
{
if(!arrlist.Contains(GridView1.DataKeys[grv.RowIndex].Value.ToString()))
arrlist.Add(GridView1.DataKeys[grv.RowIndex].Value.ToString());
}
else
{
if(arrlist.Contains(GridView1.DataKeys[grv.RowIndex].Value.ToString()))
arrlist.Remove(GridView1.DataKeys[grv.RowIndex].Value.ToString());
}
}
if (arrlist.Count>0)
{
this.ViewState["Arrlist"] = arrlist;
}
}
protected void GridView1_RowDataBound(object sender,
GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
if
(arrlist.Contains(GridView1.DataKeys[e.Row.RowIndex].Value.ToString()))
{
CheckBox
chkSecim = (CheckBox)e.Row.FindControl("chkSecim");
chkSecim.Checked = true;
}
}
}
protected void TumTabloyuDonustur_Click(object sender, EventArgs e)
{
DataTable dt = new DataTable();
string sql = "Select PersonelId, Adi, Yasi, Eposta,
Sayi, Bugun, ImageURL From Personel";
SqlDataAdapter da = new SqlDataAdapter(sql, cnstr);
da.Fill(dt);
GridExceleDonussun(dt);
}
protected void SeciliSatirlariDonustur_Click(object sender, EventArgs e)
{
SecilenListeyiGetir();
if (this.ViewState["ArrList"] != null)
{
arrlist =
(ArrayList)this.ViewState["ArrList"];
}
DataTable dt = new DataTable();
string sql = "Select PersonelId, Adi, Yasi, Eposta, Sayi,
Bugun, ImageURL From Personel";
SqlDataAdapter da = new SqlDataAdapter(sql, cnstr);
da.Fill(dt);
DataView dv = dt.DefaultView;
DataTable dtTemp = dv.ToTable().Clone();
for (int i = 0; i < arrlist.Count; i++)
{
dv.RowFilter = "PersonelId=" +
arrlist[i].ToString();
dtTemp.ImportRow(dv.ToTable().Rows[0]);
}
GridExceleDonussun(dtTemp);
}
protected void SayfayiDonustur_Click(object sender, EventArgs e)
{
DataTable dt = new DataTable();
string sql = "Select PersonelId, Adi, Yasi, Eposta, Sayi,
Bugun, ImageURL From Personel";
da.Fill(dt);
DataView dv = dt.DefaultView;
DataTable dtTemp = dv.ToTable().Clone();
foreach (GridViewRow grv in GridView1.Rows)
{
dv.RowFilter = "PersoneId" +
GridView1.DataKeys[grv.RowIndex].Value.ToString();
dtTemp.ImportRow(dv.ToTable().Rows[0]);
}
GridExceleDonussun(dtTemp);
} |
Bu çalışmada veritabanından alarak, web sayfası üzerinde kullanıcıya sunduğumuz veriyi; Excel Sayfası olarak farklı kaydetme seçeneğini örneğimiz üzerinden anlamaya çalıştık. Umarım sizler için yararlı olmuştur.. Sermin Yağcı http://serminyagci.blogspot.com/
|