Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1168to1172
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

SaveAs über VBA macht bei BeforeSave Probleme

SaveAs über VBA macht bei BeforeSave Probleme
norman
Hallo alle,
ich habe ein wirklich kniffeliges Problem, das bereits hier mal angegangen wurde (https://www.herber.de/forum/archiv/1144to1148/t1147360.htm und https://www.herber.de/forum/archiv/1144to1148/t1145651.htm, vielen Dank an dieser Stelle an Tino, entschuldige bitte, dass ich damals da nicht weiter gemacht hatte, ich war an einem anderen Projekt, aber vielleicht kommen wir da ja jetzt weiter :)).
Folgendes will ich schaffen: Ich habe eine XLA die über startup geladen wird. Jede Datei die gespeichert wird soll in einer zentralen Datenbank als Datensatz eingetragen werden. Den Dateinamen habe ich natürlich erst nach dem Speichern. Das habe ich bereits alles hinbekommen. Erschwerend kommt hinzu, dass jede Datei mit der Datensatz-ID versehen werden muss (lege ich in der ExcelDatei ab). Ich habe also in BeforeSave das komplette "Datei-speichern-unter-Handling" eingebaut. Damit wird der Dateiname ermittelt, damit ich diesen im Datensatz speichern kann. Dann wird die ID in der ExcelDatei gesetzt und die Datei gespeichert. Dadurch erkenne ich auch bei einer verschobenen oder umbenannten Datei, wo sie ursprünglich her kommt. Wie gesagt, das klappt alles.
Jetzt aber mein Problem: Es gibt ExcelDateien, die nutzen im VBA-Code SaveAs. Damit ist der Dateiname ja beim Speichern für Excel bekannt, leider ist er aber nicht ermittelbar in BeforeSave, da BeforeSave ja nicht weiß, ob der User per Menü gespeichert hat oder VBA den Aufruf tätigt. Ihr könnt Euch vorstellen was passiert? Richtig, ich frage den User in meiner Routine nach dem Dateinamen, was natürlich zu Verwirrung führt, denn der wurde ja im VBA-Code mit angegeben!
Tino hat hier schon einen timerbasierten Ansatz vorgeschlagen, in dem eine Klasse einfach wartet, bis die Datei .Saved ist. Das ist ne klasse Idee, da ich selbst dann nicht mehr die Dateinamen ermitteln müsste und das ganze würde dann auch mit VBA funktionieren. Aaaaber: Bei dieser Methode kann ich die ID nicht mehr in der ExcelDatei setzen, da diese erst ermittelt werden kann, wenn der Dateiname feststeht. (Hintergrund: Wird die eine bereits im Datenbanksystem vorhandene Datei an einen neuen Platz gespeichert wird ggf. auch eine neue ID vergeben, die dann auch in der ExcelDatei gesetzt werden muss. Diese ist dann aber schon gespeichert!).
Irgendwie kommt mir das verdammt nach Henne/Ei Problem vor, und aktuell kriege ich das Ei nicht kaputt. Zwei Fragen also:
1. Wie könnte ich mitkriegen, ob der Aufruf von VBA oder über den User kommt (SaveAsUI hilft da nicht). Nepumuk hatte glaube ich schon mal geantwortet, dass das nicht geht, vielleicht hat aber einer eine Idee. Habe schon überlegt das ExcelMenü umzugestalten und meinen eigenen Aufruf an die Stelle von "Datei speichern unter" zu setzen, das ist aber einen mords Aufwand auch für spätere Versionen von Excel (2007, da weiß ich gar nicht ob das geht). Wenn meine eigenen Funktion im Menü eingebunden wäre könnte ich dort ein Flag setzen, das mir anzeigt, dass die Eingabe vom User kam. Je länger ich darüber nachdenke um so eher ist das wohl die Lösung. Weiß jemand wie ich "Datei speichern unter" und "Datei speichern" als auch STRG+S "überladen" kann?
2. (Alternative) Wie könnte ich die ID in die Datei bekommen und nach dem Speichern erst den Dateinamen ermitteln? Wenn die Datei an die gleiche Stelle wie vorher gespeichert wird muss die ID gleich bleiben, bei einer Speicherung an eine andere Stelle erhält sie eine neue ID. Theoretisch könnte ich die Datei, wenn sie gespeichert wurde und der Name klar ist einfach noch mal speichern, dann mit ID. Das würde die Zeiten zwar verlängern, wäre aber eine Möglichkeit. Schief gehts natürlich, wenn der User "Datei schließen" drückt und dabei speichert...
Bin echt verzweifelt und für Hilfe dankbar...
Gruß
Norman

10
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Benutzer
Anzeige
wollte erst gar nicht Antworten
23.07.2010 17:21:36
Tino
Hallo,
und hoffe dass ich diesmal eine Rückmeldung bekomme egal wie viele Projekte du hast
(den Beitrag schreiben kannst Du ja auch), sonst macht es mir keinen Spaß Dir zu antworten.
Habe mal etwas getestet (unter xl2007 u. xl2003),
So kannst Du abfragen ob der User den speichern unter Dialog aufruft oder
ob das speichern unter durch VBA erfolgt.
kommt als Code in DieseArbeitsmappe
Option Explicit 
 
Dim oKlasseExcel As Klasse1 
  
Private Sub Workbook_BeforeClose(Cancel As Boolean) 
  On Error Resume Next 
  If Not ActiveWorkbook.Saved Then 
    If Err.Number <> 0 Then GoTo ErrorH: 
        booClose = True 
        oTimer_ = Now + TimeSerial(0, 0, 1) 
        Application.OnTime oTimer_, "SaveAsMe_" 
  Else 
ErrorH: 
    Application.OnTime oTimer_, "SaveAsMe_", , False 
    Set oKlasseExcel = Nothing 
  End If 
End Sub 
 
Private Sub Workbook_Open() 
    Set oKlasseExcel = New Klasse1 
    Set oKlasseExcel.ExcelWatch = Application 
End Sub 
 
kommt als Code in Modul1
Option Explicit 
 
Public oTimer_ As Date, booClose As Boolean 
  
Sub SaveAsMe_() 
    MsgBox ActiveWorkbook.FullName 
      
    If booClose Then 
        booClose = False 
        ThisWorkbook.Close False 
    End If 
End Sub 
kommt als Code in Klasse1
Option Explicit 
 
Public WithEvents ExcelWatch As Application 
 
Private Sub ExcelWatch_WorkbookBeforeSave(ByVal Wb As Workbook, ByVal SaveAsUI As Boolean, Cancel As Boolean) 
Dim booUserSave As Boolean 
 
'check ob speichern unter erfolgt 
If SaveAsUI Then 
 
    With Application 
        booUserSave = LCase(.CommandBars("Document").Controls(1).Caption) = "&speichern" 
    End With 
 
 
    If booUserSave Then 
        MsgBox "User ruft jetzt den Dialog speichern unter auf" 
    Else 
        MsgBox "Speichern unter erfolgt durch VBA" 
    End If 
     
End If 
 
If Wb.FullName = ThisWorkbook.FullName Or Not booUserSave Then Exit Sub 
 
If Not SaveAsUI Then 
    Call SaveAsMe_
Else 
    oTimer_ = Now + TimeSerial(0, 0, 1) 
    Application.OnTime oTimer_, "SaveAsMe_" 
End If 
  
End Sub 
 
 

Gruß Tino
Anzeige
AW: wollte erst gar nicht Antworten
24.07.2010 11:16:28
norman
Hi Tino,
ok, anschiss angekommen :) So, ich bin gerade den Code am testen und verstehe eins nicht:
booUserSave = LCase(.CommandBars("Document").Controls(1).Caption) = "&speichern"
Wieso weiß man durch diese Code-Zeile, dass es sich um eine User-Speicherung handelt? Die Caption ist auch bei einem VBA-Save "&speichern". Irgendwie steh ich da auf der Leitung... Funktioniert bei mir auch nicht richtig. Der Rest vom Code ist cool, das mit dem Timer habe ich schon eingebaut und es funzt.
Aber das mit dem "&speichern" geht irgendwie nicht.
Gruß Norman
bei mir funzt es
24.07.2010 12:29:35
Tino
Hallo,
wenn der User auf speichern oder auf speichern unter drückt, dann ist
LCase(.CommandBars("Document").Controls(1).Caption) = "&speichern"
also True oder False.
Nun in Verbindung mit SaveAsUI kannst Du nun feststellen ob auf speichern unter gedrückt wurde.
Bei mir funktioniert es wunderbar.
Du musst es halt entsprechend einbauen und umsetzen damit Deine Makros entsprechend darauf reagieren oder angestoßen werden, die kenne ich ja nicht.
Kann natürlich nur richtig gehen wenn es als Addin eingebunden ist sonst funktioniert es mit dieser Zeile nicht, ist ja klar.
If Wb.FullName = ThisWorkbook.FullName Or Not booUserSave Then Exit Sub
Gruß Tino
Anzeige
AW: bei mir funzt es
24.07.2010 17:28:18
norman
Hi Tino,
ok, habe ich verstanden, da schau ich gleich nach. Ist den die Caption nach dem Speichern wieder anders? Also wenn der User nach dem Saven über Menü direkt sein VBA-Makro ausführt (z.B. per Button)?
Viele Grüße
AW: bei mir funzt es
24.07.2010 18:42:23
Tino
Hallo,
bei meinen versuchen funktioniert dies.
Habe glaube ich gerade festgestellt,
dass SaveAsUI nur True ist wenn der Dialog speichern unter auf geht.
Dies ist ja beim speichern unter mit VBA nicht der Fall, also kann man den ganzen gram sich sparen und nur SaveAsUI abfragen.
Gerade nochmal in die Hilfe gesehen, da steht es ja auch, Schei…
"SaveAsUI True, wenn das Dialogfeld Speichern unter angezeigt wird."
Gruß Tino
Anzeige
AW: bei mir funzt es
24.07.2010 19:23:01
norman
Hi,
ok, das mit dem SaveAsUI stimmt, aber wenn nur Save aufgerufen wird ist es für mich wichtig zu erfahren, ob aus dem Menü oder von VBA. Da hilft mir Deine Technik. Ich habe überlegt die Caption einfach nach dem Saven auf einen anderen Wert zu setzen, dann müsste auch mein vorhergehendes Problem klappen. Melde mich sobald ich das weiß.
Eine wichtige Frage für die Zukunft. Gibt es die Caption für das Menü auch unter 2007/2010 oder muss ich das da wieder anders machen?
Viele Grüße
Norman
AW: bei mir funzt es
24.07.2010 19:54:48
Tino
Hallo,
"Gibt es die Caption für das Menü auch unter 2007/2010"
unter 2007 kann ich sagen ja, 2010 habe ich nicht.
Gruß Tino
Anzeige
Bei mir nicht...
25.07.2010 23:18:41
norman
Hi Tino,
also, habe es eingebaut, es geht aber nicht... Ich habe mal die Datei angehängt, mit der ich den Test mache: https://www.herber.de/bbs/user/70754.xls
Diese Datei speichert sich selbst nach S:. Zum Test noch Pfad in VBA anpassen.
LCase(wb.Application.CommandBars("Document").Controls(1).Caption) "&speichern" ist bei mir immer true, egal ob ich von VBA oder über Menü komme. Wie schaffst Du es, dass es bei Dir false ist?
Viele Grüße
Norman
AW: Bei mir nicht...
26.07.2010 09:01:20
Tino
Hallo,
ich dachte es geht darum ob der User speichern unter drückt?
Weil sonst verstehe ich nicht was der Sinn ist,
ob VBA speichert oder der User ist doch wurscht, kommt auf selbe raus.
https://www.herber.de/bbs/user/70755.zip
In der zip ist ein testfile und ein Addin zum testen.
Gruß Tino
Anzeige
AW: Bei mir nicht...
27.07.2010 13:36:28
norman
Hi Tino,
SaveAsUI funktioniert bei mir auch wie bei Dir. Das Problem liegt im SaveAs durch VBA. Das kommt nicht mit SaveAsUI = true rein, sondern mit false. Des weiteren ist der Dateiname, der durch das VBA-SaveAs angegeben wird nicht in beforeSave "sichtbar". Deswegen musste ich Deinen Timer einbauen, was auch funktioniert hat.
Inzwischen habe ich alle Konstellationen hinbekommen, es funktioniert bestens :) Vielen Dank an Dich Tino.
Gehe wie folgt vor:
1. SaveAsUI = true: User hat SaveAs gemacht, dann gehe ich mit meinem eigenen DateiSpeichernDialog dran und mache dann per VBA SaveAs.
2. SabeAsUI = false: Mehrere Möglichkeiten
2a. SaveAs durch VBA:
a: Wenn die Datei noch nicht gespeichert wurde (also per VBA eine neue angelegt wurde) ist der
Dateiname noch ohne : und ohne // oder \\. Das kann ich prüfen. Eine solche Datei ignoriere ich
b: Wenn schon ein Dateiname drin ist gibt es mehrere Möglichkeiten: Die Datei speichert sich selbst irgendo hin oder sie speichert eine geladene Datei irgendwo hin. Beides merke ich dadurch, dass ich über Deine TimerFunktion nach dem Speichern prüfe, ob der Dateiname jetzt ein neuer ist. Wenn nicht, dann war es ein normales Save. Falls unterschiedlich, dann hat sich die Datei selbst (bzw. die geladene Datei) irgendwo hingeschrieben. Das klappt dann auch, da eine Kopie einer Datei keine neue ID erhält, sondern die alte beibehält.
2b. Save durch VBA oder durch User: Läuft genau wie oben, funktioniert nämlich mit dem gleichen Code.
Dank Dir noch mal recht herzlich Tino für die Hilfe!
Viele Grüße
Norman
Anzeige

307 Forumthreads zu ähnlichen Themen

Anzeige
Anzeige
Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige