Laden...

EXCEL Export Problem

Erstellt von romu2000 vor 15 Jahren Letzter Beitrag vor 13 Jahren 5.293 Views
R
romu2000 Themenstarter:in
291 Beiträge seit 2006
vor 15 Jahren
EXCEL Export Problem

Hallo zusammen,

ich versuche mich gerade an Rainbirds Excel export via oleDB.

Mein Problem ist, das mir das Snippet NUR die Spaltenüberschriften anzeigt, aber keinen Dateninhalt .... Hier mal kurz das Script, vllt. kann mir ja jemand sagen was ich hier falsch gemacht habe.:

'Ich vermute ja den Fehler evtl. beim deklarieren der Datatable. Habe aber keine Ahnung.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;

using System.Runtime.Remoting;
using System.Reflection;
using System.Runtime.InteropServices;

namespace Excel
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void bestellungenBindingNavigatorSaveItem_Click(object sender, EventArgs e)
        {
            this.Validate();
            this.bestellungenBindingSource.EndEdit();
            this.tableAdapterManager.UpdateAll(this.fDTEL_DE_SQL_2008DataSet);

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // TODO: Diese Codezeile lädt Daten in die Tabelle "fDTEL_DE_SQL_2008DataSet.Bestellungen". Sie können sie bei Bedarf verschieben oder entfernen.
            this.bestellungenTableAdapter.Fill(this.fDTEL_DE_SQL_2008DataSet.Bestellungen);

        }

        FDTEL_DE_SQL_2008DataSet.BestellungenDataTable bestell = new FDTEL_DE_SQL_2008DataSet.BestellungenDataTable();

        public class ExcelExport
        {
            /// <summary>
            /// Privater Standardkonstruktor.
            /// </summary>
            private ExcelExport() { }

            /// <summary>
            /// Schreibt das Schema einer bestimmten Tabelle in eine neue Excel-Datei.
            /// </summary>
            /// <param name="table">Tabelle</param>
            /// <param name="fileName">Dateiname</param>
            public static void WriteTableSchemaToExcelFile(DataTable table, string fileName)
            {
                // Excel im Hintergrund öffnen
                object excel = Activator.CreateInstance(Type.GetTypeFromProgID("Excel.Application"));

                // Auflistung der Mappeen abrufen
                object books = excel.GetType().InvokeMember("Workbooks", BindingFlags.IgnoreCase | BindingFlags.GetProperty | BindingFlags.OptionalParamBinding, null, excel, new object[0]);

                // Neue Mappe erstellen
                object book = books.GetType().InvokeMember("Add", BindingFlags.InvokeMethod | BindingFlags.OptionalParamBinding, null, books, new object[0]);

                // Auflistung der Tabellenblätter abrufen
                object sheets = book.GetType().InvokeMember("Sheets", BindingFlags.IgnoreCase | BindingFlags.GetProperty | BindingFlags.OptionalParamBinding, null, book, new object[0]);

                // Neues Tabellenblatt erstellen
                object sheet = sheets.GetType().InvokeMember("Add", BindingFlags.InvokeMethod | BindingFlags.OptionalParamBinding, null, sheets, new object[0]);

                // Name des Tabellenblatts festlegen
                sheet.GetType().InvokeMember("Name", BindingFlags.SetProperty, null, sheet, new object[1] { table.TableName });

                // Zähler
                int i = 0;

                // Spalten der Tabelle durchlaufen
                foreach (DataColumn column in table.Columns)
                {
                    // Zähler erhöhen
                    i++;

                    // Feldnamen einfügen
                    object range = sheet.GetType().InvokeMember("Cells", BindingFlags.GetProperty | BindingFlags.OptionalParamBinding, null, sheet, new object[2] { 1, i });
                    range.GetType().InvokeMember("Value", BindingFlags.SetProperty | BindingFlags.OptionalParamBinding, null, range, new object[1] { column.ColumnName });
                }

                // Dokument speichern
                book.GetType().InvokeMember("SaveAs", BindingFlags.InvokeMethod | BindingFlags.OptionalParamBinding, null, book, new object[1] { fileName });

                // COM-Verweise freigeben
                Marshal.ReleaseComObject(sheet);
                Marshal.ReleaseComObject(sheets);
                Marshal.ReleaseComObject(book);
                Marshal.ReleaseComObject(books);

                // Excel schließen
                excel.GetType().InvokeMember("Quit", BindingFlags.InvokeMethod, null, excel, new object[0]);

                // Excel.Application COM-Verweis freigeben
                Marshal.ReleaseComObject(excel);
            }

            /// <summary>
            /// Erzeugt eine OLEDB-Verbindungszeichenfolge für ein bestimmtes Excel-Dokument.
            /// </summary>
            /// <param name="fileName">Dateiname (.XLS)</param>
            /// <returns>Verbindungszeichenfolge</returns>
            private static string BuidExcelConnectionString(string fileName)
            {
                // Verbindungszeichenfolge erzeugen un zurückgeben
                return "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + fileName + ";Extended Properties=Excel 8.0";
            }

            /// <summary>
            /// Erzeugt aus einer Tabelle ein Excel-Dokument.
            /// </summary>
            /// <param name="table">Tabelle</param>
            /// <param name="fileName">Dateiname des Ziel-Excel-Dokuments</param>
            public static void FillExcelSheet(DataTable table, string fileName)
            {
                // Neue leere Excel-Datei aus dem Tabellenschema erzeugen
                WriteTableSchemaToExcelFile(table, fileName);

                // Verbindungszeichenfolge erzeugen
                string connectionString = BuidExcelConnectionString(fileName);

                // Neue OLEDB-Verbindung erzeugen
                OleDbConnection connection = new OleDbConnection(connectionString);
                connection.Open();

                // String-Generator für Parameter erzeugen
                StringBuilder parameterBuilder = new StringBuilder(") VALUES (");

                // Spalten zählen
                int columnCount = table.Columns.Count;

                // INSERT SQL-Anweisung für Excel erzeugen
                StringBuilder builder = new StringBuilder("INSERT INTO [");
                builder.Append(table.TableName);
                builder.Append("$] (");

                // Alle Spalten durchlaufen
                for (int i = 0; i < columnCount; i++)
                {
                    // Spaltennamen anfügen
                    builder.Append(table.Columns[i].ColumnName);

                    // Parameter anfügen
                    parameterBuilder.Append("?");

                    // Wenn eine weitere Spalte folgt ...
                    if (i < (columnCount - 1))
                    {
                        // Kommas anfügen
                        builder.Append(",");
                        parameterBuilder.Append(",");
                    }
                }
                // SQL-Anweisung fertigstellen
                builder.Append(parameterBuilder.ToString());
                builder.Append(")");
                string insertStatement = builder.ToString();

                // Preisliste durchlaufen
                foreach (DataRow row in table.Rows)
                {
                    // Neuen OLEDB-Befehl erzeugen
                    OleDbCommand command = new OleDbCommand(insertStatement, connection);

                    // Alle Spalten durchlaufen
                    foreach (DataColumn column in table.Columns)
                    {
                        // Parameter übergeben                    
                        command.Parameters.Add(new OleDbParameter(column.ColumnName, row[column]));
                    }
                    // Befehl ausführen
                    command.ExecuteNonQuery();
                }
                // Verbindung schließen
                connection.Close();
            }
        }
        private void button1_Click(object sender, EventArgs e)
        {
           ExcelExport.WriteTableSchemaToExcelFile(bestell, "C:\\TEST2.XLS");
            ExcelExport.FillExcelSheet(bestell, "C:\\TEST2.XLS");
            
        }
    }
}

