Kadir Özdemir

  • Ben Kimim
  • PHP
  • Sencha Touch
  • Home/
  • C# /
  • C# .COM bileseniyle Excel export

C# .COM bileseniyle Excel export

Skorp 14.07.2011 8 Comments

Bugün son günlerde urastigim birseyi sizlerle paylasmak istiyorum.
Datagridview dan Excel e veri export etmem gerekiyordu, bunun icin hemen bir Library aradim, FF de arkadasin birisi sagolsun yardimci olmaya calisti.
Ben vermis oldugu linkten NPOI kütüphanesini kesfettim ve kullanmaya basladim.
Ama Iki gün önce farkettimki 10 000 satir lik bir export haddinden fazla (>10 dk) sürüyordu. Halbuki yapilacak olan export nice 10 000 leri yapa bilmeli.
Devam arastirdim bizim servere disaridan erisim kapali sadece Citrix icinden calisiyor ve üstünde Excel bulunuyordu, bende .COM bilesenlerini kullanmaya karar verdim.
Yeni bir test yapip en basit haliyle söyle bir kod olusturdum.

private void btn_export_Click(object sender, EventArgs e) {
    Excel.Application xlApp;
    Excel.Workbook xlWorkBook;
    Excel.Worksheet xlWorkSheet;
    object misValue = System.Reflection.Missing.Value;

    xlApp = new Excel.Application();
    xlApp.ScreenUpdating = false;
    xlApp.Calculation = Excel.XlCalculation.xlCalculationManual;
    xlWorkBook = xlApp.Workbooks.Add(misValue);
    xlWorkSheet = (Excel.Worksheet)xlWorkBook.Worksheets.get_Item(1);
    int ix = 0;
    int j = 0;
    //datagridview un baslik sütunünü ekliyelim
    for (int x = 0; x < dgv_search_result.Columns.Count; x++)
    {
        xlWorkSheet.Cells[1, x + 1] = dgv_search_result.Columns[x].HeaderText;
    }
    //basliklari kalin yazalim ve yaziyi ortaliyalim
    xlWorkSheet.get_Range("A1", "T1").Font.Bold = true;
    xlWorkSheet.get_Range("A1", "T1").VerticalAlignment = Excel.XlVAlign.xlVAlignCenter;
    //ardindan Datagridview daki satirlari excel dosyamiza yazalim
    for (ix = 1; ix <= rowcount; ix++) {
       for (j = 0; j <= dgv_search_result.ColumnCount - 1; j++){
          DataGridViewCell cell = dgv_search_result[j, ix - 1];
          //10. sutünü Text olarak formatliyalim
          if(j==10)
             xlWorkSheet.Cells[ix + 1, j + 1].NumberFormat = "@";
          xlWorkSheet.Cells[ix + 1, j + 1] = cell.Value;
         }
     }
                                                 
     //kayit edelim
      xlWorkBook.SaveAs(extraction_export.FileName, Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue);
      xlWorkBook.Close(true, misValue, misValue);
       xlApp.Quit();
     //objeleri yok edelim
      releaseObject(xlWorkSheet);
      releaseObject(xlWorkBook);
      releaseObject(xlApp);
}
private void releaseObject(object obj){
   try
   {
      System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
      obj = null;
   }
   catch (Exception ex)
   {
       obj = null;
       MessageBox.Show("Hata olustu " + ex.ToString());
   }
   finally
   {
        GC.Collect();
   }
 }


Bu Npoi yönteminden cok daha hizliydi ama yinede yeterince hizli degildi 10 dk dan fazla sürmesede en az 5 dk sürüyordu 10 000 satir icin.

Bunu dahada hizlandirmam gerekiyordu, Öncelikle yukarki kodda her satiri tek tek ekledigimizden bir güc kaybediyorduk bunu degistirmek icin aramalara girdim.
Ardindan hepsini bir objeye kaydedip birden eklemenin daha dogru olacagini okudum.

Hemen uyguladim söyle bir kod cikti ortaya

