Überprüfen, ob Excel-Datei bereits geöffnet ist. Ansonsten aktivieren.

  • VB.NET

Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von ADB.

    Überprüfen, ob Excel-Datei bereits geöffnet ist. Ansonsten aktivieren.

    Ich begrüsse das Forum.

    Leider bin ich nach stundenlanger Suche mit einem Problem noch nicht fertig geworden. Ich bin kein erfahrener Programmierer...

    Folgende Sache möchte ich realisieren:

    Mein Programm sollte eine bestimmte Excel-Datei öffnen und zwar exklusiv, also nicht schreibgeschützt. Falls sie Datei bereits geöffnet sein sollte, soll diese aktiviert werden, damit mein Programm Daten eingeben und auslesen kann. Das Eingeben und Auslesen ist jedoch weniger das Problem, sondern das Aktivieren der bereits geöffneten Datei.

    Unter openbook.galileocomputing.de/vb_net/msvb040001.htm habe ich im Abschnitt

    Somit kann überprüft werden, ob eine Datei schon geöffnet ist oder nicht. Falls ja, wird sie nach vorne geholt, falls nein, wird sie geöffnet

    folgenden Code gefunden:

    VB.NET-Quellcode

    1. Sub DateiÖffnen()
    2. Dim xlsDatei As Workbook
    3. Dim strDatName As String
    4. On Error Resume Next
    5. For Each xlsDatei In Workbooks
    6. If xlsDatei.Name = "Rechnung.xls" Then
    7. xlsDatei.Activate
    8. Exit Sub
    9. End If
    10. Next
    11. Workbooks.Open Filename:= __
    12. "C:\Eigene Dateien\Uebungsdateien" & _
    13. "\Excel\Rechnung.xls"
    14. End Sub




    Diesen habe ich an mein Programm entsprechend angepasst:

    VB.NET-Quellcode

    1. Dim Zelle As String
    2. Dim xls_Appl As Excel.Application ' Excel Anwendung
    3. Dim xls_Mappe As Excel.Workbook ' Excel Arbeitsmappe
    4. Dim xls_Blatt As Excel.Worksheet ' Excel Blatt (Tabelle)
    5. Dim xls_Bereich As Excel.Range
    6. Dim ExcelDateiPfad As String = "C:\Trainingsplan_vb.net.xlsx"
    7. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    8. On Error Resume NextFor Each Me.xls_Mappe In xls_Appl.Workbooks
    9. If xls_Mappe.Name = "Trainingsplan_vb.net.xlsx" Then
    10. xls_Mappe.Activate()
    11. Exit Sub
    12. End If
    13. Next
    14. xls_Appl.Workbooks.Open(ExcelDateiPfad)
    15. xls_Appl.Visible = TrueEnd Sub




    Ich Programmiere mit Visual Basic 2008. Wenn ich auf den Button1 klicke, geschieht jedoch überhaupt nichts. Weder wenn die Datei bereits geöffnet, noch wenn sie geschlossen ist.



    Kann mir evtl. jemand bei meinem Problem weiterhelfen?



    Besten Dank.

    Freundlich grüsst

    ADB
    Hey,

    kurz und knapp: Also wenn eine Excel Tabelle/Liste geöffnet/schreibgeschützt ist kannst du diese natürlich auslesen, allerdings nicht "aktivieren" in dem Sinne von überschreiben.
    Das heißt wenn sie offen ist kannst du nur noch eine Kopie davon anlegen, nachdem du diese editiert hast.

    "Somit kann überprüft werden, ob eine Datei schon geöffnet ist oder nicht. Falls ja, wird sie nach vorne geholt, falls nein, wird sie geöffnet "

    Damit ist gemeint ob sie in den Vordergrund genommen wird, oder einfach nur aktiviert wird im Sinne von "Programm starten"

    Wie du herausfinden kannst ob diese Datei bereits geöffnet ist?
    Nun, ich mache es momentan so:
    (Beim Öffnen wird eine "nicht sichtbare Datei" erstellt die wie folgt heißt; "~$Original.xlsx" es werden folgende Zeichen genommen "~$")


    VB.NET-Quellcode

    1. Dim Excel_Sicherungsdatei As String = "C:\Temp\~$Beispiel.xlsx"
    2. 'Load Ereignis überprüfen ob Datei existiert
    3. If My.Computer.FileSystem.FileExists(Excel_Sicherungsdatei) Then '...


    Ich hoffe das hilft dir.

    Grüße
    Option Strict On!

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Drahuverar“ ()

    ADB schrieb:

    VB.NET-Quellcode

    1. On Error Resume Next
    1. Das ist Fehlerhandling made by VB6.
    2. Falls Du Fehler finden willst, schmeiß diese Zeile raus.
    3. Falls dann eine Exception auftritt, dann fang genau diese Exception genau so ab:

      VB.NET-Quellcode

      1. Try
      2. ' Code
      3. Catch ex As MySpecialException ' hier die genannte Exception-Klasse eintragen
      4. 'MessageBox.Show(ex.Message)
      5. End Try

    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Besten Dank für eure Antworten.

    @Drahuverar

    Wahrscheinlich konnte ich mich zu wenig genau ausrücken. Ich möchte nicht eine schreibgeschützte Datei öffnen, sondern die Datei ohne Schreibschutz öffnen. Dies bedingt natürlich, dass die Datei noch nicht geöffnet ist. Jedoch kann es ja vorkommen, dass die Datei bereits geöffnet ist, während mein Programm abläuft und die bereits geöffnete Datei öffnen möchte. (sorry für den seltsamen Satz :D )

    Deshalb soll das Programm überprüfen, ob die Datei bereits geöffnet ist und demensprechend reagieren:

    1. Programm soll per Button überprüfen, ob die Datei bereits geöffnet ist.

    2. Nach der Überprüfung soll die Datei gestartet werden, falls diese noch nicht geöffnet sein sollte.

    3. Sollte die Datei bereits geöffnet sein, müsste die Datei nicht erneut gestartet, sondern nur in den Vordergrund gebracht werden, damit mein Programm Einträge eintragen und auslesen kann.

    Aus diesem Grund wollte ich nachfolgenden Code einsetzen:

    VB.NET-Quellcode

    1. Dim Zelle As String
    2. Dim xls_Appl As Excel.Application ' Excel Anwendung
    3. Dim xls_Mappe As Excel.Workbook ' Excel Arbeitsmappe
    4. Dim xls_Blatt As Excel.Worksheet ' Excel Blatt (Tabelle)
    5. Dim xls_Bereich As Excel.Range
    6. Dim ExcelDateiPfad As String = "C:\Trainingsplan_vb.net.xlsx"
    7. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    8. Try
    9. For Each Me.xls_Mappe In xls_Appl.Workbooks
    10. If xls_Mappe.Name = "Trainingsplan_vb.net.xlsx" Then
    11. xls_Mappe.Activate()
    12. Exit Sub
    13. End If
    14. Next
    15. xls_Appl.Workbooks.Open(ExcelDateiPfad)
    16. xls_Appl.Visible = TrueEnd Sub
    17. Catch ex As Exception
    18. MessageBox.Show(ex.Message)
    19. End Try




    @RodFromGermany

    Leider hat die Try-Catch-Variante nicht viel gebracht, bisher. Nach wie vor geschieht überhaupt nichts, wenn ich den Button betätige.

    Zudem konnte mein VB 2008 mit Catch ex As MySpecialException nicht viel anfangen. Das Catch ex As Exception hat er jedoch gefressen.



    Kann es denn sein, dass der Code für VB6 geschrieben ist? Oder gibt es sonst in einem Ort einen (bzw. mehrere) Fehler?



    Freundlich grüsst

    ADB

    ADB schrieb:

    Exception hat er jedoch gefressen.
    Genau das sollst Du nicht tun. MySpecialException gibt es nicht!
    Kam eine Exception? Wenn nein, schmeiß das Try-Catch raus.
    Wenn ja, sieh nach, um welche Exception es sich handelt und schreib genau die da ren, zum Beispiel FileNotFoundException (diese kommt allerdings da nicht vor).
    ----
    Setz einen Haltepunkt rein und arbeite Deinen Code zeilenweise ab.
    Tut er das was er soll? Wenn Nein, hast Du einen Fehler gefunden.
    Gugst Du hier.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Sorry, ich steige gerade nicht durch.

    Wie soll denn der Try -Catch - Code genau heissen? Exception soll ich nicht brauchen und MySpecialException gibt es nicht??

    Seltsamerweise wird jetzt eine Fehlermeldung ausgegeben. Bevor ich den Try-Catch-Block eingefügt habe, hat der Debugger keinen Fehler gemeldet. Jetzt unterbricht das Programm mit der Meldung:

    Nullreferenzexception wurde nicht behandelt.

    Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.

    Die Zeile

    VB.NET-Quellcode

    1. For Each Me.xls_Mappe In xls_Appl.Workbooks


    ist markiert. Kann es sein, dass das Me.xls_Mappe das Problem verursacht?


    Danke noch für den Hinweis zur Fehlersuche.

    ADB schrieb:

    Nullreferenzexception wurde nicht behandelt.
    Na also.
    Diesde Exception musst Du im Code reparieren, weil da ein New oder ein Create() fehlt. Poste mal den relevanten Code und markiere die betreffende Zeile.
    -----
    Try/Catch soll nicht verwendet werden, um iwelche Exceptions zu ignorieren, sondern um für einzelne Exceptions eine separate Bwehandlung durchführen zu können, gugst Du hier.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Als ich xls_Appl = New Excel.Application() eingefügt habe, hat sich die gewünschte Datei zwar geöffnet, als ich jedoch ein zweites Mal auf den Butten gedrückt habe, hat das Programm dieselbe Datei als schreibgeschützt geöffnet.

    Aber es gibt doch sicherlich eine Möglichkeit, die Datei nicht ein zweites Mal (schreibgeschützt) zu öffnen, sondern nur zur bereits geöffneten Datei zu wechseln (bzw. springen).

    GetObject ist wohl auch nicht die Lösung für mein Problem, oder?

    So sieht mein Code momentan aus:


    VB.NET-Quellcode

    1. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    2. xls_Appl = New Excel.Application() ' Excel Instanz bilden
    3. xls_Appl.Visible = True
    4. Try
    5. For Each Me.xls_Mappe In xls_Appl.Workbooks
    6. If xls_Mappe.Name = "Trainingsplan_vb.net.xlsx" Then
    7. xls_Mappe.Activate()
    8. Exit Sub
    9. End If
    10. Next
    11. xls_Appl.Workbooks.Open(ExcelDateiPfad)
    12. xls_Appl.Visible = True
    13. Catch ex As Exception
    14. MessageBox.Show(ex.Message)
    15. End Try
    16. xls_Mappe.Save()
    17. End Sub
    Ist deine Aussage jetzt bezogen auf "GetObject" oder auf die Möglichkeit mit der For-Each-Schleife ?

    Über GetObject hatte ich jedoch auch wenig Erfolg. Nur, wenn die korrekte Excel-Datei als einzige Excel-Datei geöffnet war, konnte ich über mein Programm ins Excel schreiben...

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ADB“ ()

    Um meinen letzten Beitrag evtl. noch zu erweitern:

    VB.NET-Quellcode

    1. GetObject(ExcelDateiPfad)
    2. xls_Blatt = CType(xls_Mappe.Worksheets(1), Excel.Worksheet) ' 1. Tabelle auswhlen
    3. xls_Blatt.Select()
    4. xls_Bereich = xls_Blatt.Range("A3:H3") ' Bereich B13 bis H13 festlegen
    5. xls_Bereich.Select() ' Bereich markieren
    6. If CStr(xls_Blatt.Range("A2").Value) = "" Then ' Die zweite Zeile sollte immer leer sein.
    7. Else
    8. xls_Blatt.Range("A2:H2").Value = "" ' Ansonsten soll sie gelscht werden.
    9. End If
    10. If CStr(xls_Blatt.Range("A3").Value) = "" Then ' Ist die dritte Zeile bereits leer, soll keine neue Zeile eingefgt werden.
    11. Else
    12. xls_Bereich.Insert(Shift:=Excel.XlInsertShiftDirection.xlShiftDown) ' Zellen nach unten verschieben
    13. End Ifxls_Blatt.Range("A3").Value = TextBoxDate.Text
    14. xls_Blatt.Range("B3").Value = TextBoxTime.Textxls_Appl = New Excel.Application


    Wenn ich auf den Button drücke und nur die richtige Datei geöffnet habe, funktioniert alles prima. Sobald eine weitere Excel-Datei geöffnet ist, bricht das Programm ab. Die Zeile

    VB.NET-Quellcode

    1. xls_Blatt.Select()

    ist markiert, mit der Meldung:
    Ausnahme von HRESULT: 0x800A03EC
    Du musst dir die Excel-Instanz holen
    Set ExcelApp = GetObject("Excel.Application")
    Dann musst die die ExcelApp.Workbooks-Collection scannen, ob da dein gewünschtes dabei ist.
    Wenn ja, kannst du es ansprechen.
    Wenn nein, kannst du es öffnen mit ExcelApp.Workbooks.Open()
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Danke für deine Hinweise.

    Mein Code sieht nun so aus:

    VB.NET-Quellcode

    1. Dim ExcelApp As New Excel.Application
    2. ExcelApp = CType(GetObject(, "Excel.Application"), Application)
    3. For Each Me.xls_Mappe In ExcelApp.Workbooks
    4. If xls_Mappe.Name = "Trainingsplan_vb.net.xlsx" Then
    5. xls_Mappe.Activate()
    6. Else
    7. ExcelApp.Workbooks.Open(ExcelDateiPfad)
    8. Exit Sub
    9. End IfNext


    Leider überspringt das Programm die Zeile

    VB.NET-Quellcode

    1. xls_Mappe.Activate()


    und geht direkt zu

    VB.NET-Quellcode

    1. ExcelApp.Workbooks.Open(ExcelDateiPfad)


    Stimmt denn die nachfolgende Zeile auch wirklich?

    VB.NET-Quellcode

    1. For Each Me.xls_Mappe In ExcelApp.Workbooks

    ADB schrieb:

    Stimmt denn die nachfolgende Zeile auch wirklich?
    Nein. Das lässt ja wahrscheinlich nicht mal der Compiler durchgehen.

    VB.NET-Quellcode

    1. Dim w, wb As Excel.Workbook,
    2. For Each w In ExcelApp.Workbooks
    3. If w.Name = "Trainingsplan_vb.net.xlsx" Then
    4. wb = w
    5. Exit For
    6. Next
    7. If wb is Nothing Then wb = ExcelApp.Workbooks.Open(ExcelDateiPfad)
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    sorry für die verspätete Antwort.

    Ich habe noch einiges versucht, jedoch bisher noch zu keinem befriedigenden Resultat gekommen.

    Leider ist mir relativ spät aufgefallen, dass er die Schleife

    VB.NET-Quellcode

    1. For Each w In ExcelApp.Workbooks
    2. If w.Name = "Trainingsplan_vb.net.xlsx" Then
    3. wb = w
    4. Exit For


    überspringt und direkt zu


    VB.NET-Quellcode

    1. If wb is Nothing Then wb = ExcelApp.Workbooks.Open(ExcelDateiPfad)



    übergeht, obwohl die Excel-Datei ja eigentlich bereits offen ist...

    Somit klappt natürlich auch das Speichern der Änderung nicht, da die Excel-Datei schreibgeschützt geöffnet wird.



    Zudem wird das "w" in der Zeile 2 markiert mit dem Warnhinweis:

    Der Typ für die Variable "w" wird nicht abgeleitet, da er an ein Feld in einem einschließenden Bereich gebunden ist. Ändern Sie den Namen von "w", oder verwenden Sie den vollqualifizierten Namen (z.B. "Me.w" oder "MyBase.w")

    Ich werde "mein Glück" noch weiter versuchen. Falls jemand noch konkrete Hinweise liefern kann, würde ich mich natürlich darüber freuen...
    Ich weiß nicht, was du falsch machst und wie deine Verweise und Imports aussehen.
    Ich habe jetzt testweise eine Billiganwendung geschrieben, die mir alle offenen Arbeitsmappen listet.
    Und die funktioniert.

    VB.NET-Quellcode

    1. Option Strict On
    2. Imports Microsoft.Office.Interop.Excel 'ins Projekt auch diesen Verweis einfügen
    3. Module Module1
    4. Sub Main()
    5. Dim ExcelApp As Application
    6. ExcelApp = CType(GetObject(, "Excel.Application"), Application)
    7. For Each w As Workbook In ExcelApp.Workbooks
    8. Debug.Print(w.Name)
    9. Next
    10. End Sub
    11. End Module
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Aus irgendwelchen Gründen will dein Code nicht hinhauen. Es ist mir jedoch bewusst, dass die Wahrscheinlichkeit, dass es an mir liegt, sehr gross ist... :D

    Ein anderer Code hat jedoch fast einwandfrei funktioniert. Ob er jedoch in jeder Situation funktioniert, wird sich zeigen. Mein Programm wird noch etwas erweitert und anschliessend einige Tage getestet. Falls es zu meiner Zufriedenheit funktionieren sollte, werde ich den Code hier posten...

    Besten Dank nochmals für eure Bemühungen.

    Gruss
    ADB