Viele Grüße

Ronny

3.728 Beiträge seit 2005
vor 15 Jahren
Doppelter Aufruf

Hallo romu2000,

WriteTableSchemaToExcelFile wird bereits implizit durch FillExcelSheet aufgerufen. Deshalb verschluckt er sich wahrscheinlich daran. Probleme kann es auch geben, wenn Spaltennamen der DataTable Leer- oder Sonderzeichen enthalten.


private void button1_Click(object sender, EventArgs e)
{
    // Falsch (wird implizit aufgerufen): ExcelExport.WriteTableSchemaToExcelFile(bestell, "C:\\TEST2.XLS");
    
    // Excel-Export ausführen
    ExcelExport.FillExcelSheet(bestell, "C:\\TEST2.XLS");
}

OLEDB ist manchmal etwas empfindlich. Wesentlich robuster ist folgende Lösung: Excel-Export ohne Excel (Snippet)
Läuft allerdings erst ab Excel 2003 oder höher und erzeugt XML-Dateien statt XLS-Dateien.

C
54 Beiträge seit 2007
vor 15 Jahren

Hallo,

habe gerade versucht deine Klasse bei mir einzubauen.

Bekomme in Methode "FillExcelSheet" immer einen Fehler und zwar wenn er die Excel-Tabelle füllen will.


				// durchlaufen
				foreach (DataRow row in table.Rows)
				{
					// Neuen OLEDB-Befehl erzeugen
					OleDbCommand command = new OleDbCommand(insertStatement, connection);

					// Alle Spalten durchlaufen
					foreach(DataColumn column in table.Columns)
					{
						// Parameter übergeben                    
						command.Parameters.Add(new OleDbParameter(column.ColumnName,row[column]));
					}
					// Befehl ausführen
					command.ExecuteNonQuery();
				}

Er läuft hier nur einmal durch die obere Schleife und dann bricht er ab.
Die Spaltennamen werden im ersten Schleifendurchlauf in Excel gesetzt und dann kommt der Abbruch mit "Ungültiger Tabellennamen".

Das DataTable habe ich mit einem SQL-String gefüllt.

Benutze VS 2003.

C
54 Beiträge seit 2007
vor 15 Jahren

Habe mir den Code nochmals angeschaut und durch den Kopf gehen lassen.

Ist natürlich alles mist was ich in meinem Beitrag geschrieben habe.

Eine frage habe trotzdem.

// INSERT SQL-Anweisung für Excel erzeugen
StringBuilder builder = new StringBuilder("INSERT INTO [");
builder.Append(table.TableName);

wohin schreibt er den Insert?

Das DataTable habe ich mit einem SQL-String gefüllt welches mehrere Tabellen beinhaltet.

G
26 Beiträge seit 2009
vor 13 Jahren

Hallo,

das Thema ist zwar schon etwas älter aber ich habe eine kleine Frage.
Ich benutze Excel 2010 und bekomme einen Fehler nach der Schleife die mir den Sql Insert Befehl zusammensetzt.

Meldung bei ExecuteNonQuery();

"Das Microsoft Jet-Datenbankmodul konnte das Objekt '$' nicht finden. Stellen Sie sicher, dass das Objekt existiert und dass die Namens- und Pfadangaben richtig eingegeben wurden."

ich habe auch schon "$Tabelle4" oder "Tabelle4" als Table.TableName vergeben. dann steht an der stelle wo das Dollar steht halt der andere String.
Die Überschriften werden normal erzeugt und die Datei wird auch gespeichert.
Ich denke mal das die Parameter in der Foreach Schleife nicht gefüllt werden.