Hallo zusammen,
ich arbeite mit A03 (SP3) und Win 7 und wollte den Code
DoCmd.OutputTo acOutputReport, "Name des Berichts", acFormatSNP, Pfad & " \ Test.snp", false
benutzen, um einen Bericht als Snapshot-Datei auszugeben. Ich habe die Fehlermeldung erhalten, dass kein temporärer Speicher mehr auf der Festplatte verfügbar sei. Sehr unwahrscheinlich! Oder ist ein Bug schuld?
Alternativ könnte ich den Bericht als PDF ausgeben. Allerdings habe ich gelesen, dass die Erweiterung von Stefan Labans bei Win 7 abstürzt. Ist das heute auch noch so?
Kann mir jemand helfen?
Gruß
Max
Die Leerzeichen vor und hinter dem Backslash im Pfad sind so gewollt?
ZitatDie Leerzeichen vor und hinter dem Backslash im Pfad sind so gewollt?
Nein!
Und du hast Recht, ohne die Leerzeichen funzt es!
Dafür schon mal vielen Dank!
Nun habe ich noch das Problem/die Aufgabe, dass der Dateiname im o.g. Code automatisch generiert werden soll.
Der Dateiname besteht weitestgehend aus dem Access bekannten Projektnamen, etc und einer lauf. Nr. am Ende (01 bis max. 10). z.B. 18124455-02-s01.snp
Wie schaffe ich es mit Hilfe einer Schleife die höchste bisher vergebene Zahl zu ermitteln, um dann den Dateinamen der zu speichernden Datei um 1 zu erhöhen.
Gruß
Max
Hallo,
lass das mit der laufenden, nichts aussagenden Nummer bleiben.
Nimm lieber die Uhrzeit (evtl. noch mit Datum) in abgekürztem Format, z. B. 1559 für 15:59 Uhr
Mit der nichts aussagenen, lauf. Nummer arbeite ich nun seit über 20 Jahren und bin damit sehr zufrieden. Ich habe meine komplette Projektabwicklung darauf ausgerichtet.
Ich sehe ja ein, dass Access es einfacher hat, das Erstellungsdatum einfach an den Dateinamen zu hängen, um eindeutige Namen zu erzeugen.
Wenn ich z.B. 5 Beteiligte für einen gemeinsamen Termin anschreibe, dann geschieht das Dank entsprechender Vorlage innerhalb von 7 Minuten. Dann hätte ich 5 fast gleichlautende Dateien wie z.B. 18124455-02-s140119-1615.snp etc.
Viel zu lang, um diesen im Anschreiben unter dem Datum als Aktenzeichen zu führen. Und alle, die sich an der Korrespondenz beteiligen wollen, müssen das lange Aktenzeichen abtippen. Echt nervig und fehleranfällig.
Ich kann mir eine einzelne Ziffer besser merken bzw. einer Person zuordnen, als 10 Ziffern. Ebenso ist die Ziffer für mich nicht nur eine lauf. Nr., sondern stellt auch eine Priorität dar. Außerdem speichert Win 7 das Erstellungs- bzw. Änderungsdatum ohnehin direkt dem Dateinamen.
Gruß
Max
Hallo Max,
ZitatWie schaffe ich es mit Hilfe einer Schleife die höchste bisher vergebene Zahl zu ermitteln, um dann den Dateinamen der zu speichernden Datei um 1 zu erhöhen.
Ich würde dafür eine Hilfstabelle verwenden mit den benötigten
Fremdschlüsseln und einem Feld für die letzte höchste Nummer.
Da braucht es keine Schleife, nur ein DLookup.
gruss ekkehard
Zitatmit Hilfe einer Schleife
Da müsste man etwas haben, wo man Schleife laufen kann. Daneben ist das umständlich. DMax(...) + 1 macht es auch.
Zitatdass Access es einfacher hat, das Erstellungsdatum einfach an den Dateinamen zu hängen
Nö, eine Zahl anzuhängen ist mindestens genau so einfach.
Hallo,
@ ekkehard
Mir schwebt da eine Tab mit 3 Feldern+Id vor (Projktverz., UnterOrdner und Dateinr).
Mit Hilfe von Insert into würde ich den ersten DS einfügen wollen, mit Update Set würde ich die Dateinr aktualisieren.
Mit Hilfe von Dlookup könnte ich dann die Berichte als Snapshot autom. speichern. Oder gehts besser?
Muss ich mich heute mal dransetzen.
Schon mal vielen Dank an Euch.
Gruß
Max
ZitatDMax(...) + 1
Man (ich) soll halt schreiben was man meint :-[
Hallo,
ich stolpere gerade über folgendes Problem beim Zusammenbau der o.g. Befehlsstruktur.
Ich möchte den Wert der Variablen strUOrdner an die Prozedur SVDateiNr übergeben. Das funzt aber nicht.
Private Sub BHOrdnerÖffnen()
...
Const strUOrdner As String = "02-BH"
Call SVDateiNr(strUOrdner)
...
End Sub
Public Sub SVDateiNr()
Dim Akt_DateiNr As Integer
Dim NeueNr As Integer
Dim strUOrdner As String
Akt_DateiNr = Nz(DLookup("DateiNr", "tbl_SVDateien", "[ProOrdner] = '" & verz & "' and UOrdner = '" & strUOrdner & "'"), 0)
...
End Sub
Ich hoffe die Code-Schnipsel reichen.
Fehlermeldung: Fehler beim Kompilieren: Falsche Anzahl an Argumenten oder ungültige Zuweisung zu einer Eigenschaft
Markiert ist Call SVDateiNr(strUOrdner)
Gruß
Max
Hallo Max,
Na ja, du musst der Sub auch mitteilen, dass da ein Parameter ankommt.
Public Sub SVDateiNr(ByVal strUOrdner As String)
Und dann brauchst du auch keine zusätzliche Variable dafür deklarieren.
Public Sub SVDateiNr(ByVal strUOrdner As String)
Dim Akt_DateiNr As Integer
Dim NeueNr As Integer
Akt_DateiNr = Nz(DLookup("DateiNr", "tbl_SVDateien", "[ProOrdner] = '" & verz & "' and UOrdner = '" & strUOrdner & "'"), 0)
...
End Sub
gruss ekkehard
Hallo,
das funzt schon mal.
Nun ist mein Aufbau leider ziemlich verschachtelt und ich komme (wieder) mit der Weitergabe der Variablen durcheinander. Hier die vereinfachte Struktur (kein echter Code) der Prozeduren:
Private Sub Bericht1Öffnen() 'ein bestimmtes Dokument erstellen u. speichern
Call BHOrdnerÖffnen
Private Sub BHOrdneröffnen() 'Pfade einstellen
Call Function ScanProjBez
Function ScanProjBez() 'ProjOrdnernamen finden
End Function
Dim Pfad, strUordner, Dateiname
...
Call SVDateiNr(strUOrdner)
Public Sub SVDateiNr(ByVal strUOrdner As String)
'letzte DateiNr in Tabelle speichern
End Sub
End Sub 'BHOrdnerÖffnen
' Pfad u. Dateiname wird benötigt. (Fehlermeldung: Variable nicht definiert)
End Sub 'Bericht1Öffnen
Ich habe die eigentlichen Befehle weggelassen, da die einzelnen Prozeduren funktionieren. Ich hoffe, ihr kommt damit klar.
Gruß
Max
Zitat von: MaxP am Januar 15, 2019, 18:25:20
Nun ist mein Aufbau leider ziemlich verschachtelt und ich komme (wieder) mit der Weitergabe der Variablen durcheinander.
Ich weiß nicht ob deine "vereinfachte" Darstellung so sinnvoll ist, um deinen Code zu diskutieren. Insbesondere die "Weitergabe der Variablen" kann ich mit deinem Pseudocode nicht nachvollziehen.
Poste besser den echten Code. - Falls es sehr lang wird, u.u. auch einer angehängten Textdatei.
Moin,
ich wollte euch nur ein wenig Arbeit ersparen, aber vermutlich ist es so besser.
Zur Verdeutlichung: Es existieren ca. 9 Berichte, die in 3 Unterordnern als Snapshot automatisch gespeichert werden sollen. Dazu sollen die Berichte dann den Dateinamen aus der Tabelle auslesen und als Dokumentnamen ausgeben.
Der kompl. Pfad sieht z.B. so aus: M:\Eigene-Dateien-D5\Büro\Projekte-aktuell\18121213-Mustermann\02-BH\18121213-02-s02.snp
Hier die 4 Codes:
'Hier wird der Bericht geöffnet und als Snapshot abgespeichert.
Private Sub Befehl107_Click()
On Error GoTo Err_Befehl107_Click
Call BHOrdnerÖffnen
Dim stDocName As String
DoCmd.OutputTo acOutputReport, "Bericht1", acFormatSNP, Pfad & "\" & Dateiname, True
stDocName = "Bericht1"
DoCmd.OpenReport stDocName, acPreview
Exit_Befehl107_Click:
Exit Sub
Err_Befehl107_Click:
MsgBox Err.Description
Resume Exit_Befehl107_Click
End Sub
**********************************************
'Hier werden der Pfad zum Unterordner und der Dateiname definiert
Private Sub BHOrdnerÖffnen()
Call fktScanProjektbezeichnung
If Forms![SV-Verwaltung-neu]![verz] = "" Then Exit Sub
Dim Pfad As String
Const strUOrdner As String = "02-BH"
Dim Dateiname As String
Pfad = "M:\Eigene-Dateien-D5\Büro\Projekte-aktuell" & "\" & verz & "\" & strUOrdner
Dateiname = Format([BV-Auftragsdatum], "yymm") & Me.[BV-Nr] & "-" & strUOrdner & "-s" & _
DLookup("DateiNr", "tbl_SVDateien", "[ProOrdner] = '" & verz & "' and [UOrdner] = '" & strUOrdner & "'")
Call SVDateiNr(strUOrdner)
End Sub
********************************************
'Hier wird die Projektbezeichnung auf Win-Ebene ausgelesen
Function fktScanProjektbezeichnung()
Dim strProBez As String, strProNummer As String
Const strHOrdner As String = "M:\Eigene-Dateien-D5\Büro\Projekte-aktuell"
strProNummer = Format(Forms![SV-Verwaltung-neu]![Auftragsdatum], "yymm") & Forms![SV-Verwaltung-neu]![BV-Nr]
strProBez = Dir(strHOrdner & "\" & strProNummer & "*", vbDirectory)
'Debug.Print strProBez
If strProBez = "" Then MsgBox ("Verzeichnis noch nicht vorhanden!")
Forms![SV-Verwaltung-neu]![verz] = strProBez
End Function
********************************************
'Hier wird in eine separate Tabelle Projektbezeichnung, Unterordner und Dateinummer eingefügt bzw. aktualisiert
Public Sub SVDateiNr(ByVal strUOrdner As String)
Dim Akt_DateiNr As Integer
Dim NeueNr As Integer
Akt_DateiNr = Nz(DLookup("DateiNr", "tbl_SVDateien", "[ProOrdner] = '" & verz & "' and [UOrdner] = '" & strUOrdner & "'"), 0)
Debug.Print Akt_DateiNr
If Akt_DateiNr = 0 Then GoTo Einfügen
NeueNr = Akt_DateiNr + 1
'Debug.Print NeueNr
CurrentDb.Execute "UPDATE tbl_SVDateien" _
& " SET DateiNr = " & NeueNr & "" _
& " Where ProOrdner = '" & verz & "' and UOrdner = '" & strUOrdner & "'"
Exit Sub
Einfügen:
CurrentDb.Execute "Insert into tbl_SVDateien (ProOrdner, Uordner, DateiNr) Values ('" & verz & "' , '" & strUOrdner & "',1)"
End Sub
Das Problem ist, im ersten Code werden Variablen genutzt, die erst im 2. Code definiert werden und ich weiß nicht, wie ich die wieder in Code 1 "zurückbekomme".
Da ich VBA-Anfänger bin, entschuldigt bitte die holprig gestrickten Codes. Die DB entstand zu einer Zeit, wo ich noch weniger Ahnung von Access hatte. Ich bin schon happy, wenn es funktioniert.
Gruß
Max
Hallo Max,
Leider bin ich nicht sehr gut darin fremden Code zu verstehen, aber das
Prinzip kann ich vielleicht einigermassen erklären.
Nur Functions können einen Wert zurück liefern im Gegensatz zu Subs.
Private Sub VerwendeFct()
Dim Bla As String
Bla = Test
Debug.Print Bla
End Sub
Private Function Test() As String
Test = "ZusammengesetzterString"
End Function
Du brauchst beim Aufruf also eine Variable, die das Ergebnis einer Function
aufnimmt. Besser, "aufnehmen kann" -> Datentyp muss übereinstimmen.
Was mir an deinem Code ansonsten auffällt
1. die beiden Constanten "strHOrdner" und "strUOrdner" kannst du aus den
Prozeduren rausnehmen und sie im Modulkopf unterbringen. Dann kannst
du sie überall verwenden, - z.B. statt
Pfad = "M:\Eigene-Dateien-D5\Büro\Projekte-aktuell" & "\" & verz & "\" & strUOrdner
Pfad = strHOrdner & "\" & verz & "\" & strUOrdner
2. Es gibt eine Variable "verz", die allerdings nirgends deklariert ist. Dem
Code nach scheint das ein Formularfeld zu sein. Das solltest du dann aber
auch vollständig referenzieren; -
im Formularmodel mit
Me.verz
in einem allgemeinen Modul oder in einem anderen Formular mit
Forms![SV-Verwaltung-neu].verz
3. Dies hier
If strProBez = "" Then MsgBox ("Verzeichnis noch nicht vorhanden!")
Forms![SV-Verwaltung-neu]![verz] = strProBez
Ist das Absicht, dass das Feld u.o.a.U. geleert wird? Wolltest du nicht eher dies
If strProBez = "" Then
MsgBox ("Verzeichnis noch nicht vorhanden!")
Else
Forms![SV-Verwaltung-neu]![verz] = strProBez
End If
Ich hoffe, dass du damit erstmal weiter kommst, ansonsten gerne wieder melden.
gruss ekkehard
Hallo Ekkehard,
danke für deine Tipps.
Deine Pkt. 2 u. 3 habe ich entsprechend bei mir geändert.
Bei Pkt. 1 habe ich nur den Hauptpfad als Konstante in dem Kopf aufgenommen. Da es 3 Unterordner gibt, muss die Variable strUOrdner m.E. im Modul bleiben.
Eine Übergabe von Variablen müsste zumindest auch bei Public u. Private Sub möglich sein (s. Post #9+#10). Aber ansonsten bin ich diesbezüglich leider ahnungslos.
Gruß
Max
Hallo Max,
Zitatmuss die Variable strUOrdner m.E. im Modul bleiben.
Eine Konstante ist eben keine Variable. Wie willst du die 3 UOrdner
denn auseinanderhalten? Drei gleiche Prozeduren mit unterschiedlicher
Konstante? Da muss man sich was ausdenken, wie die variabel in die
Prozedur kommen.
ZitatEine Übergabe von Variablen müsste zumindest auch bei Public u. Private Sub möglich sein
Private oder Public ist dabei erstmal egal. Natürlich kann auch eine Sub
Werte
empfangen, aber nur eine Function kann auch einen Wert zurück
liefern.
gruss ekkehard
Zitat von: MaxP am Januar 16, 2019, 08:27:38
Das Problem ist, im ersten Code werden Variablen genutzt, die erst im 2. Code definiert werden und ich weiß nicht, wie ich die wieder in Code 1 "zurückbekomme".
Ich habe mir erlaubt, deinen Code zu überarbeiten und ein Video daraus zu machen.Allerdings das ganze auf Englisch; dazu habe ich auch deinen Code ins Englische "übersetzt".
Ich wollte eigentlich den Schwerpunkt auf die Übergabe von Werten zwischen verschiedenen Prozeduren legen, letztendlich hat sich der Code bei der Überarbeitung aber etwas anders entwickelt.Das Video habe ich bereits vor einigen Tagen aufgezeichnet, daher ist die weitere Diskussion hier, nach dem 16., darin nicht berücksichtigt.
Nun, genug der Vorrede, hier der Link zum Video: Let's Code - VBA - Nested, Dependent Procedures (https://youtu.be/-gu8lvhUK0g)
Zitat von: Beaker s.a. am Januar 16, 2019, 18:39:41
ZitatEine Übergabe von Variablen müsste zumindest auch bei Public u. Private Sub möglich sein
Private oder Public ist dabei erstmal egal. Natürlich kann auch eine Sub
Werte empfangen, aber nur eine Function kann auch einen Wert zurück
liefern.
Nicht ganz korrekt. Über ByRef-Argumente, kann auch eine Sub-Prozedur Werte an den Aufrufer zurückliefern. Allerdings würde ich das i.d.R. vermeiden, weil es weniger intuitiv lesbar ist.
(Das wollte ich ursprünglich auch in meinen Video zeigen, aber letztendlich hat sich das nach der Umstrukturierung als unnötig erwiesen.)
Hallo zusammen,
@ PhilS: schön, wenn ich auch ein wenig zurückgeben kann.
Mit der Übergabe von Variablen scheint das nicht so einfach zu sein. Deshalb habe ich mir bezüglich meines Codes (wie so häufig) damit beholfen, dass ich die betroffenen Variablen nun unsichtbar im Formular speichere.
Nun funzt es, wie es soll.
Vielen Danke an Euch.
Gruß
Max
Hallo Philipp,
ZitatNicht ganz korrekt. Über ByRef-Argumente, kann auch eine Sub-Prozedur Werte an den Aufrufer zurückliefern.
Danke für die Erinnerung an diese Tatsache. Hatte ich beim Schreiben
nicht daran gedacht; - wie so oft :-[ .
Verwende ich auch nur sehr selten.
gruss ekkehard
Zitat von: MaxP am Januar 21, 2019, 14:16:19
Mit der Übergabe von Variablen scheint das nicht so einfach zu sein. Deshalb habe ich mir bezüglich meines Codes (wie so häufig) damit beholfen, dass ich die betroffenen Variablen nun unsichtbar im Formular speichere.
Technisch ist die Übergabe von Variable an andere Prozeduren und zurück nicht besonders schwer. - Vielleicht behandle ich das nochmal explizit in einem anderen Video.Für deinen konkreten Fall war es nur nach einer sinnvollen Strukturierung des Prozessablaufes im Code einfach überflüssig.
Die Verwendung von Steuerelementen im Formular ist aus meiner Sicht so ziemlich die schlechteste Lösung dafür. - Nicht weil sie nicht funktionieren würde, sondern weil sie (Entwickler-)fehlerträchtig ist und trotz ihrer engen Kopplung nur schlecht nachvollziehbar ist.
Hallo Phil,
Dein angekündigtes Video (sofern in deutsch) würde mich interessieren. Wie und wo erfahre ich, wenn es wo online ist?
Gruß
Max
Zitat von: MaxP am Januar 23, 2019, 08:53:20Dein angekündigtes Video (sofern in deutsch) würde mich interessieren. Wie und wo erfahre ich, wenn es wo online ist?
Wenn ich das Video auf deutsch mache, werde ich es auf meinem YouTube-Channel codekabinett/de (https://www.youtube.com/channel/UCq9jRf468Yqhh0yNwrSbbGA) veröffentlichen.
In letzter Zeit mache ich die meisten Videos nur noch auf Englisch (codekabinett/EN (https://www.youtube.com/channel/UClXjFXc4TbZS82qR6NrMqjA)), weil sich der nicht unerhebliche Aufwand für die dort etwas größere Zielgruppe mehr lohnt. - Dieses Thema scheint mir aber so oft miss-/unverstanden zu sein, dass ich hier tatsächlich wieder mal ein Video auf Deutsch dazu machen könnte.