Hallo zusammen,
irgendwie komme ich nicht weiter, aber vielleicht kann jemand hier helfen.
Ich hatte bisher einen Bericht der monatliche alle Rechnungen für unsere Kunden an einem Stück ausgedruckt hat.
Jetzt möchte ich aber pro Kunde ein PDF erzeugen und natürlich die 160 Rechnungen als einzelne Dateien speichern.
Der Bericht: ABR 01_Rechnung+Einzelaufstellung hat als Kriterium wo man trennen könnte das Feld [ReNr-Belastung]
und das wäre dann auch der Dateiname für die PDF.
Beispiel: C:\Rechnungen\2016-0001.pdf
Alle Felder sind entweder in dem Bericht oder der davorliegenden Abfrage (wo alle Datensätze enthalten sind) enthalten.
Danke für Eure Tipps im voraus
Zitat von: Thomas_Klee am August 05, 2016, 23:49:06irgendwie komme ich nicht weiter, aber vielleicht kann jemand hier helfen.
Wo genau kommst du nicht weiter? - Du hast schon die einzelnen, relevanten Details korrekt zusammengesucht. Jetzt musst du sie nur noch zusammensetzen.
- Du öffnest ein Recordset mit den Daten deiner Abfrage.
- In einer Do-Loop-Schleife läufst du durch alle Datensätze.
- Für jeden Datensatz öffnest du den Bericht mit der aktuellen [ReNr-Belastung] als Kriterium.
- Du lässt den geöffneten Bericht mit Docmd.OutputTo als PDF ausgeben und schließt den Bericht wieder.
- Dann mit MoveNext weiter zum nächsten Datensatz im Recordset.
Das Problem ist das ich zwar mit den Access Bordmitteln relativ fit bin ... aber bei VBA eher Novize :-\
Hier mein Versuch:
'-----------------------------------------------------------------
' Bericht ABR_01_Rechnung und Einzelaufstellung als PDF speichern
' Abfrage: A_RE_GESAMT
' Bericht: ABR_01_Rechnungen
' Ziel: C:\Rechnungen\[RE].pdf
'-----------------------------------------------------------------
Private Sub Befehl0_Click()
Dim sql As String
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim Pfad As String
Dim strWHERE As String
sql = "SELECT [RE]FROM [A_RE_GESAMT]"
Set db = CurrentDb
Set rs = db.OpenRecordset(sql, dbOpenSnapshot)
Do Until rs.EOF
Pfad = "C:\Rechnung\" & rs.Fields("RE").Value & ".pdf"
strWHERE = "RE = " & rs!RE
DoCmd.OpenReport "ABR_01_Rechnung", acViewPreview, , strWHERE, acHidden
DoCmd.OutputTo acOutputReport, "ABR_01_Rechnung", acFormatPDF, Pfad, False
DoCmd.Close acReport, "ABR_01_Rechnung"
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub
Also das Skript macht jetzt folgendes:
Beim Starten kommen zwei Feldabfragen SMS und HR die so nicht kommen wenn ich die Abfrage oder den Bericht manuell öffne. Diese beiden Werte sind Bestandteil der Rechnungsnummer.
Danach speichert er einmal die Datei im richtigen Pfad mit der "ersten Rechnungsnummer", allerdings sind dann alle
Rechungen in dieser einen PDF und nicht pro Rechnung eine PDF.
Bei zweiten Durchlauf kommt dann der Debugger an dieser Stelle:
DoCmd.OutputTo acOutputReport, "ABR_01_Rechnung", acFormatPDF, Pfad, False
Muss ich an dem Bericht etwas ändern, der ja normalerweise einfach die Abfrage geöffnet hat und dann eine
Riesendatei erzeugt hat?
Moin,
ich habe deinen Code mal modifiziert:
'-----------------------------------------------------------------
' Bericht ABR_01_Rechnung und Einzelaufstellung als PDF speichern
' Abfrage: A_RE_GESAMT
' Bericht: ABR_01_Rechnungen
' Ziel: C:\Rechnungen\[RE].pdf
'-----------------------------------------------------------------
Private Sub btnRE_EinzelDruck_Click()
Dim strSQL As String
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strDatei As String, strWhere as String
Set db = CurrentDb
strSQL = "SELECT * FROM [A_RE_GESAMT]"
Set rs = db.OpenRecordset(strSQL, dbOpenSnapshot)
Do Until rs.EOF
strDatei = "C:\Rechnung\" & rs.Fields("RE").Value & ".pdf"
strWHERE = strSQL & " WHERE RE = " & rs!RE
DoCmd.OpenReport "ABR_01_Rechnung", acViewDesign
Reports!ABR_01_Rechnung.RecordSource = strWHERE
DoCmd.OpenReport "ABR_01_Rechnung", acViewPreview, , , acHidden
DoCmd.OutputTo acOutputReport, "ABR_01_Rechnung", acFormatPDF, strDatei, False
DoCmd.Close acReport, "ABR_01_Rechnung"
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub
Die Bezeichner habe ich "sprechend" geändert, für Access reservierte Begriffe (sql) geändert. Der Bericht erhält jetzt beim Öffnen jeweils die Zuweisung nur der gewählten RE.
Habe den Code allerdings nicht getestet ...
Hallo Jürgen,
erstmal dank für die Antwort. Habe jetzt dein Skript mal getestet. Es bleibt ebenfalls bei dem DoCMDoutput noch hängen.
In Access passiert folgende:
Er macht den Druckdialog auf, es kommen zwei Eingabefenster SMS und HR ... da ist mir noch nicht klar was er will, weil
wenn ich die Abfrage ja so öffne kommt die Frage nicht.
Und dann bleibt er mit der Fehlermeldung:Laufzeitfehler 2501 Die Aktion Output wurde abgebrochen stehen.
HILFE :-\
Kann es eventuell ein Problem sein, das das Feld RE so einen Wert hat:
SMS-HR-2016-0135
Würde dann auch erklären wo die beiden Abfragen SMS und HR herkommen könnten.
Zitat
Er macht den Druckdialog auf, es kommen zwei Eingabefenster SMS und HR ... da ist mir noch nicht klar was er will, weil
wenn ich die Abfrage ja so öffne kommt die Frage nicht.
Du beschreibst da 2 unterschiedliche Dinge. Per Code wird der Bericht geöffnet, die Abfrage (welche?) ist etwas anderes. Der Fehler deutet darauf hin, dass 2 benötigte Felder nicht im Bericht vorhanden sind.
Da mit meinem Code als Datenquelle für den Bericht alle Felder aus A_RE_GESAMT herangezogen werden, scheint eine weitere Tabelle in Relation zu setzen zu sein.
Ich glaube das Problem ist die SQL abfrage:
Ich habe den Code mal so angepasst:
Option Compare Database
'-----------------------------------------------------------------
' Bericht ABR_01_Rechnung und Einzelaufstellung als PDF speichern
' Abfrage: A_RE_GESAMT
' Bericht: ABR_01_Rechnungen
' Ziel: C:\Rechnungen\[RE].pdf
'-----------------------------------------------------------------
Private Sub btnRE_EinzelDruck_Click()
Dim strSQL As String
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strDatei As String, strWhere As String
Set db = CurrentDb
strSQL = "SELECT * FROM A_RE_GESAMT WHERE (((A_RE_GESAMT.[RE])='SMS-HR-2016-0135'));"
Set rs = db.OpenRecordset(strSQL, dbOpenSnapshot)
Do Until rs.EOF
strDatei = "C:\Rechnung\" & rs.Fields("RE").Value & ".pdf"
strWhere = strSQL & " WHERE RE = " & rs!RE
DoCmd.OpenReport "ABR_01_Rechnung", acViewDesign
Reports!ABR_01_Rechnung.RecordSource = strWhere
DoCmd.OpenReport "ABR_01_Rechnung", acViewPreview, , , acHidden
DoCmd.OutputTo acOutputReport, "ABR_01_Rechnung", acFormatPDF, strDatei, False
DoCmd.Close acReport, "ABR_01_Rechnung"
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub
Jetzt wird der Bericht zwar geöffnet aber er macht die Schleife nicht ;-(
Zwei Probleme in deinem Code:
1.) Du öffnest das Recordset für eine einzelne, konkrete Rechnungsnummer. Deshalb ist die Schliefe nach einen einzigen Durchlauf auch schon fertig.
2.) Die Rechnungsnummer als Kriterium für den Bericht musst du auch in Hochkommata einschließen.
... WHERE RE = '" & rs!RE & "'"
Letzteres war sicherlich die Ursache für die Parameterabfrage, die du vorher als Problem hattest.
Ich werde noch kirre ......
Meldung: Typen unverträglich ... Bericht kann nicht gerendert werden ;-(((
Habe den Code wie folgt angepasst:
Option Compare Database
'-----------------------------------------------------------------
' Bericht ABR_01_Rechnung und Einzelaufstellung als PDF speichern
' Abfrage: A_RE_GESAMT
' Bericht: ABR_01_Rechnungen
' Ziel: C:\Rechnungen\[RE].pdf
'-----------------------------------------------------------------
Private Sub btnRE_EinzelDruck_Click()
Dim strSQL As String
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strDatei As String, strWhere As String
Set db = CurrentDb
strSQL = "SELECT * FROM A_RE_GESAMT WHERE RE = '" & rs!RE & "'"
Set rs = db.OpenRecordset(strSQL, dbOpenSnapshot)
Do Until rs.EOF
strDatei = "C:\Rechnung\" & rs.Fields("RE").Value & ".pdf"
strWhere = strSQL & " WHERE RE = " & rs!RE
DoCmd.OpenReport "ABR_01_Rechnung", acViewDesign
Reports!ABR_01_Rechnung.RecordSource = strWhere
DoCmd.OpenReport "ABR_01_Rechnung", acViewPreview, , , acHidden
DoCmd.OutputTo acOutputReport, "ABR_01_Rechnung", acFormatPDF, strDatei, False
DoCmd.Close acReport, "ABR_01_Rechnung"
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub
Meinen ersten Hinweis hast du nicht umgesetzt. Das Recordset öffnest du mit einer Abfrage ohne Kriterien. Einfach nur mit SELECT * FROM deineAbfrage.
Dann gibt es noch ein Problem in deinem Code, das ich vorher nicht gesehen habe.
Diese Zeilen sind unnötig, du kannst sie löschen:
strWhere = strSQL & " WHERE RE = " & rs!RE
DoCmd.OpenReport "ABR_01_Rechnung", acViewDesign
Reports!ABR_01_Rechnung.RecordSource = strWhere
Die nächste Zeile änderst du wie folgt.
DoCmd.OpenReport "ABR_01_Rechnung", acViewPreview, , "RE = '" & rs!RE & "'" , acHidden
So wird dem Report direkt beim Öffnen das gewünschte Kriterium mitgegeben, ohne dass du den Entwurf ändern musst.
oh mann ..... wird nicht besser:
Option Compare Database
'-----------------------------------------------------------------
' Bericht ABR_01_Rechnung und Einzelaufstellung als PDF speichern
' Abfrage: A_RE_GESAMT
' Bericht: ABR_01_Rechnungen
' Ziel: C:\Rechnungen\[RE].pdf
'-----------------------------------------------------------------
Private Sub btnRE_EinzelDruck_Click()
Dim strSQL As String
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strDatei As String, strWhere As String
Set db = CurrentDb
strSQL = "SELECT * FROM A_RE_GESAMT"
Set rs = db.OpenRecordset(strSQL, dbOpenSnapshot)
Do Until rs.EOF
strDatei = "C:\Rechnung\" & rs.Fields("RE").Value & ".pdf"
DoCmd.OpenReport "ABR_01_Rechnung", acViewPreview, , "RE = '" & rs!RE & "'", acHidden
DoCmd.OutputTo acOutputReport, "ABR_01_Rechnung", acFormatPDF, strDatei, False
DoCmd.Close acReport, "ABR_01_Rechnung"
rs.MoveNext
Loop
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub
Reaktion:
Laufzeitfehler 2491
Die Aktion ist ungültig, da das Formular bzw. der Bericht nicht an eine Tabelle oder Abfrage gebunden ist.
Ich geben VBA vielleicht doch besser auf ;-(
ZitatLaufzeitfehler 2491
Die Aktion ist ungültig, da das Formular bzw. der Bericht nicht an eine Tabelle oder Abfrage gebunden ist.
Das ist nur noch eine Kleinigkeit. Du musst noch
A_RE_GESAMT (oder was immer du vorher benutzt hast) als Datenherlunft für den Report eintragen.
Heurka .... er macht es fast richtig.
Ich hätte vielleicht noch sagen müssen, das in der Abfrage für die Rechnungen natürlich x-Datensätze mit der gleichen Rechnungsnummer enthalten sein können und der Bericht (die Rechnung) jetzt nicht bei jedem Datensatz den Bericht drucken soll um ihn dann 20 x zu überschreiben.
Pro [RE] die x-Datensätze hat nur einmal den Bericht öffen, da hängt es momentan noch.
Noch ein Tipp?
Hallo,
schreib mal so:
.
.
.
strSQL = "SELECT distinct RE FROM A_RE_GESAMT"
.
.
.
Hallo Ich habe die Abhilfe so geschafft, das ich eine zusätzliche Abfrage erstellt habe, die die Rechnungsnummern gruppiert hat. Jetzt klappt der Code ;)
Aber ich sagte ja ganz am Anfang das ich eine .... VBA Novice bin...
So wie ich das Ganze verstehe brauch ich noch ein Function? um dann in einem Access (Riesen-)Makro sagen zu können:
Führ mir dieses Modul aus.
Bitte nicht lachen .... ich mach das wirklich das erste mal so ::)
Hallo,
das "distinct" und nur das Feld "RE" in der Select-Liste hat (hier) denselben Effekt wie eine gruppierende Abfrage... Das Recordset "rs" beinhaltet nur die Rechnungsnummern ohne Duplikate.
Wofür willst (brauchst) Du noch eine weitere Funktion ? Wenn auf den Button geklickt wird, startet die Ereignisprozedur "btnRE_EinzelDruck_Click()" und druckt alle Rechnungen separat hintereinander aus.
Voraussetzung ist, dass in der Eigenschaft(enzeile) "Beim Klicken" des Buttons "btnRE_EinzelDruck"
[Ereignisprozedur]
eingetragen ist.
btw: Schreib in alle Modulköpfe:
Option Compare Database
Option Explicit
und kompilier den Code (Debuggen/Kompilieren)
Evtl. auftretende Fehler müssen korrigiert werden.
Naja, ich will es ja gar nicht mittels Button starten, sondern in einem Makro, das tausend Dinge hintereinander macht:
Daten importieren, mit Preisverzeichnissen je Kunde hinterlegen, Rechnungsnummern fortlaufend erzeugen, Rechungen erzeugen, Anlagen erzeugen, [NEU],KST-Einnahmenübersicht erstellen, DATEV Excell-Datei ausgeben, Rechnungen auf erledigt setzen.
Und da wo [NEU] steht will ich meiner Controllerin den gefallen tun, das sie pro Re.Nr. jetzt eine Kombi aus Rechnung und Anlage gleich als PDF gespeichert mit dem Rechnungsname pro Rechnung bekommt.
Das alles habe ich ja jetzt mit Eurer Unterstützung geschafft ... ich müsste nur noch das Modul dann irgendwie in diesem langen Makro so starten das es automatisch läuft und nicht mit einem Ereignis-Button.
????????????????
Hallo,
Zitat von: Thomas_Klee am August 07, 2016, 21:24:45
so starten das es automatisch läuft und nicht mit einem Ereignis-Button.
erkläre bitte genauer, wie du dir das vorstellst.
Irgendein auslösendes Ereignis wird es doch wohl geben müssen.
Hallo,
Zitat von: Thomas_Klee am August 07, 2016, 21:24:45
... ich müsste nur noch das Modul dann irgendwie in diesem langen Makro so starten das es automatisch läuft und nicht mit einem Ereignis-Button.
vielleicht kommst Du durch Einsatz eines Makros mit dem Namen "Autoexec" zum Ziel. Dieses wird
automatisch beim Start der Datenbank aufgerufen. Im Makro steht die Funktion bzw. stehen die Funktionen, die im Modul enthalten sind. Vielleicht reicht es ja auch, Dein Makro in diesen Namen umzubenennen (mit dem Effekt, dass diese Aktion dann immer beim Start läuft).
Ansonsten ist auch denkbar, in einem Formular das Ereignis "Bei Zeitgeber" zu verwenden. Dort könnte der Aufruf Deiner Funktionen/Subs im Modul eingetragen werden. Diese Routine wird
automatisch aufgerufen in einem bei "Zeitgeberintervall" definierten Zeitabstand [Mikrosekunden].
Es wäre hilfreich, Wenn Du genauere Angaben zur Situation machst:
Wer soll was wann wie oft mit welchen Mitteln machen.
Harald
Hallo Thomas,
Zitatsondern in einem Makro, das tausend Dinge hintereinander macht:
1. Ein (ausser des erwähnten AutoExec-) Macro muss auch irgendwie gestartet werden.
2. Macros sind Sch...
Ich würde für 1000 Dinge besser 1000 Prozeduren schreiben. Diese können ja in einer
anderen Prozedur nacheinander aufgerufen werden (oder bei Bedarf auch einzeln).
gruss ekkehard