Der Zugriff auf Excel-Dateien und -Funktionen mit C# ist eigentlich recht einfach. Zunächst muss ein Verweis auf die COM-Bibliothek Microsoft Excel 11.0 Object Library hinzugefügt und dann noch der entsprechende Namespace inkludiert werden mittels:
using Microsoft.Office.Interop.Excel;
Änderungen bei Excel 2007: Es muss die COM-Bibliothek Microsoft Excel 12.0 Object Library verwendet werden.
Änderungen bei Excel 2010: Es muss die COM-Bibliothek Microsoft Excel 14.0 Object Library verwendet werden.
Dann kann man munter drauflos programmieren, vielleicht wie folgt:
// benötigte Objekte vorbereiten
Microsoft.Office.Interop.Excel.Application excel = null;
Workbook wb = null;
try
{
// Excel starten
excel = new Microsoft.Office.Interop.Excel.Application();
excel.Visible = false;
// Datei öffnen
wb = excel.Workbooks.Open(
@"C:\test.xlsx",
ExcelKonstanten.UpdateLinks.DontUpdate,
ExcelKonstanten.ReadOnly,
ExcelKonstanten.Format.Nothing,
"", // Passwort
"", // WriteResPasswort
ExcelKonstanten.IgnoreReadOnlyRecommended,
XlPlatform.xlWindows,
"", // Trennzeichen
ExcelKonstanten.Editable,
ExcelKonstanten.DontNotifiy,
ExcelKonstanten.Converter.Default,
ExcelKonstanten.DontAddToMru,
ExcelKonstanten.Local,
ExcelKonstanten.CorruptLoad.NormalLoad);
// Arbeitsblätter lesen
Sheets sheets = wb.Worksheets;
// ein Arbeitsblatt auswählen...
Worksheet ws = (Worksheet)sheets.get_Item("Tabelle1");
// ...oder eine Zelle
Range range = (Range)ws.get_Range("A1", "A1");
// deren Wert auslesen
string zellwert = range.Value2.ToString();
Console.WriteLine(zellwert);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
finally
{
wb.Close(false, null, null);
excel.Quit();
}
Ich habe mir der Einfachheit halber die Werte, die als Parameter für die Methode Worbook.Workbooks.Open benötigt werden, in eine kleine Hilfsklasse geschrieben. Die Werte habe ich von der Microsoft-Seite.
/// <summary>
/// Diese Klasse enthält alle Konstanten, die beim Zugriff auf Excel
/// benötigt werden. Die Beschreibungen sind von Microsoft übernommen
/// und daher noch auf Englisch.
/// </summary>
private static class ExcelKonstanten
{
/// <summary>
/// Specifies the way links in the file are updated. If this
/// argument is omitted, the user is prompted to specify how
/// links will be updated. Otherwise, this argument is one of
/// the values listed in the following table.
/// </summary>
public enum UpdateLinks
{
DontUpdate = 0,
ExternalOnly = 1,
RemoteOnly = 2,
ExternalAndRemote = 3
};
/// <summary>
/// True to open the workbook in read-only mode.
/// </summary>
public const bool ReadOnly = true;
public const bool ReadWrite = false;
/// <summary>
/// If Microsoft Excel is opening a text file, this argument
/// specifies the delimiter character, as shown in the following
/// table. If this argument is omitted, the current delimiter
/// is used.
/// </summary>
public enum Format
{
Tabs = 1,
Commas = 2,
Spaces = 3,
Semicolons = 4,
Nothing = 5,
CustomCharacter = 6
};
/// <summary>
/// True to have Microsoft Excel not display the read-only
/// recommended message (if the workbook was saved with the
/// Read-Only Recommended option).
/// </summary>
public const bool IgnoreReadOnlyRecommended = true;
public const bool DontIgnoreReadOnlyRecommended = false;
/// <summary>
/// If the file is a Microsoft Excel 4.0 add-in, this argument
/// is True to open the add-in so that its a visible window.
/// If this argument is False or omitted, the add-in is opened
/// as hidden, and it cannot be unhidden. This option doesn't
/// apply to add-ins created in Microsoft Excel 5.0 or later.
/// If the file is an Excel template, True to open the specified
/// template for editing. False to open a new workbook based on
/// the specified template. The default value is False.
/// </summary>
public const bool Editable = true;
public const bool NotEditable = false;
/// <summary>
/// If the file cannot be opened in read/write mode, this
/// argument is True to add the file to the file notification
/// list. Microsoft Excel will open the file as read-only, poll
/// the file notification list, and then notify the user when
/// the file becomes available. If this argument is False or
/// omitted, no notification is requested, and any attempts to
/// open an unavailable file will fail.
/// </summary>
public const bool Notify = true;
public const bool DontNotifiy = false;
/// <summary>
/// The index of the first file converter to try when opening
/// the file. The specified file converter is tried first; if
/// this converter doesnt recognize the file, all other converters
/// are tried. The converter index consists of the row numbers
/// of the converters returned by the FileConverters property.
/// </summary>
public enum Converter
{
Default = 0
};
/// <summary>
/// True to add this workbook to the list of recently used files.
/// The default value is False.
/// </summary>
public const bool AddToMru = true;
public const bool DontAddToMru = false;
/// <summary>
/// True saves files against the language of Microsoft Excel
/// (including control panel settings). False (default) saves
/// files against the language of Visual Basic for Applications
/// (VBA) (which is typically US English unless the VBA project
/// where Workbooks.Open is run from is an old internationalized
/// XL5/95 VBA project).
/// </summary>
public const bool Local = true;
public const bool NotLocal = false;
public enum CorruptLoad
{
NormalLoad = 0,
RepairFile = 1,
ExtractData = 2
};
}
Wiso kann man das den zweiten Codeteil nicht kopieren??
Ansonsten gut:)
Grüsse
Also ich kann alles kopieren!?
Ich kann den zweiten Teil mit der Maus nicht mal markieren…Benutze IE 6.0
Super! funktioniert alles…
bis, dass beim Aufruf nicht das gewünschte Blatt aufgerufen wird.
ist doch in dieser funktion: //Ein Arbeitsblatt auswählen
habe es bei mir aber richtig angepasst!
Funkrioniert dieser version??:S
Die Funktion nutze ich seit längerer Zeit wie oben abgebildet. Bau doch mal ein try-catch drum und schau, was das genaue Problem ist…
Da ich mitbekommen habe, dass hier jemand Ahnung hatte, hoffe ich das du noch diesen Beitrag liest obwohl der Thread schon alt ist … aber was mache ich falsch wenn ich diese Fehlermeldung bekomme.
Error: Das COM-Objekt des Typs “Microsoft.Office.Interop.Excel.WorkbookClass” kann nicht in den Schnittstellentyp “Microsoft.Office.Interop.Excel.Workbooks” umgewandelt werden. Dieser Vorgang konnte nicht durchgeführt werden, da der QueryInterface-Aufruf an die COM-Komponente für die Schnittstelle mit der IID “{000208DB-0000-0000-C000-000000000046}” aufgrund des folgenden Fehlers nicht durchgeführt werden konnte: Schnittstelle nicht unterstützt (Ausnahme von HRESULT: 0x80004002 (E_NOINTERFACE)). Line: WindowsFormsApplication2
Danke für die Hilfe
selber Fehler wie Matthias… auch mit der msdn-website-anleitung…
Hast du den oben angegebenen Quellcode wirklich 1:1 verwendet?
Hallo Hannes.
Ich habe den Code aus meinem lauffähigen Programm kopiert. Hast du alle Verweise eingefügt? Bei mir läuft’s mit Excel 2003…
Hallo,
in welcher Form muss ich denn den Pfad und den Dateinamen eingeben?
Z.B. wenn ich das C#-Projekt unter
c:\csharp\projekt1
gespeichert habe und meine Datei liegt auf
c:\eigenedateien\mappe1.xls
Wenn ich an Stelle von
this.dateiname
folgendes eingebe:
c:\eigenedateien\mappe1.xls
dann funktioniert das nicht.
Fehlermeldung: Unerwartetes Zeichen “\”.
Auch mit Anführungsstrichen (” bzw. ‘) funktioniert das nicht.
Fehlermeldung: Nicht erkannte Escapesequenz
@Andy: Du musst natürlich die Backslashes escapen. Entweder separat oder gleich ein “@” vor den String: "c:\\eigenedateien\\mappe1.xls" oder @"c:\eigenedateien\mappe1.xls".
Hallo,
ich bekomme beim Aufruf von
Sheets sheets = wb.Worksheets;
stets den Fehler
Eine Ausnahme (erste Chance) bei 0x7c812aeb in KppSAPServer.exe: 0x80010108: Das aufgerufene Objekt wurde von den Clients getrennt.
@Andreas: Dazu kann ich dir leider nichts sagen. Du wirst wohl mal den Debugger anschmeißen müssen 🙁
@stefan: Gut, dass ich ab übermorgen Urlaub hab. Ich habe den Code in eine Methode ausgelagert und übersehen, dass das Excel im finally block geschlossen wird ;-(. Dein Code funktioniert problemlos.
Hey, danke, das hat mir sehr geholfen, funktioniert!
Thx
Pingback:Excel Zellen schreiben (Problem) - .NET Datenverwaltung @ tutorials.de: Forum, Tutorial, Anleitung, Schulung & Hilfe
Hallo,
Gut geht das auch mittels XML :
http://www.ploetzeneder.eu/softwareentwicklung/cvbnet/38-datagridview-in-excel-exportieren.html
Hallo,
super Sache das Snippet, nur leider bricht er bei mir beim Open schon ab. An was kann das liegen? dateiname und Excel ist offen.
gruß
steffen
@Steffen: Da wäre jetzt eine Fehlermeldung hilfreich. Irgendeine Exception oder so!?
A first chance exception of type 'System.Runtime.InteropServices.COMException' occurred in SharePointCleanupTool2.exe
Das ist die Fehlermeldung
A first chance exception of type ‘System.Runtime.InteropServices.COMException’ occurred in SharePointCleanupTool2.exe
Das ist die Fehlermeldung
Vielen Dank.
Du hast allen Usern im Web einen schönen Einstieg in die Automatisierung von Excel gegeben.
@Michael: Danke! Freut mich, dass es jemand brauchen kann 🙂
@Stefan: Ich fand Deinen Beitrag sehr hilfreich. Bin dabei eine Excel 2007-Anwendung (Fahrtenbuch für mein Motorrad) mittels Visual C# 2008 zu automatisieren und suche mit Hilfe einer 0)> -Schleife die erste leere Zeile unten in meiner Tabelle zum Einfügen neuer Daten (Datum, km-Stand, Tankstelle, Liter, Kosten). Dazu muss ich unbedingt eine neue Zeile einfügen, da noch weiter unten Zellen belegt sind. Wie schaffe ich das in meinem C#-Programm?
@Jürgen: Probier’s doch mal hiermit:
@Stefan: Bedanke mich für die Antwort. Ich versuche bei Reihe 191 eine
neue Zeile in meine Excel-Tabelle mit C#, Visual Studio 2008 Express
einzufügen. Das Ergebnis war wie folgt:
oSheet.Range(“A191”).EntireRow.Insert(xlShiftDown);
Fehler 1 Die Eigenschaft, der Indexer oder das Ereignis “Range” wird von der Sprache nicht unterstützt. Rufen Sie die Microsoft.Office.Interop.Excel._Worksheet.get_Range(object, object)-Accessormethode direkt auf.
Fehler 2 Der Name “xlShiftDown” ist im aktuellen Kontext nicht vorhanden.
Ich habe es auch analog zu VBA für Excel versucht:
ActiveSheet.Rows(191).Insert
bekomme dann aber die Fehlermeldung, dass Rows keine Methode ist.
Ich bin schon fast verzweifelt, finde kaum Doku oder Buch zum Thema
C# und Excel-Automatisierung.
Jürgen
@Stefan: Du hast mich mit “EntireRow.Insert” auf die richtige Spur gebracht.
Folgende zwei Zeilen funktionieren tatsächlich bei mir:
oRng = oSheet.get_Range(“A191”, Missing.Value);
oRng.EntireRow.Insert(Excel.XlInsertShiftDirection.xlShiftDown, false);
wo oRng ein Range Objekt ist. Abenteuerlich, nicht wahr?
Trotzdem habe ich noch immer keine vernünftige Doku zum Thema: “Automation von Excel mittels C# Programme” gefunden und tappt man mehr oder weniger im Dunkeln. Zu diesem Thema scheint es auch keine
Bücher zu geben! Sonst wird man doch zugemüllt mit Titeln wie:
Einstieg in ….. Schritt für Schritt usw.. VBA und Excel – jede Menge.
C# und Excel – nichts.
Jürgen
Danke der Code war sehr hilfreich 😀
mfg
dom
Hallo,
ich habe den Code 1 zu 1 übernommen doch es funktioniert bei mir leider nicht. Ich bekomme zwar keine Fehlermeldung, doch das Programm macht bei mir scheinbar garnix.
System:
Visual Studio 2008
Excel 2007
Ich lege eine “Windows Form application” an und kopiere beide Codeteile in dieselbe Datei. Dann mache ich noch einen Button “button 1”. Das Form kommt auch, aber wenn ich auf den Button drücke passiert leider garnichts. Kann mir jemand weiterhelfen ?
@Murat: Der obige Code ist nicht 1-zu-1 lauffähig. Du musst schon noch ein Gerüst drumherum bauen…
Hallo,
bei mir läuft der Code.
Nun mein Problem: Ich möchte ein Macro ausführen daas in dem Excelsheet in einem Modul ist. Wie kann ich dieses Macro aufrufen?
Gruß
M
@MK: Sorry, das weiß ich leider nicht…
Hier ist einige Info um Excel auch ohne com zu schreiben/
einzulesen: http://www.schonebeck.net/?p=127
Hallo zusammen
ich bin auf VS2010 umgestiegen. Verwende aber noch office2003.
Wenn ich meine solution baue, kommt die meldung das die Office Assembly nicht passt. Ich lade mir die PIO2003 runter und installiere diese. Ich binde den Verweis (V12.0)ein. Der compiler meckert aber immernoch, weil er die V11.0 haben will. ich habe keine lust meinen code umzubauen. Könnt ihr mir bitte helfen ?
mfg
zippo
Hallo alle zusammen!
@Stefan, erstmal ein fettes dankeschön meinerseits für den Code und damit einen einstieg in die automatisierung von excel 😉
Ich habe jedoch das Problem, dass bei Codezeile:
7. excel = new Microsoft.Office.Interop.Excel.ApplicationClass();
die Fehlermeldung kommt:
Der Interoptyp “Microsoft.Office.Interop.Excel.ApplicationClass” kann nicht eingebettet werden. Verwenden Sie stattdessen die entsprechende Schnittstelle.”
Ich verwende Excel 2007 und habe daher “Microsoft Excel 12.0 Object Library” als Verweis hinzugefügt.
Den Verweis “Microsoft Excel 11.0 Object Library” gibt es bei meinem Visual Studio anscheinend auch nicht und so meine frage an dich:
Bist du dir sicher dass dein Code auch bei Excel 2007 funktioniert?
MfG, Käse 😉
@Käse: Danke für den Tipp. Der Code ist korrigiert (Quelle: Peter Torr: Don’t use ApplicationClass (unless you have to)).
Danke dass du das behoben hast ^^
Freut mich dass ich helfen konnte, obwohl ich neu in c# bin 😉
wenn ich eine zweite Exceldatei ausser meinem Programm aufmache und die zumacht dann ist auch gleichzeitig die Datei, deren ich mit meinem Programm geöffnet habe zugemacht. wie kann ich es vermeiden
@gilles: Vielleicht könntest du einfach das excel.Quit(); weglassen.
Sehr gutes Posting. Danke. bb
Hallo, danke für Deine 5-jährige!!! Unterstützung zu diesem Thema!
Vielleicht kannst Du mir auch helfen. Ich möchte in einem Programm sowohl den Import von Excel 2007 als auch 2010 Dateien unterstützen, ohne dass der Nutzer angeben muss welche Version er importiert. Jetzt habe ich gehört, dass folgende Probleme auftreten:
– Falls ich nur die Excel 2010 Bibliothek verwende, dann werden die 2007er Dateien automatisch konvertiert und die Tabellenstruktur kann verloren gehen.
– Ich kann, ohne dass ich die Datei mit einer der Bibs aufmache, nicht entscheiden um welche Excel Version es sich handelt.
Wäre super, wenn Du under jemand anderes hier mir diese Aussagen kommentieren könnte!
Ich werde ja nicht die erste sein, die vor dieser Aufgabe steht, da muss es doch eine Lösung geben.
Mh… mir ist nicht bekannt, dass es einen Unterschied der Dateiformate zwischen 2007 und 2010 gibt. Wenn du ein Beispiel für eine 2007er Datei hättest, die “kaputt” geht, wenn man sie mit 2010 öffnet, könnte ich das mal nachstellen.
Ich verwende den Code in einer ASP.NET-Seite zum Hochladen und Analysieren einer xlsx. Klappt in VS2010 wunderbar, leider nicht mehr, wenn ich die Seite in IIS7 veröffentliche. Habe mittlerweile die COM-Komponente korrekt berechtigt und komme bis zum Open des Workbooks:
Microsoft.Office.Interop.Excel.Application excel = null;
Workbook wb = null;
excel = new Microsoft.Office.Interop.Excel.Application();
excel.Visible = false;
wb = excel.Workbooks.Open(xlsxFile,
ExcelKonstanten.UpdateLinks.DontUpdate,
ExcelKonstanten.ReadOnly,
ExcelKonstanten.Format.Nothing,
“”, // Passwort
“”, // WriteResPasswort
ExcelKonstanten.IgnoreReadOnlyRecommended,
XlPlatform.xlWindows,
“”, // Trennzeichen
ExcelKonstanten.Editable,
ExcelKonstanten.DontNotifiy,
ExcelKonstanten.Converter.Default,
ExcelKonstanten.DontAddToMru,
ExcelKonstanten.Local,
ExcelKonstanten.CorruptLoad.NormalLoad);
Hier erhalte ich den Fehler, dass auf die Exceldatei nicht zugegriffen werden kann, weil schon geöffnet. Die Exceldatei steht in einem Ordner mit JEDER-Vollzugriffsrechten. Weiß nicht mehr weiter … bitte um Tipps, wo ich noch ansetzen könnte. Besten Dank, Martin
Ergänzung, der genaue Fehler lautet:
Microsoft Excel kann auf die Datei ‘C:\inetpub\ExcelAuswertung\App_Data\Excelfiles\test.xlsx’ nicht zugreifen. Dies kann mehrere Gründe haben:
• Der Name des Dokuments oder der Pfad ist nicht vorhanden.
• Das Dokument wird von einem anderen Programm verwendet.
• Der Name der Arbeitsmappe, die gespeichert werden soll, ist identisch zu dem Namen eines anderen Dokuments, welches schreibgeschützt ist.
Beschreibung: Unbehandelte Ausnahme beim Ausführen der aktuellen Webanforderung. Überprüfen Sie die Stapelüberwachung, um weitere Informationen über diesen Fehler anzuzeigen und festzustellen, wo der Fehler im Code verursacht wurde.
Ausnahmedetails: System.Runtime.InteropServices.COMException: Microsoft Excel kann auf die Datei ‘C:\inetpub\ExcelAuswertung\App_Data\Excelfiles\test.xlsx’ nicht zugreifen. Dies kann mehrere Gründe haben:
• Der Name des Dokuments oder der Pfad ist nicht vorhanden.
• Das Dokument wird von einem anderen Programm verwendet.
• Der Name der Arbeitsmappe, die gespeichert werden soll, ist identisch zu dem Namen eines anderen Dokuments, welches schreibgeschützt ist.
Sorry Martin, dazu kann ich dir leider auch nichts sagen 🙁
Habe genau das gleiche Problem wie Martin, C# Webanwendung, gleiche Fehlermeldung beim Öffnen der Datei. Das seltsame ist auf einem anderen Server läuft der gleiche Binärcode einwandfrei, auch gleiche Office Version. Leider waren bisher im Internet keine Antworten zu finden, das Problem gibts aber öfters.
Guten Abend,
vielen Dank für den tollen Einstieg!
Was mir noch fehlt ist das Schreiben von (einzelnen) Werten
in die Excel-Tab (das Schreiben einer ganzen Zeile
noch nicht probiert habe), vielleicht habe ich es auch nur nicht
gesehen, so oder so wäre ein Tip sehr hilfreich.
Versucht habe ich bisher
Object[] args = new Object[1];
args[0] = 6;
aRange.GetType().InvokeMember(“Value”,
BindingFlags.SetProperty, null, aRange, args);
aRange.Value2 = 8;
Verwenden von COM-Interop zum Erstellen einer
Excel-Kalkulationstabelle
(http://msdn.microsoft.com/de-de/library/ms173186%28v=vs.80%29.aspx#Y611)
bzw.
excelRange.Cells.set_Item(row, col, value);
von Set cell value using Excel interop
(http://stackoverflow.com/questions/4811664/set-cell-value-using-excel-interop)
Beides leider ohne Erfolg, würde mich freuen, wenn jemand eine
weitere Idee hat.
Im voraus vielen Dank
🙂
Guten Abend 🙂
schon schade, wenn man ReadOnly in Zeile 14 übersieht.
Wobei Excel auch artig fragt, ob die Datei überschrieben werden soll
und keine Fehlermeldung bringt.
nochmal vielen Dank für die Seite
Gruß D
@Martin
Hast du es schon mal mit einem Virtuellen Verzeichnis probiert?
Bei hat es danach funktioniert.
LG
@Martin
Hast du es schon mal mit einem Virtuellen Verzeichnis probiert?
Bei mir hat es danach funktioniert.
LG
Hi,
Ich habe win7 64 bit, office 2010 und vs2008. Ich kann die Microsoft Excel 14.0 Object Library nicht finden. Bei mir ist nur die 12.0 vorhanden.
Grüße, Oli
Danke für die Hilfe, das funktioniert auch soweit alles ganz gut, jedoch springt er bei mir direkt zum Ende wenn er eine leere Zelle erwischt.
Ein Codeausschnitt
if (crange11.Value.ToString() != null)
{ czellwert11 = crange11.Value2.ToString();
czellwertint11 = Convert.ToInt16(czellwert11);
}
else
{czellwertint11 = 0;}
Wenn die Zelle leer ist, geht er einfach nicht in die Else-Schleife.
Hat jemand eine Lösung???
Hat sich erledigt, wenn eine Zelle leer ist, kann man sie nicht in einen String umwandeln, heißt in
if (crange11.Value.ToString() != null)
muss das .ToString() rausgenommen werden
Vielen Dank!!!
Super Anleitung hat mir sehr geholfen!
Hallo Stefan,
erst einmal vielen Dank für Deine Mühe.
Das Auslesen einer Zelle funktionierte bei mir auf Anhieb. Klasse!
Frage: Wie kann ich jedoch mehrere Zellen auslesen?
Hintergrund: Ich habe eine Excel-Liste mit 2 Spalten. In der ersten stehen Namen und in der zweiten stehen die dazugehörigen Email-Adressen. Ich möchte meiner Freundin nun den Gefallen tun, für ihre Arbeit ein Script zu schreiben, welches ihr etwas Arbeit abnimmt. Das Script soll mit einem Button-Druck, jedem Mitarbeiter eine Mail mit dem aktuellen Gleitzeit- und Urlaubsstand aus einer anderen Excel-Liste senden.
Per Google und msdn finde ich leider nur das Auslesen EINER Zelle.
Für einen Tipp, wie ich die Sache realisieren könnte, wäre ich Dir sehr dankbar.
Viele Grüße
Andre
Hallo Andre, dafür wirst du dir dann ein Programm schreiben müssen. Grundsätzlich kannst du ja nur auf eine Zelle gleichzeitig zugreifen. Die restliche Logik muss dann dein Programm übernehmen (z.B. mit einer Schleife durch die Zellen wandern).
Das Einlesen einer Excel-Datei funktioniert problemlos (zumindest bei xls), aber ist sehr langsam. Wenn ich nun versuche, ein Eintrag (Datum) hinzuzufügen, kann ich die Datei nicht mehr einlesen. Ein Öffnen mit Excel funktioniert und zeigt auch alles korrekt an!
Wie muss ich ein Datum korrekt übergeben? Mein Versuch für Schreiben / Lesen:
ws.Cells[zeile, 1] = DateTime.Now.ToShortDateString();
dt = DateTime.FromOADate((double)range.Value2.ToString());