Hilfe: Serienbrief aus Access für eine ID öffnen

Hallo Experten,

ich habe in Access ein Formular erstellt, in dem diverse Daten zu jeweils einer Person gespeichert sind. Nun möchte ich über einen bereits angelegten Button einen Serienbrief für die Person öffnen, die mir gerade angezeit wird.

Kann mir jemand den notwendigen VBA-Code geben, sodass ich ihn nur noch einfügen muss?

Außerdem möchte ich, dass, sobald ich diesen Serienbrief öffne, in einem Feld des Formulars automatisch das heutige Datum angelegt wird.

Ich hoffe, ihr könnt mir helfen. Suche seit Stunden vergeblich nach einer Lösung.

Danke!!!

Cassie

Hallo Cassie,
gewöhnlich werden nur die Adressen für Serienbriefe in Access verwaltet, der Brief wird in Word verfasst und an alle oder ausgewählte Adressen verschickt. Für dieses Verfahren bin ich leider nicht der „Experte“.

Allerdings habe ich auch schon eine reine Access Lösung implementiert, die Berichten verwendet. Elegant ist aber etwas anderes:
Basierend auf der Tabelle kann ein Bericht angelegt werden, der im Detailblock die Adresse enthält. Der eigentlich „Kopf“ des Berichts bleibt leer, der „Fuß“ enthält das eigentliche Anschreiben, der Detailblock die Adresse wenn nicht Teile der Personendaten im Anschreiben vorkommen sollen. Andernfalls muß das komplette Schreiben im Detailblock aus „Literalkonstanten“ und Feldinhalten zusammengesetzt werden.
Bsp: =„fester text“ & Spaltenname & „Text geht weiter…“ kann als Label im Detailblock platziert werden.

Das Datum in Kurzschreibweise kann in Berichten über =Format(Date();„Short Date“) eingefügt werden.

Berichte können gefiltert werden: über die FilterOn Eigenschaft des Berichts und eine where Klausel könnte die Beschränkung auf einen Datensatz oder Brief erzwungen werden:
Reports(„Berichtsname“).FilterOn = True

Ausgegeben am Bildschirm wird der Bericht dann über:
Application.DoCmd.OpenReport „Berichtsname“ ,acViewPreview, , "Kundennr. = " & KundennrVariable

Fast schon peinlich, diese „Lösung“!

Hallo CassieT86

Am einfachsten wäre es, einen Serienbrief mit Hilfe von Word zu erstellen. Word kann Access-Daten als Steuerdatenquelle verwenden. Vorher könnte
eine entsprechende ‚Hilfstabelle‘ mit den selektierten
Daten gefüllt werden.
z.B.

Private Sub Befehl2_Click()
Dim varName As String
Dim varVorname As String
Dim SQL As String

varName = txtname.Value
varVorname = txtvorname.Value
On Error Resume Next

'Warnmeldung abschalten
DoCmd.SetWarnings False

'Hilfstabelle leeren, weil nur
'aktueller Dastensatz der Haupttabelle
'enthalten sein soll
SQL = „DELETE * FROM Hilfstabelle;“
DoCmd.RunSQL SQL

‚Tabelle mit aktuellen Werten füllen
SQL=„INSERT INTO Hilfstabelle (Name, Vorname)“ & _
"VALUES (‘ " & varName & " ‚,‘ " & varVorname & " ')"
DoCmd.RunSQL SQL

'Warnmeldung wieder einschalten
DoCmd.SetWarnings True
End Sub

Im Anschluss sollte sich genau ein Datensatz in der Hilfstabelle befinden. Für diese Hilfstabelle kann eine Abfrage in Access erstellt und abgespeichert werden und dann auch innerhalb von Word als Steuerdatei für Seriendruck verwendet werden.
Bei mehreren notwendigen Datensätzen darf das Leeren der Hilfstabelle natürlich auch nur einnmal vor dem ersten Datensatz erfolgen.

Ansonsten ist unter der URL:
http://www.access-stammtisch.de/wissen/2001-05/WrdDe…
ein Beispiel zu finden. Dieses ist allerdings mit einer älteren Access-Version (Access97) erstellt worden und müsste für aktuelle Access-Versionen angepasst werden. Aber vielleicht hilft es trotzdem.

Zur Frage mit dem aktuellem Datum:
Dieses kann man mit Hilfe der Funktion Now() erreichen.
Da hierbei neben dem aktuellen Datum auch die Zeit ausgegeben wird, kann dies auch erweitert werden:
Dim aktDatum As Date
aktDatum = Left(Now(),10)
Dies würde heute z.B. 11.11.2010 ausgeben.
Mit dieser Variable könnte ein entsprechendes Textfeld
gefüllt werden: Datum.Text

Dim aktDatum As Date
aktDatum = Left(Now(),10)
txtDatum.SetFocus
txtDatum.Text = aktDatum

Ich hoffe, das dies etwas geholfen hat.

Wolfgang

Hi Cassie,

eigentlich hast du doch alles, was du benötigts:
Im Feld des Users/der ID kannst du die Bedingung für die Abfrage auslesen und für das Datum- - - naja, mal die Hilfefunktion von Access getestet?
Aber trotzdem, schicke mir die Accessdatei und ich baue dir die Abfrage

Erstmal vielen Dank für die Antworten.
Habe mich aber anscheinend falsch ausgedrückt. Ich schilder den Sachverhalt nochmal:

Ich habe einen Serienbrief in Word erstellt. Über einen Button in Access öffnet dieser sich auch und verknüpft ALLE Datensätze meiner Abfrage mit diesem Brief. Dies funktioniert über folgenden Code:

Private Sub Befehl13_Click()

Dim strPfad As String

strPfad = Left(CurrentDb.Name, Len(CurrentDb.Name) - Len(Dir(CurrentDb.Name)))
FollowHyperlink (strPfad & „S_Erinnerung Zertifikat MA (Bewertung schon abgegeben).doc“)

End Sub

Weiterhin habe ich ein Formular, in dem die Datensätze einzeln angezeigt werden. Also wer hat welches Seminar gemacht, hat er schon eine Zertifikat abgegeben usw. In diesem Formular möchte ich nun auch einen Button erstellen, der mich wie oben mit dem Word-Serienbrief verknüpft. ABER er soll den Brief eben nur mit dem gerade im Formular angezeigten Datensatz verknüpfen. Und sobald ich auf den Button geklickt habe, soll in diesem Formular bei ebendiesem Datensatz das Datum ausgeben, an dem ich den Serienbrief geöffnet bzw. gedruckt habe. Somit würde ich ganz genau sehen, wann ich welchen Mitarbeiter an z. B. das Zertifikat erinnert habe.

Habe dieses Prinzip schon mal in einer anderen Datenbank gesehen, komme da aber leider nicht dran.

Viele Grüße,

Cassie

Hallo Cassie,

leider kann ich Dir keine fertige Vorlage liefern. Was Du Dir vorstellst ist relativ komplex und mit viel Arbeit verbunden. Eine Möglichkeit wäre Deine Adresse in eine Tabelle zu schreiben und diese Tabelle mit dem immer selben Serienbriefdokument in Word zu verknüpfen. Wenn Du dieses dann öffnest, hat Du die richtigen Daten dastehen. Das aktuelle Datum im Brief bekommst Du ja über ein Wordfeld direkt hinein.

Ansonsten müsstest Du Word fernsteuern und das ist nicht mit ein paar Zeilen Code erledigt. Hier fehlt mir auch die Erfahrung.

viele Grüße

Bernd

Hallo Cassie

Wenn ein Seriendruck mit Allen Datensätzen der entsprechenden Abfrage
funktioniert, dann sollte es doch auch möglich sein mit einer Abfrage, die nur genau einen Datensatz zurückgibt. Dazu würde ich eine Hilfstabelle erstellen und mittels entsprechenden SQL-Befehl (INSERT INTO)
den aktuellen Datensatz einfügen (vorher diese Tabelle leeren mit DELETE ). Wenn dazu noch eine Abfrage analog der Anderen
auf diese Hilfstabelle erstellt wird, sollte es doch möglich sein, mittels Word einen Serienbrief ausgeben zu lassen (bei einer Verknüpfung mit dieser Tabelle/Abfrage werden dann nur noch die Anzahl von Datensatze zum Drucken bereitgestellt die vorher selektiert wurden - Alle oder eben nur Einer -).
Wird für diesen Vorgang ein weiterer Button verwendet, so dient der eine Button dazu alle Sätze per Seriendruck zu drucken (dazu einfach alle Datensätze in die Hilfstabelle kopieren lassen) und der Andere eben nur für den momentan aktuellen Satz.

Damit das Datum im Formular erscheint, wenn ein entsprechender Serienbrief gedruckt wird, müssen die entsprechenden Daten z.B. in die Haupttabelle oder in einer verknüpften separaten Tabelle eingespeichert werden.

Jedesmal, wenn jetzt ein Satz gedruckt wird, würde ich per SQL-Befehl UPDATE das entsprechende Datum in die entsprechende Tabelle schreiben.
Wenn im Formularfeld dann ein entsprechendes Feld für dieses Datum erstellt wird, so sollte der entsprechende Wert dann auch erscheinen.