private void btn_export_Click(object sender, EventArgs e)
{
    Excel.Application xlApp;
    Excel.Workbook xlWorkBook;
    Excel.Worksheet xlWorkSheet;
    Excel.Sheets excelSheet;
    Excel.Workbooks excelWorkBooks;
    object misValue = System.Reflection.Missing.Value;

    xlApp = new Excel.Application();
    excelWorkBooks = xlApp.Workbooks;
    xlWorkBook = excelWorkBooks.Add(misValue);
    excelSheet = xlWorkBook.Worksheets;
    xlWorkSheet = (Excel.Worksheet)excelSheet.get_Item(1);

    var data = new object[rowcount, columncount];

    //basliklari ekliyelim 
    for (int x = 0; x < columncount; x++){
        data[0, x] = dgv_search_result.Columns[x].HeaderText;
    }
    //basliklari kalin ve sutünun ortasina pozisyonliyalim
    var boldformat = xlWorkSheet.get_Range("A1", "T1");
    var m_objfont = boldformat.Font;
    m_objfont.Bold = true;

    var verformat = xlWorkSheet.get_Range("A1", "T1");
    verformat.VerticalAlignment = Excel.XlVAlign.xlVAlignCenter;

    //satirlari objemize ekliyelim
    for (var row = 1; row < rowcount; row++){
        for (var column = 1; column <= columncount; column++){
            data[row , column - 1] = dgv_search_result.Rows[row - 1].Cells[column - 1].Value.ToString();
        }
     }
     
     //K sütünün Text olarak formatliyalim 
     string endcelltelephone = "K" + rowcount.ToString();
     var writeFormat = xlWorkSheet.get_Range("K1", endcelltelephone);
     writeFormat.NumberFormat = "@";

     //Objeyi ekliyecegimiz Range i belirliyelim
     string endcell = "T" + rowcount.ToString();
     var writeR = xlWorkSheet.get_Range("A1", endcell);
     //objeyi hazirladigimiz range e ekliyelim
     writeR.Value2 = data;
    //kayit edelim
    xlWorkBook.SaveAs(extraction_export.FileName, Excel.XlFileFormat.xlWorkbookNormal, misValue, misValue, misValue, misValue, Excel.XlSaveAsAccessMode.xlExclusive, misValue, misValue, misValue, misValue, misValue);
    data = null;
    xlWorkBook.Close(false, misValue, misValue);
    excelWorkBooks.Close();
    xlApp.Quit();
   
    //objeleri yok edelim
    System.Runtime.InteropServices.Marshal.ReleaseComObject(verformat);
    System.Runtime.InteropServices.Marshal.ReleaseComObject(boldformat);
    System.Runtime.InteropServices.Marshal.ReleaseComObject(m_objfont);
    System.Runtime.InteropServices.Marshal.ReleaseComObject(writeFormat);
    System.Runtime.InteropServices.Marshal.ReleaseComObject(writeR);
    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkSheet);
    System.Runtime.InteropServices.Marshal.ReleaseComObject(excelSheet);
    System.Runtime.InteropServices.Marshal.ReleaseComObject(excelWorkBooks);
    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkBook);
    System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
    verformat = null;
    boldformat = null;
    m_objfont = null;
    writeR = null;
    writeFormat = null;
    xlWorkSheet = null;
    excelSheet = null;
    excelWorkBooks = null;
    xlWorkBook = null;
    xlApp = null;
                            
    //GC calistiralim
    GC.GetTotalMemory(false);  
    GC.Collect();  
    GC.WaitForPendingFinalizers();  
    GC.Collect();  
    GC.GetTotalMemory(true); 
}

bu yöntem ile 10 000 satiri 10 saniye den az bi zamanda export ede biliyoruz.
Simdi dikkat edilmesi gereken seyleri yazmak istiyorum arkadaslar.
Öncelikle .COM bilesenini kullanmak istiyorsaniz Programi kullandiginiz makinada Excel kurulu olmalidir.
Projenin References bölümünden “Add Reference” e tiklayarak Reference ekleme penceresini aciyoruz. COM sekmesinde sunucuda kayitli Com bilesenlerine ulasa bilirsiniz biz Microsoft Excel 12.0 Object Library yi projemize ekliyoruz. (12 sizde degisik ola bilir, bende Excel 2007 var ondan 12 )
Projemizin basina

using Excel = Microsoft.Office.Interop.Excel;

yaziyoruz.

Ve son olarak ögrenmis oldugum en önemli seylerden birtanesini sizlerle paylasmak istiyorum.

Never use 2 dots with COM objects:

Ben yukarki kodda Excel in kayit ettikden sonra kapanmamasi ve üretilen Excel dosyasinin ici bos görünmesi sorununu yasiyorudm.
Bunu asmanin tek yolu yukardaki kural a uymakdir.

Örnek vermek gerekirse

xlWorkSheet.get_Range("A1", "T1").Font.Bold = true;

bu sekil iken excel kapanmiyor ve ben cildiriyordum. bu satiri böyle düzeltince ve diger satirlarida düzenleyince sorunlar kalkti.

var boldformat = xlWorkSheet.get_Range("A1", "T1");
var m_objfont = boldformat.Font;
m_objfont.Bold = true;

gördügünüz gibi tek satir icinde 2 (.) nokta kullanmadik.
Kodumuzun basindada normalde internet örneklerinde bulunan satirlardan fazla satir bulunmakda bunun tek sebebi o kuraldir.

Excel.Application xlApp;
Excel.Workbook xlWorkBook;
Excel.Worksheet xlWorkSheet;
Excel.Sheets excelSheet;
Excel.Workbooks excelWorkBooks;

