27 Haziran 2012 Çarşamba

Asp.Net ile Excel'den Veri Çekip Bu Verileri Diziler Yardımıyla Tabloya Kaydetmek

Bu makalemden önce yazdığım makalelerdeki konuları birleştirip bir örnek uygulama yapmak istedim.Bu uygulamada bir excel dosyasından çektiğimiz verileri PL SQL dizileri yardımıyla ilgili tablomuza kaydedeceğiz buradaki amaç Hem dizi kullanımı nı pekiştirmek hemde dizilerin esnekliğini ortaya koymak.

Örnek olarak aşağıdaki gibi bir Excel Dosyamız olsun
.














İşlemimize öncelikle bu Excel dosyasındaki verileri okuyarak başlayacağız bu işlemin nasıl yapılacağını (Asp.NET ile Excel'den Veri Okumak) isimli makalemde anlatmıştım bundan dolayı tekrar detayına girmiyorum.Veri okuma işlemini tamamladıktan sonra bu verileri yazacağımız Stored Procedure parametre olarak göndermek için özel bir formata sokacağız(Dataları birleştireceğiz). Kullanacağımız format için aynı satırda olan datalar arasına '*' işareti koyacağız ve her satır değiştiğindede oluşan metnin sonuna '#' işareti koyacağız.

Kullanacağımız Format : 
Bilgisayar * 1500 * 3 * 4500 # Tahta Masa * 100 * 5 * 500 # Kalem * 1,25 * 100 * 125 ...

Excel'den veri okumak için yazdığımız prosedürün bize DataTable tipinde bir nesne döndüğünü hatırlayın.Excel'deki dataları alıp DataTable nesnesini içine dolduruyordu bizde bu nesneyi kullanarak datalarımızı yukarıdaki formata çeviricez bunun için aşağıdaki gibi bir fonksiyon yazmamız yeterli olacaktır.

    #region Datatable daki Değerleri Geçerli Formata Çevir

    private string getExcelData(System.Data.DataTable dTable)
    {
        string rValue = "";
        string temp;

        foreach (DataRow dRC in dTable.Rows)
        {
            temp = "";

            //Satırdaki Dataları '*' işareti ile birleştir
            for (int i = 0; i < dTable.Columns.Count; i++)
            {
                temp += dRC[i].ToString() + "*";
            }
            //Satırın sonuna fazladan koyulan '*' işaretini çıkar
            temp = temp.Substring(0, temp.Length - 1);

            //Bir satır okundu bir sonraki satıra geçilecek Araya '#' işareti koy
            rValue += temp + "#";
        }

        //Oluşan verinin sonuna fazladan koyulan '#' işaretini çıkar ve sonucu ilgili yere bildir
        return rValue.Substring(0, rValue.Length - 1); ;
    }
    #endregion

Önyüzde kullanacağımız Fonksiyonlarımızın büyük bir çoğunluğu hazır olduğuna göre Database geçip önyüzden gelen datayı Split edip bu dataları tabloya INSERT edip sonuçta tabloda oluşan dataların hepsini önyüze geri dönen bir Stored Procedure yazalım.Bu prosedürde daha önceki makalelerimden biri olan (Oracle PL SQL'de Dizi Kullanımı) isimli makalemizde yazdığımız dizi tipi ve SPLIT işlemi yapıp dizi tipinde sonuç dönen F_SPLIT fonksiyonlarını kullanacağız.Bu fonksiyon yardımıyla önyüzden gelen datayı parçalayacağız.

Not : Datalarımızı kaydedeceğimiz Tablo aşağıdaki gibi olacaktır.



CREATE OR REPLACE PROCEDURE MIMRE.INSERT_EXCEL_DATA
(
    P_EXCEL_LINES VARCHAR2, --Excel'deki satırların özel operatörlerle birleştirilmesi sonucu olulan değer
    --Örnek Değer :  Bilgisayar * 1500 * 3* 4500 # Tahta Masa * 100 * 5 * 500 # Kalem * 1,25 * 100 * 125
    --Yukardaki Örnek Değer, aynı satırdaki hücrelerin '*' , satırların ise '#' operatörü ile birleştirilmesi ile oluşturulmuştur.
                                              
    P_SEPERATOR1 VARCHAR2, --Örnek Değer : '#'   (Satırların birleştirildiği değer)
    P_SEPERATOR2 VARCHAR2, --Örnek Değer : '*'   (Hücrelerin birleştirildiği değer)
   
    P_CURSOR OUT SYS_REFCURSOR,
    ERROR_NO OUT NUMBER,
    ERROR_DESC OUT VARCHAR2
)
AS

    --Excel'deki Bütün Satırları Saklayacak Olan Dizi Değişkenimiz
    MyExcel_ALL_LINES   MIMRE.COMMON.STRINGARRAY;   
    --Her bir Satırdaki Hücre Değerlerinin Saklayacak Olan Dizi Değişkenimiz
    MyExcel_LINE_VALUE MIMRE.COMMON.STRINGARRAY;
   
BEGIN

    ERROR_NO := 0;
    ERROR_DESC := '';

    --P_EXCEL_LINES parametresindeki Datalar Kolon bazlı olarak parçalanıyor.
    --(Yukarıda'ki Örnek dataya göre önce '#' karakterine göre Split işlemi yapılacak).Oluşacak Dizinin
    --1. Elemanı     :   Bilgisayar * 1500 * 3* 4500    (Excel 1. Satır)
    --2. Elemanı     :   Tahta Masa * 100 * 5 * 500   (Excel 2. Satır)
    --3.Elemanı      :    Kalem * 1,25 * 100 * 125      (Excel 3 Satır) 
    MyExcel_ALL_LINES := MIMRE.COMMON.F_SPLIT( P_EXCEL_LINES , P_SEPERATOR1 );
   
    FOR arrIndexLine IN MyExcel_ALL_LINES.FIRST .. MyExcel_ALL_LINES.LAST --Exceldeki Satırlar Geziliyor
    LOOP
    BEGIN
        --Yukarıda oluşan dizinin Her bir elemanı Yüklenilen Excel'deki bir satırdı.
        --Fakat dizimizde bu satır birleşik olarak tutuluyor yani : Bilgisayar * 1500 * 3* 4500 şeklinde
        --Şimdi biz bu satırı'da parçalayarak Satır ve Hücre bazında değerlere ulaşıcaz.
        --Oluşacak dizinin elemanları
        --1. Eleman :     Bilgisayar    <Excel'deki 1. Hücre>
        --2. Eleman :     1500           <Excel'deki 2. Hücre>
        --3. Eleman :     3                <Excel'deki 3. Hücre>
        --4. Eleman :     4500           <Excel'deki 4. Hücre>
        MyExcel_LINE_VALUE := MIMRE.COMMON.F_SPLIT( MyExcel_ALL_LINES(arrIndexLine) , P_SEPERATOR2 );
       
        --Satırı tabloya Insert Et
        INSERT
           INTO MIMRE.URUNLER
                    (
                        URUN_AD,
                        URUN_ADET,
                        URUN_FIYAT,
                        URUN_TOPLAM_FIYAT
                    )
        VALUES(
                        MyExcel_LINE_VALUE(1), --Excel'deki 1. Kolon Urun Adıydı
                        TO_NUMBER(MyExcel_LINE_VALUE(2)), --Excel'deki 2. Kolon Urun Adetiydi
                        TO_NUMBER(MyExcel_LINE_VALUE(3)), --Excel'deki 3. Kolon Urun Fiyatıydı
                        TO_NUMBER(MyExcel_LINE_VALUE(4))  --Excel'deki 4. Kolon Urun Toplam Fiyatıydı
                    );
   
        EXCEPTION
        WHEN OTHERS THEN
            ERROR_NO := ERROR_NO + 1;
            ERROR_DESC := ERROR_DESC || ERROR_NO || '. Hata : ' || SQLERRM || '<BR />';
    END;
    END LOOP;

    --Tablodaki Verileri Çek
    OPEN P_CURSOR FOR
        SELECT URUN_AD,
                    URUN_ADET,
                    URUN_FIYAT,
                    URUN_TOPLAM_FIYAT
          FROM MIMRE.URUNLER;

END INSERT_EXCEL_DATA;
/

Gördüğünüz gibi prosedürümüz son derece basit ve anlaşılır bir format'ta bu yöntemi bir çok farklı uygulamada kullanabilirsiniz.

Database prosedürümüzde hazır olduğuna göre Web tarafına geçip aşağıda'ki gibi bir sayfa tasarımı yapıp oluşturduğumuz parçaları birleştirelim.
Dataları Excel'den okuma ve gride yükleme işlemini daha önceki makalelerimiz de anlatmıştık.Bu yüzden ekran da bu işlemleri tekrar anlatmıyorum.

Bu ekran da sadece yazdığımız prosedüre parametreleri geçip Kaydet'me ve Grid'i güncelleme işlemlerini yapacak.

Bunun için öncelikle yazdığımız prosedüre parametreleri geçip prosedürü çalıştıracak ve Tablomuzda oluşan dataları bize geri döndüren InsertAndGet_ExcelData() adında bir method yazalım.


public DataTable InsertAndGet_ExcelData()
{
    string connectionString = ""; //Buraya ConnectionString Yazılmalı
    OracleConnection oConnection = new OracleConnection(connectionString);
    OracleCommand oCommand = new OracleCommand("MIMRE.INSERT_EXCEL_DATA", oConnection);

    OracleParameter P_EXCEL_LINES = new OracleParameter("P_EXCEL_LINES", OracleType.VarChar);
    P_EXCEL_LINES.Value = getExcelData((DataTable)Session["ExcelTable"]);
    oCommand.Parameters.Add(P_EXCEL_LINES);

    OracleParameter P_SEPERATOR1 = new OracleParameter("P_SEPERATOR1", OracleType.VarChar);
    P_SEPERATOR1.Value = "#"; //Satırları birleştirdiğimiz değer
    oCommand.Parameters.Add(P_SEPERATOR1);

    OracleParameter P_SEPERATOR2 = new OracleParameter("P_SEPERATOR2", OracleType.VarChar);
    P_SEPERATOR2.Value = "*"; //Hücreleri birleştirdiğimiz Değer
    oCommand.Parameters.Add(P_SEPERATOR2);

    OracleParameter P_CURSOR = new OracleParameter("P_CURSOR", OracleType.Cursor);
    P_CURSOR.Direction = ParameterDirection.Output;
    oCommand.Parameters.Add(P_CURSOR);

    OracleParameter P_ERROR_NO = new OracleParameter("ERROR_NO", OracleType.Number);
    P_ERROR_NO.Direction = ParameterDirection.Output;
    oCommand.Parameters.Add(P_ERROR_NO);

    OracleParameter P_ERROR_DESC = new OracleParameter("ERROR_DESC", OracleType.Cursor);
    P_ERROR_DESC.Direction = ParameterDirection.Output;
    oCommand.Parameters.Add(P_ERROR_DESC);

    DataTable dTable = new DataTable();

    //Prosedürü Çalıştır
    oConnection.Open();
           
    OracleDataAdapter dAdapter = new OracleDataAdapter(oCommand);
    dAdapter.Fill(dTable);

    oConnection.Close();

    if (Convert.ToInt32(P_ERROR_NO.Value) > 0) //Hatalar oluşmuşmu
    {
        Response.Write("Insert İşlemi Sırasında Oluşan Hatalar : " +   P_ERROR_DESC.Value.ToString());
    }           

    return dTable;
} 


Prosedürümüzü tetikleyecek methodumuzda hazır olduğuna göre artık yapacağımız başka bir işlem kalmadı yapmamız gereken tek şey ekrandaki "Verileri Kaydet ve Grid'i Güncelle" butonuna basılınca InsertAndGet_ExcelData() methodunu çağırmak ve işlem sonucu tablodan gelen dataları ekrandaki gridde göstermek.


protected void btnSaveAndRefreshGrid_Click(object sender, EventArgs e)
{
    if (Session["ExcelTable"] == null)//Eğer datalar yüklenmemişse uyarı ver ve işlem yapma
    {
        Response.Write("Verileri kaydetmek için öncelikle 'Yükle' butonuna basmalısınız");
        return;
    }
    else
    {
        DataTable newDt = InsertAndGet_ExcelData();
        //Session'ımızı kill edelim
        Session.Remove("ExcelTable");

        DataGrid1.DataSource = newDt;
        DataGrid1.DataBind();
    }
}


"Click" eventımız da hazır olduğuna göre projemizi çalışıtırıp uygulamamızı test edebilirsiniz.Umarım faydalı bir makale olmuştur.Bu makalemizde kullandığımız yöntem çok farklı şekiller de oracle uygulamarında kullanılabilir.Bundan ötürü, temel teşkil etmesi bakımından bence faydalı bir makale oldu bu yaptığımız işlemi bu kadar takla atmadan direk Store Procedur'e dizi tipinde parametre geçerek de yapabilirdik fakat bazı şeyleri daha detaylı öğrenmek için böyle bir uygulama yapmanın faydalı olacağını düşünüyorum.

Bir sonraki makalemde eğer fırsatım olursa Oracle'a nasıl dizi tipin'de parametre geçilir bundan bahsedeceğim.

Herkese kolay gelsin.

1 yorum: