Hallo,
ich möchte auf eine bestimmte Excel Datei und in dieser auf bestimmte Sheets zugreifen. Das klappt soweit gut, wenn die Datei geschlossen ist und vom Programm erst geöffnet wird. Dazu benutze ich folgenden Code:
/*Excel*/
Excel.Sheets objSheets;
Excel._Worksheet objSheet;
try
{
// Open a specified workbook
objApp = new Excel.ApplicationClass();
objBook = objApp.Workbooks.Open("I:/Test123.xls");
objSheets = objBook.Worksheets;
//write to the Signal sheet
objSheet = (Excel._Worksheet)objSheets.get_Item("Test");
/*Erstmal Sheet bereinigen*/
objSheet.get_Range("C3:L18").set_Value(Missing.Value, "");
objSheet.get_Range("B1").set_Value(Missing.Value, "Test123456");
}
Was muss ich anpassen, damit zunächst geprüft wird, ob diese Datei bereits geöffnet ist und dann direkt in diese geschrieben wird?
Ich habe zwar via Google einige Beispiele gefunden, diese aber nicht verstanden und hopffe mir kann jemand das konkret an meinem Code zeigen. Danke.
So, ich habe selbst noch einiges versucht. Im Moment hänge ich aber fest. Ich schaffe es, dass er die Datei öffnet, wenn sie nicht offen ist. An dem Punkt war ich ja schon heute Morgen.
Zusätzlich schaffe ich es jetzt, die Datei zu bearbeiten, wenn sie schon offen ist. Soweit so gut. Jetzt geht es darum beide zusammenzufügen, mit einer Prüfung, ob die Datei läuft. Falls nein: öffne sie, sonst beschreibe sie direkt.
Hier kommt aber ein Fehler. Ich denke, dass der Fehler direkt die Zeile eins in dem Ausschnitt betrifft. Evtl. klappt das mit der Überprüfung auf null nicht, wie kann ich das anders machen?
Der Fehler heißt ungefähr so:
Error: Ausnahme von HRESULT; 0x800A03EC bei Microsoft.Office.Interop.Excel
if ((Excel.Workbook)System.Runtime.InteropServices.Marshal.BindToMoniker(filePath + file) == null)
{
//Open it since it is not yet open ----working fine
objApp = new Excel.ApplicationClass();
objWorkbook = objApp.Workbooks.Open(filePath + file);
objSheets = objWorkbook.Worksheets;
}
else
{
//it is open, get it ------this part IS working fine
objWorkbook = (Excel.Workbook)System.Runtime.InteropServices.Marshal.BindToMoniker(filePath + file);
objSheets = objWorkbook.Application.Worksheets;
}
Auch die andere Alternative bringt leider keine Lösung. Zwar kommt dann der Fehler nicht, aber es wird in die geöffnete Datei nicht geschrieben.
try
{
//Open it since it is not yet open ----working fine
objApp = new Excel.ApplicationClass();
objWorkbook = objApp.Workbooks.Open(filePath + file);
objSheets = objWorkbook.Worksheets;
}
catch(Exception e)
{
//it is open, get it ------this part IS working fine
objWorkbook = (Excel.Workbook)System.Runtime.InteropServices.Marshal.BindToMoniker(filePath + file);
objSheets = objWorkbook.Application.Worksheets;
}
Habs gelöst:
if(!isFileOpenOrReadOnly(filePath + file))
{
//Open it since it is not yet open ----working fine
objApp = new Excel.ApplicationClass();
objWorkbook = objApp.Workbooks.Open(filePath + file);
objSheets = objWorkbook.Worksheets;
}
else
{
//it is open, get it ------this part IS working fine
objWorkbook = (Excel.Workbook)System.Runtime.InteropServices.Marshal.BindToMoniker(filePath + file);
objSheets = objWorkbook.Application.Worksheets;
}
und de funktion ist
public bool isFileOpenOrReadOnly(string file)
{
try
{
//first make sure it's not a read only file
if ((File.GetAttributes(file) & FileAttributes.ReadOnly) != FileAttributes.ReadOnly)
{
//first we open the file with a FileStream
using (FileStream stream = new FileStream(file, FileMode.OpenOrCreate, FileAccess.Read, FileShare.None))
{
try
{
stream.ReadByte();
return false;
}
catch (IOException)
{
return true;
}
finally
{
stream.Close();
stream.Dispose();
}
}
}
else
return true;
}
catch (IOException)
{
return true;
}
}
Hallo dansmo,
du hast zwar das Problem gelöst, uns aber leider nicht mitgeteilt, was der Grund für das Verhalten ist. Andere, die das gleiche Problem haben und die Forensuche verwenden, werden dann leider nicht wissen, warum die Fehlermeldung kommt. Es wäre nett, wenn du das beschrieben könntest.
Ich nehme dir die Arbeit mal ab: Der Grund ist, dass Excel die Datei offen hat. Weil Excel die Datei offen hat, ist somit der Stream offen. Erst wenn der Stream wieder geschlossen ist, kann man die Datei wieder lesen. Wenn nun Excel die Datei verwendet und eine andere Anwendung versucht, die Datei zu lesen, kommt es zu dieser Fehlermeldung. Aus diesem Grund muss man vorher prüfen, ob es möglich ist, die Datei zu lesen.
zero_x
zero_x | <span style="font-size: 10;">my</span><span style="font-size: 10;">CSharp</span><span style="font-size: 10;">.de</span> - gemeinsam mehr erreichen
Für längere Zeit inaktiv.
Ja, hast du recht. Danke.
Jetzt habe ich noch ein kleineres Problem, das ich der Vollständigkeit halber auch gerne noch lösen möchte:
Wenn mehrere Excel Instanzen geöffnet sind dann kommt es zu Problemen. Wie kann ich das noch einfügen, damit der Code immer (naja, fast immer) richtig funktioniert?
Jetzt habe ich noch eine Anschlussfrage:
Auf meinem "Entwickler PC" habe ich Office 2010 installiert, auf dem "Arbeits PC" jedoch Office 2003. Dort funktioniert es jetzt leider nicht, wenn ich meine Anwendung am Arbeits PC laufen lass.
Was muss ich tun damit das trotzdem geht, egal welche Office Version der user benutzt?
Hallo!
Um versionsunabhängig auf Office-Instanzen zuzugreifen, bleibt dir entweder, alle dafür benötigten Office-Wrapper einzubinden, oder komplett auf COM-LateBinding umzusteigen, zu zweiterem gobt's sogar schon fertige Komponenten hier im Forum.
Nobody is perfect. I'm sad, i'm not nobody 🙁
Hallo Tom,
ich habe zu dem Late Binding code gefunden, ja. Leider habe ich keine Ahnung, wie ich meinen obigen Code verändern muss, damit das klappt. Ich war ja schon froh, dass es überhaupt funktioniert hat. Kann mir denn jemand helfen dass in meinen Code zu integrieren?
Es geht um den Code in diesem Thrad http://www.mycsharp.de/wbb2/thread.php?threadid=77102und dessen Integration mit meinem obigen Code. Ich gehe davon aus, dass das der richtige Weg ist verstehe aber vom Code ehrlich gesagt nichts.
Was verstehst du am Code nicht.
Rainbird erklärt das soweit ganz gut finde ich.
Alternativ möchte ich dir ein kleines Projekt von mir empfehlen
das dir dass bietet was du brauchst.
Hallo Sebastian,
danke für dein Projekt, jetzt geht es.
Eine kleine Frage dazu:
vorher konnte ich ein einzelnes Worksheet so ansteuern:
objSheet = (Excel._Worksheet)objSheets.get_Item("Signal");
Mit deiner dll geht das jetzt nicht mehr, anscheinend kann ich das nur noch nach Nummerierung aufrufen?
objSheet = (Excel._Worksheet)objSheets[1];
Oder geht das so auch?
objSheet = (Excel._Worksheet)objSheets["Signal"];
Danke für Feedback,
dansmo
Hallo dansmo,
Klar das geht auch so
Excel.Worksheet workSheet = workBook.Worksheets["Signal"];
Wenn du Fragen zu LateBindingApi.Excel hast dann stelle die bitte in dem
myCSharp Thread dazu:
LateBindingApi.Excel - Framework für den versionsfreien Zugriff
Viel Erfolg!
Sebastian