Ist solch ein Seriendruck bereits erfolgt (Datum vorhanden) und soll bei einem unbeabsichtigten
Betätigen des Buttons kein erneutes Drucken erfolgen und damit auch kein Aktualisieren des Datums), so kann dies mit Hilfe einer Boolschen Variablen abgefangen werden (Wenn Datum vorhanden, dann True anderenfalls False und Druck/Aktualisierung nur bei False).

Gruß Wolfgang

Hallo,
leider kann ich Dir nicht weiterhelfen.
Viele Grüße
Maike

Hallo Cassie,
ich muss dich leider enttäuschen. Zum einen habe ich keinen solchen Code (was meinst du überhaupt mit einem Serienbrief für eine Person??), zum anderen bin ich schon (gefühlt) vor Jahrzehnten von AccessBasic auf C umgestiegen und vergesse immer mehr von dem, was ich mal gewusst habe …
Tut mir leid, ich hoffe, du bekommst von anderer Seite noch die gewünschte Unterstützung!
(Und ich werde mich mal als „Access-Experte“ hier rausnehmen …)
Grüße
Burkhard

Hallo Cassie,

die Übergabe von Access an Word könnte man über folgendes Objekt lösen:

On Error Resume Next
AppActivate „Microsoft Word“
Set WordObj = GetObject(, „Word.Application“)

If Err = 429 Then
'If Application.IsCompiled = False Then 'Bei A-97, das NICHT MDE sein darf:
Programm-Pfad
Shell „C:\Programme\Microsoft Office\Office\WINWORD.EXE“, 3 'A97
vbMaximizedFocus) '=im Vollbild öffnen
ElseIf Application.IsCompiled = True Then 'Bei A-XP: Programm-Pfad Shell „C:\Programme\Microsoft Office\Office10\WINWORD.EXE“, 3 'XP
vbMaximizedFocus) '=im Vollbild öffnen 19.05.01 Das ist es!!!
End If

If Application.IsCompiled = False Then 'Bbei A-97, MsgBox „Diese Pause, weil Word für die folgenden Anweisungen zu langsam öffnet. Bitte quittieren.“
Else 'A-XP braucht die Pause nicht mehr (je nach Betriebssystem) End If AppActivate „Microsoft Word“ ', -1 ', -1 'crosoft Word" ', 0 ', -1 'WordObj 'AnwID '„Microsoft Word“ 'sichert, dass kein Code ausgeführt wird, bis „Word“ vollständig geladen ist End If On Error GoTo 0 'damit wird die vorherige Anweisung „On Error Resume Next“
ausser Kraft gesetzt
’ Switches to Word when it is allready open Set WordObj = GetObject(, „Word.Application“) 'Verweis auf ein Application Objekt, auf die Kopie von Word, die gerade offen ist With WordObj ’ Do all following comands on behalf of object Wordobj '.Visible = False ’ Make word not visible .Run MacroName:=„KPF2“
'.Visible = True ’ Make word visible
End With ’ WordObj

PS: Den VBA-Code habe ich aus dem Internet kopiert!

Für Rückfragen stehe ich gerne zur Verfügung

schöne Grüße
Stefan Klinger

Hollo Cassie,
es tut mir leid aber ich kann dir nicht helfen

Hallo Cassie,

ich komme mit der Anfrage nicht ganz klar. Ein Serienbrief macht doch nur Sinn, wenn ich ein und dieselbe Information an mehrere Personen sende. Erklär das doch bitte genauer, vielleicht meinst Du auch was anderes?

Gruß
JOGI

Hallo Experten,

ich habe in Access ein Formular erstellt, in dem diverse Daten
zu jeweils einer Person gespeichert sind. Nun möchte ich über
einen bereits angelegten Button einen Serienbrief für die
Person öffnen, die mir gerade angezeit wird.

Liebe/r Classie,
hat dir schon jemand geholfen? Wenn nicht: Du brauchst zuerst eine Abfrage, mit der du die Daten holst. Über eine Funktion kriegst du dann die Daten, die gerade auf dem Formulara angezeigt werden. Du brauchst dann noch eine Word-Vorlage, die du dann über Textmarken füllst!

Da das alles doch recht komplex ist, gehe ich noch nicht ins Detail. Ich schicke dir aber gern den Code, wenn du noch Interesse hast!

Gruß
Eckart

Kann mir jemand den notwendigen VBA-Code geben, sodass ich ihn
nur noch einfügen muss?

Außerdem möchte ich, dass, sobald ich diesen Serienbrief
öffne, in einem Feld des Formulars automatisch das heutige
Datum angelegt wird.

Ich hoffe, ihr könnt mir helfen. Suche seit Stunden vergeblich
nach einer Lösung.

Danke!!!

Cassie

