Kolumne XAML Expertise: WPF und Windows-Apps

XAML-Tipp: WPF – Export von DataGrid zu Excel
Kommentare

In der Kolumne „XAML Expertise“ präsentiert Gregor Biswanger Top-How-tos zum Thema XAML. Einsteiger und Fortgeschrittene XAML-Experten sollen hier durch geballtes Wissen gesättigt werden. Heute gibt es folgende Expertise: „WPF: Export von DataGrid zu Excel“.

Obwohl Microsoft durch moderne Designrichtlinien davon abrät, das DataGrid-Steuerelement zu nutzen, hat dieses bis heute in zahlreichen Geschäftsanwendungen überlebt. Diese Designempfehlung war übrigens auch der Grund, weshalb WPF zuerst kein solches Steuerelement zur Verfügung stellte. Ab Silverlight 2 wurde es sofort wieder eingeführt, sodass bei der nächsten WPF-Version ein DataGrid auch wieder mit an Bord der Standardsteuerelemente war. Dieser Kundenwunsch ist nicht ohne Grund aufgekommen, denn sie sind durch Excel gewohnt, täglich mit Tabellen zu arbeiten. Ebenfalls wird gewünscht, aus der Geschäftsanwendung eine Excel-Datei zu exportieren. Zum Glück ist das auch mit nur wenigen Zeilen Code ohne Probleme möglich.

Export von DataGrid zu Excel

Als Erstes wird eine Assembly-Referenz der Microsoft Excel Object Library benötigt. Diese findet man beim Reference Manager im COM-Abschnitt (Abb. 1). Danach wird eine neue Klasse, wie beispielsweise der ExcelExporter, erzeugt. Der passende Code zum Generieren einer Excel-Datei steht in Listing 1, und wie diese verwendet wird, kann in Listing 2 nachgelesen werden.

Abb. 1: Die Microsoft Excel Object Library referenzieren

Abb. 1: Die Microsoft Excel Object Library referenzieren

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;

namespace WpfDataGridToExcel
{
  public class ExcelExporter
  {
    private Microsoft.Office.Interop.Excel.Application _excel;
    private Microsoft.Office.Interop.Excel.Workbook _workbook;
    private Microsoft.Office.Interop.Excel.Worksheet _worksheet;
    private Microsoft.Office.Interop.Excel.Range _cellRange;

    public void Generate(IList data, string worksheetName, string pathWithFilename)
    {
      System.Data.DataTable dataTable = ToDataTable(data);

      _excel = new Microsoft.Office.Interop.Excel.Application
      {
        DisplayAlerts = false,
        Visible = false
      };

      _workbook = _excel.Workbooks.Add(Type.Missing);
      _worksheet = (Microsoft.Office.Interop.Excel.Worksheet) _workbook.ActiveSheet;
      _worksheet.Name = worksheetName;
      int rowcount = 1;

      for (int i = 1; i <= dataTable.Columns.Count; i++)
      {
        _worksheet.Cells[1, i] = dataTable.Columns[i - 1].ColumnName;
      }

      foreach (System.Data.DataRow row in dataTable.Rows)
      {
        rowcount += 1;
        for (int i = 0; i < dataTable.Columns.Count; i++)
        {
          _worksheet.Cells[rowcount, i + 1] = row[i].ToString();
        }
      }

      _cellRange = _worksheet.Range[_worksheet.Cells[1, 1], _worksheet.Cells[rowcount, dataTable.Columns.Count]];
      _cellRange.EntireColumn.AutoFit();

      _workbook.SaveAs(pathWithFilename);
      _workbook.Close();
      _excel.Quit();
    }

    private System.Data.DataTable ToDataTable(IList data)
    {
      PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
      DataTable dataTable = new DataTable();
      foreach (PropertyDescriptor prop in properties)
      {
        dataTable.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
      }

      foreach (T item in data)
      {
        DataRow row = dataTable.NewRow();
        foreach (PropertyDescriptor pdt in properties)
        {
          row[pdt.Name] = pdt.GetValue(item) ?? DBNull.Value;
        }
        dataTable.Rows.Add(row);
      }
      return dataTable;
    }
  }
}

Die Microsoft Excel Object Library ermöglicht den Zugriff auf Excel über die COM-Schnittstelle. Für die Lösung wird also Excel unsichtbar im Hintergrund geöffnet. Dann wird aus der Liste der Daten, die mit dem DataGrid verbunden sind, ein DataTable-Objekt erzeugt. Das ermöglicht ein Abbilden der Daten in Spalten und Zeilen. Innerhalb der Excel-Instanz wird auf das aktive Workbook zugegriffen, das per Standard ein Worksheet beinhaltet. Dieses wird dann durch Schleifen des DataTable-Objekts befüllt – erst die Spalten und dann die Zeilen. Ganz am Ende wird die Datei abgespeichert und Excel beendet. Wichtig beim Abspeichern ist der Pfad, denn dieser benötigt einen absoluten Pfad und den Namen der Datei. Die Angabe einer Dateiendung ist nicht notwendig.

private void OnButtonClick(object sender, RoutedEventArgs e)
{
  var items = new List((IEnumerable) dataGrid.ItemsSource);
  string pathWithFilename = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "MyExcel");

  var excelExporter = new ExcelExporter();
  excelExporter.Generate(items, "My Worksheet", pathWithFilename);

  MessageBox.Show("Excel-Datei wurde erfolgreich erzeugt", "Excel-Datei generiert");
}
Abb. 2: Erzeugte Excel-Datei aus dem „DataGrid“

Abb. 2: Erzeugte Excel-Datei aus dem „DataGrid“

Windows Developer

Windows DeveloperDieser Artikel ist im Windows Developer erschienen. Windows Developer informiert umfassend und herstellerneutral über neue Trends und Möglichkeiten der Software- und Systementwicklung rund um Microsoft-Technologien.

Natürlich können Sie den Windows Developer über den entwickler.kiosk auch digital im Browser oder auf Ihren Android- und iOS-Devices lesen. In unserem Shop ist der Windows Developer ferner im Abonnement oder als Einzelheft erhältlich.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -