Importowanie danych do Excel-a C#

Częstym zadaniem, na które natykam się w czasie pracy programisty .NET to integracja z Office-em. Typowym zastosowanie takiej integracji jest export lub import danych do plików Excela dla Pań z księgowości : )

Jednym z problemów podczas integracji jest szybkość importowania i eksportowania danych do z plików Excela.

Problem szybkości tworzenia plików Excel-a widać już przy wielkościach rzędu 1000 wierszy. Jedyną pomocą jest zmienić sposób obsługi integracji z Excelem.

Mam 4 sposoby tworzenia plików Excela (od najgorszych):

  • Można stworzyć plik CSV i zmienić mu nazwę na xls lub xlsx (okropne rozwiązanie)
  • Można zintegrować się za pomocą bibliotek COM Microsoft.Office.Interop.Excel (działa wolno przy większych ilościach oraz potrzeba zainstalowanego Office-a na produkcji i deweloperce)
  • Open XML SDK 2.5 (najprostszy i najszybszy pod względem nauki konfiguracji sposób komunikacji z Excelem)
  • Stworzenie czystego pliku, właściwie struktury OpenXML. (ten sposób preferuje. Wydajność jest znakomita. 153 000 wierszy w 4,5 sekundy.

Opisze ostatni sposób na podstawie biblioteki, którą nie dawno znalazłem na CodeProject.

Bibliotekę przetestowałem i działa produkcyjnie. Wszystkie kroki do jej uruchomienia, opisałem poniżej.

Kody do biblioteki są dostępna na github-ie. Należy je ściągnąć, przekompilować i dodać MyExcelExport.dll  do swojego projektu.

Efektem wykonaniu poniższych zadań będzie możliwość wczytania danych z DataTable  do pliku xlsx. Aplikacja będzie używać szablonu do określenia jakie dane mają być w jakiej kolumnie.

Najpierw tworzymy obiekt pomocniczy, który będzie wydawał kolejne wiersze.


 public class ExelData
    {
        private int currow;
        public DataTable ReportData { get; set; }

        private int MaxRow
        {
            get
            {
                return this.ReportData.Rows.Count;
            }
        }

        public object this[string name]
        {
            get
            {
                if (this.currow > this.ReportData.Rows.Count)
                {
                    return string.Empty;
                }

                if (!this.ReportData.Columns.Contains(name))
                {
                    return string.Empty;
                }

                return this.ReportData.Rows[this.currow - 1][name] + " ";
            }
        }

        public bool Read()
        {
            if (this.ReportData == null)
            {
                return false;
            }

            if (this.currow <= this.MaxRow)
            {
                this.currow++;
            }

            return this.currow <= this.MaxRow;
        }
    }

Klasa ma zadanie wydawać kolejne wiersze aż do momentu gdy nie dojdziemy do końca pliku. Zastosowany tu indekser dostaje na wejściu nazwę kolumny z szablonu. Na tej podstawie szuka wiersza używając pole „currow”.

Nazwa kolumny z szablonu jest tożsama z nazwami kolumn w obiekcie DataTable. To znaczy w szablonie wpisujemy nazwy kolumn z obiektu  DataTable.

szablonExcel

Powyżej przykład jak wypełnić szablon.

Następnie do projektu dodajemy dwie klasy( Extensions i ExcelWriter). Klasy te są gotowe i znajdują się w kodach źródłowych projektu w solucji MySample. Pamiętajmy o zmianie namespace-ów.

W klasie ExcelWriter należy zmienić typ argumentu metody „Export” na „ExelData” :

 public void Export(ExelData dataSource, string filename) 

oraz  zmienić typ pola „data” na

 ExelData data; 

W tym momencie rozwiązanie jest gotowe do uruchomienia. Oczywiście trzeba przygotować dane do DataTable oraz szablon.

Przykładowe wywołanie może wyglądać tak:

        public static void CreateFile(DataTable reportdata, string fileName, string excelTemplate)
        {
            var data = new ExelData
            {
                ReportData = reportdata
            };

            new ExcelWriter(excelTemplate).Export(data, fileName);
        }

Wszystkie dane z „DataTable” będą wstawone w docelowym pliku xlsx.

 

 

 

 

 

2 przemyślenia nt. „Importowanie danych do Excel-a C#

  1. Tworzenie excela za pomocą Interop wcale nie musi być wolne. Jeśli tworzymy document i zaczynamy wpisywać do niego rekordy wiersz po wierszu to owszem wydajność jest kiepska. Możnazrobić coś takiego:


    Excel.Range range = CreateRange(grid, ws);
    range.Value2 = arr;

    gdzier arr to dwuwymiarowa tablica obiektów.

    1. Dokladnie tak jak piszesz robilem i nie mialem zadawalajacych wynikow. Moze podejde do tematu raz jeszcze. Dzieki za info

Możliwość komentowania jest wyłączona.