umarim isinize yarar ve benim kadar aramak zorunda kalmassiniz.
Kolay gelsin

Skorp
2011-07-14
Tags:
C#
Share story:
← PreviousSilverstripe
Next →MSSQL snippetler

Written by Skorp

View all articles by Skorp

Website: http://www.skorp.eu

Related Articles

  • MSSQL birden fazla icerik eklemek

8 Comments

  1. KillExcel
    Eylül 28, 2011 at 12:08 pm

    Ellerine saglik, excel artik duzgun kapaniyor. Bir de ben soyle birsey buldum, excel objesi ile isim bittikten sonra asagidakini cagiriyorum. Ortalik dumduz oluyor, excel den eser kalmiyor.
    private static void KillExcel()
    {
    try
    {
    System.Diagnostics.Process[] PROC = System.Diagnostics.Process.GetProcessesByName(“EXCEL”);
    foreach (System.Diagnostics.Process PK in PROC)
    {
    //User excel process always have window name
    //COM process do not.
    if (PK.MainWindowTitle.Length == 0)
    PK.Kill();
    }
    }
    catch
    {
    throw;
    }
    }

  2. Skorp
    Eylül 30, 2011 at 11:53 am

    Window name li olan kismi bilmiyordum sagolasin ekledigin icin deniyecegim, process kill de sorun tüm excell process lerinin kapanmasiydi ondan kullanmamistim.

  3. metin
    Kasım 27, 2012 at 03:46 pm

    verileri bir excele yazdırdım diyelım..daha sonra aynı excele tekrar yazdırmak istiyorum yani aynı sayfa yeni sayfa oluşturmucak eskı verilerin yerine yenileri gelıcek .bunu nası yapabilirim. fikriniz varmı.

  4. Zafer YILMAZ
    Aralık 21, 2012 at 06:46 pm

    Merhaba. 46. satırdaki
    extraction_export.FileName
    ifadesi hata veriyor.

    The name ‘extraction_export’ does not exist in the current context

    hatasını veriyor.

  5. Skorp
    Aralık 21, 2012 at 07:11 pm

    o bana ait bir degisken, dosya ismi ile degise bilirsiniz.

  6. Zafer YILMAZ
    Aralık 22, 2012 at 09:07 pm

    dgv_search_result – Datagridview ile
    rowcount, columncount – Datagridview.rowcount,Datagridview. columncount ile
    extraction_export -SaveFileDialog1 ile değiştirdim.

    Aşağıdaki 48.satırda

    Message=Dosyaya erişilemedi. Aşağıdakilerden birini deneyin:

    • Belirtilen klasörün varolduğundan emin olun.
    • Dosyayı içeren klasörün salt okunur olmadığından emin olun.
    • Dosya adının aşağıdaki karakterlerden herhangi birini içermediğinden emin olun: ? [ ] : | ya da *
    • Dosya/yol adının 218 karakterden uzun olmadığından emin olun.
    Source=Microsoft Excel
    ErrorCode=-2146827284
    StackTrace:
    konum: Microsoft.Office.Interop.Excel._Workbook.SaveAs(Object Filename, Object FileFormat, Object Password, Object WriteResPassword, Object ReadOnlyRecommended, Object CreateBackup, XlSaveAsAccessMode AccessMode, Object ConflictResolution, Object AddToMru, Object TextCodepage, Object TextVisualLayout, Object Local)

    hatasını veriyor.

  7. özgür
    Mart 23, 2013 at 10:44 am

    Eski biçim veya geçersiz kitaplık türü. (HRESULT özel durum döndürdü: 0x80028018 (TYPE_E_INVDATAREAD))
    bu hatayı verıyor

  8. Skorp
    Mart 27, 2013 at 11:42 am

    suan deniyemiyorum ama surayi bi incele derim:
    http://stackoverflow.com/questions/5180713/old-format-or-invalid-type-library-exception-from-hresult-0x80028018-type-e

Leave a Comment Cancel Reply

Your email address will not be published. Required fields are marked *

Social networks

Etiket Bulutu

Android Bilgisayar & Internet C# Cms css diger Kodlar featured Genel Java Javascript Linux Mobile PHP Silverstripe typo3 Veritabani Windows Zend Framework

Links

  • H E R K O N U
  • Hüseyin Koyun
  • Urban23k

Son Yorumlar

  • Primary Key – Unique ve Index nedir? için Onur
  • Centos de apache, php ve mysql kurulumu için sezer fidancı
  • React Native – Kurulum için React Native | Kadir Özdemir
  • React Native için React Native – Kurulum | Kadir Özdemir
  • Ben Kimim için serkan

Twitter

Follow @skorp54
There is an error in twitter widget, please make sure that you have set up the Twitter API settings
  • Ben Kimim
  • PHP
  • Sencha Touch

Arsivler

Kategoriler

Copyright © 2014 webberz.at