Hallo,
ich habe noch ein altes VBA-Skript gefunden, das nur noch entsprechend angepasst werden muss. Das Skript rufst Du am besten über eine Befehlsschaltfläche im Formular auf. Voraussetzung ist allerdings, dass neben ACCESS auch WINWORD auf dem Rechner installiert ist. Die Vorgehensweise ist folgende: Man erstellt eine Dokumentenvorlage (*.dot) in WORD, in der beliebig viele Textmarken festgelegt werden, an die ACCESS die Feldinhalte der Datenbank übergibt. Das Skript „merkt“ im übrigen, ob WORD bereits gestartet ist, nötigenfalls wird es automatisch gestartet. Das erstellte Dokument kann im Anschluss gespeichert werden, ohne dass die Vorlage dadurch geändert wird. Ich hoffe. es hilft weiter. Hier das Skript:
Private Sub Eingangsbestätigung_Click()

On Error GoTo ErrWinWord

Dim objWordApp As Object ’ Verweis auf Microsoft Word.
Dim Bereich As Object ’ Verweis auf Bereich innerhalb des Dokuments (z.B. eine Textmarke)
Dim strVorlage As String

If Not IstWordGestartet Then
DoCmd.Hourglass True
Set objWordApp = CreateObject(„Word.Application“) ’ WinWord starten
DoCmd.Hourglass False
Else
Set objWordApp = GetObject(, „Word.Application“) ’ WinWord war schon gestartet
End If

objWordApp.Visible = True

’ neues Dokument basiert auf Vorlage öffnen
strVorlage = „Pfad\Beispielvorlage.dot“ ’ anpassen
objWordApp.Documents.Add Template:=strVorlage

’ zu den Textmarken springen und Felder einfügen
Set Bereich = objWordApp.ActiveDocument.Goto(What:=GotoBookmark, Name:=„Textmarke1“) ’ anpassen
Bereich.InsertAfter Me!Feldname1 ’ anpassen
Set Bereich = objWordApp.ActiveDocument.Goto(What:=GotoBookmark, Name:=„Textmarke2“) ’ anpassen
Bereich.InsertAfter Me!Feldname2 ’ anpassen

objWordApp.Activate ’ WinWord in den Vordergrund bringen

’ Verweise auf WinWord-Objekte freigeben.
Set Bereich = Nothing
Set objWordApp = Nothing

ExitWinWord:
Exit Sub

ErrWinWord:
Select Case Err.Number
Case 5101
MsgBox „Die Textmarke wurde in der Vorlage nicht gefunden.“, vbCritical
Case 429
MsgBox „Das OLE-Objekt für WinWord konnte nicht erstellt werden.“, vbCritical
Case 5137, 5151
MsgBox „Die Vorlage " & strVorlage & " wurde nicht gefunden.“, vbCritical
Case Else
MsgBox Err.Description, vbCritical
End Select
Resume ExitWinWord

End Sub

Private Function IstWordGestartet() As Boolean
’ Stellt fest, ob WinWord-97 gerade geladen ist

Dim obj As Object

On Error Resume Next
Set obj = GetObject(, „Word.Application“) ’ nach WinWord suchen
IstWordGestartet = (Err.Number = 0)
Set obj = Nothing

End Function

‘ Ab hier geht es nur noch darum, Fehler elegant abzufangen

Private Sub Befehl497_Click()
On Error GoTo Err_Befehl497_Click

DoCmd.GoToRecord , , acFirst

Exit_Befehl497_Click:
Exit Sub

Err_Befehl497_Click:
MsgBox Err.Description
Resume Exit_Befehl497_Click

End Sub
Private Sub Befehl498_Click()
On Error GoTo Err_Befehl498_Click

DoCmd.GoToRecord , , acLast

Exit_Befehl498_Click:
Exit Sub

Err_Befehl498_Click:
MsgBox Err.Description
Resume Exit_Befehl498_Click

End Sub
Private Sub Befehl499_Click()
On Error GoTo Err_Befehl499_Click

DoCmd.GoToRecord , , acNext

Exit_Befehl499_Click:
Exit Sub

Err_Befehl499_Click:
MsgBox Err.Description
Resume Exit_Befehl499_Click

End Sub
Private Sub Befehl500_Click()
On Error GoTo Err_Befehl500_Click

DoCmd.GoToRecord , , acPrevious

Exit_Befehl500_Click:
Exit Sub

Err_Befehl500_Click:
MsgBox Err.Description
Resume Exit_Befehl500_Click

End Sub
Private Sub Befehl501_Click()
On Error GoTo Err_Befehl501_Click

DoCmd.GoToRecord , , acNewRec

Exit_Befehl501_Click:
Exit Sub

Err_Befehl501_Click:
MsgBox Err.Description
Resume Exit_Befehl501_Click

End Sub

Gruß

Hartmut