I require some work done - eMail Merge Feature
Hello Ollie,
This is my code.
I create a TXT file in my Fivewin program.
In Word I create a mail merge doc template (I hope this is the right name) and connect this to the data file, my txt file.
From the original template doc (docx) I always make a copy with Fivewin so that the user works with the copy.
With winexec() I call WORD and as parameter I pass the doc-file name.
Then the mass email I send with the option from WORD.
The STRTRAN I do to be sure that there are no wrong characters in the recipients file.
Regards,
Otto
First line in the Text file:
hStrg:= 'BRIEFANREDE; ... ;ORT;TELEFONNR;TELEFAXNR'
nHandle :=fopen( cDoc, O_READWRITE+S_EXCLUSIVE)
select mailing
go top
do while .NOT. Eof()
hStrg:= ;
(STRTRAN(ALLTRIM(mailing->email ), ";","," ))+";"+;
(STRTRAN(ALLTRIM(mailing->KATEGORIE), ";","," ))+";"+;
(STRTRAN(ALLTRIM(mailing->ANREDE), ";","," ))+";"+;
(STRTRAN(ALLTRIM(mailing->NAME), ";","," ))+";"+;
(STRTRAN(ALLTRIM(mailing->VORNAME), ";","," ))+";"+;
(STRTRAN(ALLTRIM(mailing->ZUSATZ), ";","," ))+";"+;
(STRTRAN(ALLTRIM(mailing->STRASSE), ";","," ))+";"+;
(STRTRAN(ALLTRIM(mailing->LKZ), ";","," ))+";"+;
(STRTRAN(ALLTRIM(mailing->PLZ), ";","," ))+";"+;
(STRTRAN(ALLTRIM(mailing->telefonnr ), ";","," ))+";"+;
(STRTRAN(ALLTRIM(mailing->telefax ), ";","," ))
text := fwrite(nHandle, hStrg + CRLF,)
Skip
enddo
This is my code.
I create a TXT file in my Fivewin program.
In Word I create a mail merge doc template (I hope this is the right name) and connect this to the data file, my txt file.
From the original template doc (docx) I always make a copy with Fivewin so that the user works with the copy.
With winexec() I call WORD and as parameter I pass the doc-file name.
Then the mass email I send with the option from WORD.
The STRTRAN I do to be sure that there are no wrong characters in the recipients file.
Regards,
Otto
First line in the Text file:
hStrg:= 'BRIEFANREDE; ... ;ORT;TELEFONNR;TELEFAXNR'
nHandle :=fopen( cDoc, O_READWRITE+S_EXCLUSIVE)
select mailing
go top
do while .NOT. Eof()
hStrg:= ;
(STRTRAN(ALLTRIM(mailing->email ), ";","," ))+";"+;
(STRTRAN(ALLTRIM(mailing->KATEGORIE), ";","," ))+";"+;
(STRTRAN(ALLTRIM(mailing->ANREDE), ";","," ))+";"+;
(STRTRAN(ALLTRIM(mailing->NAME), ";","," ))+";"+;
(STRTRAN(ALLTRIM(mailing->VORNAME), ";","," ))+";"+;
(STRTRAN(ALLTRIM(mailing->ZUSATZ), ";","," ))+";"+;
(STRTRAN(ALLTRIM(mailing->STRASSE), ";","," ))+";"+;
(STRTRAN(ALLTRIM(mailing->LKZ), ";","," ))+";"+;
(STRTRAN(ALLTRIM(mailing->PLZ), ";","," ))+";"+;
(STRTRAN(ALLTRIM(mailing->telefonnr ), ";","," ))+";"+;
(STRTRAN(ALLTRIM(mailing->telefax ), ";","," ))
text := fwrite(nHandle, hStrg + CRLF,)
Skip
enddo
Please can you clarify what you mean by "connect this" - what is in your txt file? : hStrg:= 'BRIEFANREDE; ... ;ORT;TELEFONNR;TELEFAXNR'In Word I create a mail merge doc template (I hope this is the right name) and connect this to the data file, my txt file.
? I don't follow.
Can you show me this line of code?With winexec() I call WORD and as parameter I pass the doc-file name.
I know WORD can send email, but how do you invoke it?Then the mass email I send with the option from WORD.
Once you are sure that there are no wrong characters in the cDoc file - what do you do with it then?
I need help with the invoking of Word and making it do all these things. I assume the mail merge doc template looks for the TXT file containing your data. So does this TXT file always have the same name so that Word doesn't say "Data file not found"?
Thanks for the help so far.
Many thanks
Ollie.
Using:
xHarbour Compiler build 1.2.1 (SimpLex) (Rev. 6406)
Borland C++ 5.5.1
FWH 9.04 (2009 Apr)
Ollie.
Using:
xHarbour Compiler build 1.2.1 (SimpLex) (Rev. 6406)
Borland C++ 5.5.1
FWH 9.04 (2009 Apr)
When there is no "<toreplace>" in the Word Doc, it places "Giordano Enrico Maria" at the beginning of the file.WORDREPLACE( oSel, "<toreplace>", "Giordano Enrico Maria" )
oWord:Visible = .T.
RETURN NIL
FUNCTION WORDREPLACE( oSel, cSrc, cRpl )
oSel:Start = 0
oSel:End = -1
oSel:Find:Execute( cSrc )
oSel:Range:Text = cRpl
RETURN NIL
How can one check to see if "<toreplace>" is in the document and only if it is, - WORDREPLACE( oSel, "<toreplace>", "Giordano Enrico Maria" )
i.e.
IF "<toreplace>" $ oSel??
WORDREPLACE( oSel, "<toreplace>", "Giordano Enrico Maria" )
ENDIF
(or the check could be done in the WORDREPLACE() function.) - But whats the syntax?[/quote]
Many thanks
Ollie.
Using:
xHarbour Compiler build 1.2.1 (SimpLex) (Rev. 6406)
Borland C++ 5.5.1
FWH 9.04 (2009 Apr)
Ollie.
Using:
xHarbour Compiler build 1.2.1 (SimpLex) (Rev. 6406)
Borland C++ 5.5.1
FWH 9.04 (2009 Apr)
It would be perfect if it could work like this:
1. Put your own merge codes in the WORD doc e.g. <<SURNAME>> or <<ALLTRIM(FIRSTNAME)>> (I just chose << >> - there is no special meaning)
2. Search the word DOC for the data between << and >>
3. Then Replace <<SURNAME>> with your data e.g. "Ollewagen "
and <<ALLTRIM(FIRSTNAME)>> with "Ollie"
1. Put your own merge codes in the WORD doc e.g. <<SURNAME>> or <<ALLTRIM(FIRSTNAME)>> (I just chose << >> - there is no special meaning)
2. Search the word DOC for the data between << and >>
3. Then Replace <<SURNAME>> with your data e.g. "Ollewagen "
and <<ALLTRIM(FIRSTNAME)>> with "Ollie"
Many thanks
Ollie.
Using:
xHarbour Compiler build 1.2.1 (SimpLex) (Rev. 6406)
Borland C++ 5.5.1
FWH 9.04 (2009 Apr)
Ollie.
Using:
xHarbour Compiler build 1.2.1 (SimpLex) (Rev. 6406)
Borland C++ 5.5.1
FWH 9.04 (2009 Apr)
Hello Ollie,
I did this but you have to use RTF format.
Since WORD 2000 ??? RTF format in WORD has a bug which MS never solved. Pictures are not stored as a link. All the code of a picture is inside the RTF doc. Now with harbour such a big document - sometimes many MB - would not be a problem but search/replace would be slow.
Then I tried with htm-format and word. But the users want pure word and all the functionality.
I can’t remember well but I think also WORDREPLACE is slow if you have many placeholders.
Therefore I use the original mail merge function of word.
I am sorry I can’t post the FW code because this part is still VB6.
But I post this maybe we can transform it.
To create a template – which the user can modify from within WORD I use:
(cDatenQuelle = recipients)
This is how a recipients file looks. It is a TXT file ASCII.
To merge and send only a single letter:
To send mass letters:
This opens word with the prepared letter.
To invoke I use the menu of WORD.
This is the same in VB6 what Enrico posted for FW.
Maybe with the help of the group we can transform the code to Fivewin.
Thanks in advance
Otto
I did this but you have to use RTF format.
Since WORD 2000 ??? RTF format in WORD has a bug which MS never solved. Pictures are not stored as a link. All the code of a picture is inside the RTF doc. Now with harbour such a big document - sometimes many MB - would not be a problem but search/replace would be slow.
Then I tried with htm-format and word. But the users want pure word and all the functionality.
I can’t remember well but I think also WORDREPLACE is slow if you have many placeholders.
Therefore I use the original mail merge function of word.
I am sorry I can’t post the FW code because this part is still VB6.
But I post this maybe we can transform it.
To create a template – which the user can modify from within WORD I use:
(cDatenQuelle = recipients)
This is how a recipients file looks. It is a TXT file ASCII.
ANREDE;NAME;VORNAME;STRASSE;LKZ;PLZ;ORT;ANZHG;DATUM;COMBO;BRIEFANREDE;TITEL;FIRMA1;FIRMA2
An;DEMO;HANS;PDEMOstTR. 25;A;1020;WIEN;150.00;10.06.2008;Scheck;Sehr geehrte Frau TEST;;;
Code: Select all
word.Documents.Add DocumentType:=wdNewBlankDocument
word.ActiveDocument.SaveAs FileName:=cDatei, FileFormat:=wdFormatDocument, LockComments:=False, Password:="", AddToRecentFiles:=True, WritePassword _
:="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, _
SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:=False
word.ActiveDocument.MailMerge.MainDocumentType = wdFormLetters
word.ActiveDocument.MailMerge.OpenDataSource Name:=cDatenQuelle _
, ConfirmConversions:=False, READONLY:=False, LinkToSource:=True, _
AddToRecentFiles:=False, PasswordDocument:="", PasswordTemplate:="", _
WritePasswordDocument:="", WritePasswordTemplate:="", Revert:=False, _
Format:=wdOpenFormatAuto, Connection:="", SQLStatement:="", SQLStatement1 _
:=""
word.ActiveDocument.MailMerge.EditMainDocument
word.ActiveDocument.MailMerge.OpenDataSource Name:=cDatenQuelle
word.ActiveDocument.MailMerge.Fields.Add Range:=Selection.Range, Name:="ANREDE"
word.Selection.TypeParagraph
word.ActiveDocument.MailMerge.Fields.Add Range:=Selection.Range, Name:="NAME"
word.Selection.TypeText Text:=" "
word.ActiveDocument.MailMerge.Fields.Add Range:=Selection.Range, Name:="VORNAME"
word.Selection.TypeParagraph
word.ActiveDocument.MailMerge.Fields.Add Range:=Selection.Range, Name:="STRASSE"
word.Selection.TypeParagraph
word.ActiveDocument.MailMerge.Fields.Add Range:=Selection.Range, Name:="LKZ"
word.Selection.TypeText Text:="-"
word.ActiveDocument.MailMerge.Fields.Add Range:=Selection.Range, Name:="PLZ"
word.Selection.TypeText Text:=" "
word.ActiveDocument.MailMerge.Fields.Add Range:=Selection.Range, Name:="ORT"
word.Selection.TypeParagraph
word.Selection.TypeParagraph
word.Selection.TypeParagraph
word.Selection.TypeParagraph
word.Selection.MoveUp Unit:=wdLine, Count:=10
word.Selection.HomeKey Unit:=wdLine
word.Selection.TypeParagraph
word.Selection.TypeParagraph
word.Selection.TypeParagraph
word.Selection.TypeParagraph
To merge and send only a single letter:
Code: Select all
Documents.Open FileName:=cDatei, ConfirmConversions:=False, READONLY _
:=False, AddToRecentFiles:=False, PasswordDocument:="", PasswordTemplate _
:="", Revert:=False, WritePasswordDocument:="", WritePasswordTemplate:="" _
, Format:=wdOpenFormatAuto
word.Visible = False
word.ScreenUpdating = False
word.DisplayAlerts = False
With word.ActiveDocument.MailMerge
.OpenDataSource Name:=cDatenQuelle
With .DataSource
.FirstRecord = 1
.LastRecord = 1
End With
.Execute Pause:=True
‘ This saves the merged letter to disk if you need it later.
word.ActiveDocument.SaveAs FileName:=PfadAblage + "anf" + Trim(Str(nbriefnr))
End With
‘ This part closes the original and brings the merged document to foreground and closes the original.
I found out that the user has to work with a copy otherwise you always have to assist setting up the letters.
docFound = True
For Each aDoc In Documents
If InStr(1, aDoc.Name, cOriginal, 1) Then
aDoc.Activate
ActiveDocument.Close (wdDoNotSaveChanges)
docFound = True
Exit For
Else
docFound = False
End If
Next aDoc word.DisplayAlerts = True
word.ScreenUpdating = True
word.Visible = True
‘ If you want to send as email.
If lEmail = True Then
word.ActiveWindow.EnvelopeVisible = True
Else
word.ActiveDocument.ActiveWindow.EnvelopeVisible = False
End If
Set word = Nothing
To send mass letters:
This opens word with the prepared letter.
To invoke I use the menu of WORD.
Code: Select all
word.Documents.Open cDatei
word.Visible = True
Set word = Nothing
Maybe with the help of the group we can transform the code to Fivewin.
Thanks in advance
Otto
- Enrico Maria Giordano
- Posts: 7355
- Joined: Thu Oct 06, 2005 8:17 pm
- Location: Roma - Italia
- Contact:
Ollie wrote:When there is no "<toreplace>" in the Word Doc, it places "Giordano Enrico Maria" at the beginning of the file.
How can one check to see if "<toreplace>" is in the document and only if it is, - WORDREPLACE( oSel, "<toreplace>", "Giordano Enrico Maria" )
Code: Select all
FUNCTION WORDREPLACE( oSel, cSrc, cRpl )
LOCAL lOk
oSel:Start = 0; oSel:End = -1
lOk = oSel:Find:Execute( cSrc )
IF lOk; oSel:Range:Text = cRpl; ENDIF
RETURN lOk
This works very nicely:
First make the data file that Word will merge with
This could be a function to let the user make his Word file and has the ability to insert his Merge fields:
You could then have another function that takes that user's word doc and does the merge and emails it off:
Thanks Enrico and Otto for putting me on the right track.
First make the data file that Word will merge with
Code: Select all
//Create the Datafile for the merge
NETUSE("DBMAIN")
SET FILTER TO Surname="Ackerman" //Just to test
DBMAIN->(DBGOTOP())
cFilename:="c:\mydata.txt"
FERASE(cFilename)
WriteLine("Surname;First Name;Email", cFilename ) //A function that writes the text at the end of cFilename
DO WHILE !EOF()
WriteLine(ALLTRIM(DBMAIN->Surname)+";"+ALLTRIM(FirstName)+";"+ALLTRIM(Email), cFilename )
DBMAIN->(DBSKIP(1))
ENDDO
CLOSE DBMAIN
Code: Select all
MSGINFO("Now make your letter")
oWord := CREATEOBJECT( "Word.Application" )
oDoc := oWord:Documents:Add() //Makes new doc.
oDoc:MailMerge:MainDocumentType:=0 //wdFormLetters=0 // sets the mail merge main document type
oDoc:MailMerge:EditMainDocument()
oDoc:MailMerge:OpenDataSource(cfilename)
oWord:Visible = .T.
Code: Select all
cLetter := cGetFile( "*.DOC", "Select a Letter", 1, ".\Letters\", .F., .T. )
oWord := CREATEOBJECT( "Word.Application" )
IF FILE(cLetter)
oDoc := oWord:Documents:Open( cLetter )
ENDIF
oDoc:MailMerge:MainDocumentType:=0 //wdFormLetters=0 // sets the mail merge main document type
oDoc:MailMerge:EditMainDocument()
oDoc:MailMerge:Destination:=2 //wdSendToEmail = 2 //See Word Enumerated Constants: http://msdn.microsoft.com/en-us/library/aa211923.aspx
oDoc:MailMerge:SuppressBlankLines:=.T.
oDoc:MailMerge:DataSource:FirstRecord:=1 // wdDefaultFirstRecord = 1
oDoc:MailMerge:DataSource:LastRecord:=-16 //wdDefaultLastRecord = -16
oDoc:MailMerge:MailAddressFieldName = "EMAIL"
oDoc:MailMerge:MailSubject = "Email sent at: "+TIME()
oWord:ActiveDocument:MailMerge:Execute(.F.) // Pause:=False
oDoc:Close( 0 )
oWord:Quit()
Many thanks
Ollie.
Using:
xHarbour Compiler build 1.2.1 (SimpLex) (Rev. 6406)
Borland C++ 5.5.1
FWH 9.04 (2009 Apr)
Ollie.
Using:
xHarbour Compiler build 1.2.1 (SimpLex) (Rev. 6406)
Borland C++ 5.5.1
FWH 9.04 (2009 Apr)
- RAMESHBABU
- Posts: 591
- Joined: Fri Oct 21, 2005 5:54 am
- Location: Secunderabad (T.S), India
Hello dutch, hello Rameshbabu,
Till now I used VB6 to work with WORD. Therefore I have no
ready application. I only did some tests.
This is what I tried so far.
Not much but maybe it is of some help for starters.
Regards,
Otto
My dataSource steuer.doc
EMAIL@KATEGORIE@ANREDE@NAME@LANDFELD@VORNAME@ZUSATZ@STRASSE@LKZ@PLZ@ORT@BRIEFANRED@TITEL@Z_HD@FIRMA@BEGLEITUNG@KIND1@KIND2@KIND3@KIND4@TELEFON@FAX
KURT,HÖLZL.lkz@SOMMER@An@HÖLZL@@KURT@@ROSENGASSE 11@A@1090@WIEN@Sehr geehrte Frau HÖLZL@@@@@@@@@1090@1090
Till now I used VB6 to work with WORD. Therefore I have no
ready application. I only did some tests.
This is what I tried so far.
Not much but maybe it is of some help for starters.
Regards,
Otto
My dataSource steuer.doc
EMAIL@KATEGORIE@ANREDE@NAME@LANDFELD@VORNAME@ZUSATZ@STRASSE@LKZ@PLZ@ORT@BRIEFANRED@TITEL@Z_HD@FIRMA@BEGLEITUNG@KIND1@KIND2@KIND3@KIND4@TELEFON@FAX
KURT,HÖLZL.lkz@SOMMER@An@HÖLZL@@KURT@@ROSENGASSE 11@A@1090@WIEN@Sehr geehrte Frau HÖLZL@@@@@@@@@1090@1090
Code: Select all
#include "FiveWin.ch"
#include "InKey.ch"
#include "xbrowse.ch"
STATIC aInhalt := {}
//----------------------------------------------------------------------------//
function Main()
LOCAL oWnd
LOCAL oBrw, oCol
LOCAL oFnt
LOCAL oBar
aInhalt := directory("*.doc*","D")
DEFINE FONT oFnt NAME "ARIAL" SIZE 6 ,15 BOLD
DEFINE WINDOW oWnd TITLE "Serienbrief" ;
FROM 0,0 TO 800,1024 PIXEL
oWnd:SetFont(oFnt)
//substr(oBrw:aArrayData[oBrw:nArrayAt,1],1,( len(oBrw:aArrayData[oBrw:nArrayAt,1])-4) )
oBar := TBar():New( oWnd, 65, 65, .T.,"TOP", )
oBar:l2007 = .T.
DEFINE BUTTON FILE "new.bmp" OF oBar ;
ACTION (makedoc(oBrw),;
ASIZE(aInhalt,0) ,;
aInhalt := directory("*.doc*","D"),;
oBrw:SetArray( ainHalt, .T. ),;
oBrw:refresh()) ;
PROMPT "Serienbrief"+CRLF+"erstellen"
DEFINE BUTTON FILE "compile.bmp" OF oBar ;
ACTION mailsend(oBrw);
PROMPT "Email" + CRLF + "senden"
DEFINE BUTTON FILE "end.bmp" OF oBar ;
ACTION oWnd:end();
PROMPT "Ende"
oBrw := TXBrowse():New( oWnd )
oBrw:nTop := 80
oBrw:nLeft := 20
oBrw:nBottom := 600
oBrw:nRight := 400
oBrw:SetArray( ainHalt, .T. )
oBrw:aCols[1]:cHeader := 'Source'
oBrw:aCols[1]:nWidth := 157
oBrw:aCols[2]:cHeader := 'Size'
oBrw:aCols[3]:cHeader := 'Date'
oBrw:nMarqueeStyle := MARQSTYLE_HIGHLROW
oBrw:nRowDividerStyle := 4
oBrw:lRecordSelector := .t.
//oBrw:bChange := {|| }
//oBrw:bLDblClick := {|| }
//oBrw:bKeyDown := {|nkey| iF( nkey = 13, test( oBrw ), ) }
oBrw:lHScroll := .f.
oBrw:CreateFromCode()
ACTIVATE WINDOW oWnd
return nil
func makedoc(oBrw)
LOCAL cDatei :=""
LOCAL oDoc
LOCAL oWord
LOCAL cfileDataSource := "steuer.doc"
LOCAL suchbeg := space(30)
LOCAL cAppPath := ""
cAppPath := cFilePath( GetModuleFileName( GetInstance( ) ) )
cfileDataSource := cAppPath+"steuer.doc"
if MsgGet( "Name:", "Name eingeben", @suchbeg,".\bitmaps\lupa.bmp" )
cDatei := cAppPath + ALLTRIM(suchbeg) //WORD 2007
msginfo(cDatei)
oWord := CREATEOBJECT( "Word.Application" )
oDoc := oWord:Documents:Add() //Makes new doc.
oDoc:SaveAs(cDatei)
oDoc:MailMerge:MainDocumentType:=0 //wdFormLetters=0 // sets the mail merge main document type
oDoc:MailMerge:EditMainDocument()
oDoc:MailMerge:OpenDataSource(cfileDataSource)
oWord:selection:TypeText("Prototype")
oWord:selection:TypeParagraph() // new line
oWord:selection:TypeParagraph() // new line
oDoc:mailMerge:Fields:add(oWord:selection:range , "EMAIL")
oWord:selection:TypeParagraph() // new line
oWord:selection:TypeParagraph() // new line
oDoc:mailMerge:Fields:add(oWord:selection:range , "ANREDE")
oDoc:mailMerge:Fields:add(oWord:selection:range , "TITEL")
oWord:selection:TypeText(" ") // space between first and last name
oDoc:mailMerge:Fields:add(oWord:selection:range , "VORNAME")
oDoc:mailMerge:Fields:add(oWord:selection:range , "NAME")
oWord:selection:TypeText(" ") // space between first and last name
oWord:selection:TypeParagraph() // new line
oDoc:mailMerge:Fields:add(oWord:selection:range , "STRASSE")
oWord:selection:TypeParagraph() // new line
oDoc:mailMerge:Fields:add(oWord:selection:range , "PLZ")
oWord:selection:TypeParagraph() // new line
oDoc:mailMerge:Fields:add(oWord:selection:range , "ORT")
oWord:selection:TypeParagraph() // new line
oDoc:mailMerge:Fields:add(oWord:selection:range , "LANDFELD")
oWord:selection:TypeParagraph() // new line
oWord:selection:TypeParagraph() // new line
oWord:selection:TypeParagraph() // new line
oWord:selection:TypeParagraph() // new line
oDoc:mailMerge:Fields:add(oWord:selection:range , "BRIEFANRED")
oWord:selection:TypeParagraph() // new line
oWord:Visible = .T.
endif
return nil
func mailsend(oBrw)
LOCAL cLetter := ""
LOCAL oWord
LOCAL cAppPath :=""
LOCAL oDoc
if oBrw:aArrayData[oBrw:nArrayAt,1] <> "steuer.doc"
cAppPath := cFilePath( GetModuleFileName( GetInstance( ) ) )
cLetter := ALLTRIM(cAppPath + oBrw:aArrayData[oBrw:nArrayAt,1])
msginfo(cLetter)
oWord := CREATEOBJECT( "Word.Application" )
IF FILE(cLetter)
oDoc := oWord:Documents:Open( cLetter )
oWord:Visible = .T.
oDoc:MailMerge:MainDocumentType:=0 //wdFormLetters=0 // sets the mail merge main document type
//.OpenDataSource Name:=cDatenQuelle
oDoc:MailMerge:EditMainDocument()
// oDoc:MailMerge:Destination:=2 //wdSendToEmail = 2 //See Word Enumerated Constants: http://msdn.microsoft.com/en-us/library/aa211923.aspx
oDoc:MailMerge:SuppressBlankLines:=.T.
oDoc:MailMerge:DataSource:FirstRecord:=1 //wdDefaultFirstRecord = 1
oDoc:MailMerge:DataSource:LastRecord:=-16 //wdDefaultLastRecord = -16
// oDoc:MailMerge:MailAddressFieldName = "EMAIL"
// oDoc:MailMerge:MailSubject = "Email sent at: "+TIME()
oWord:ActiveDocument:MailMerge:Execute(.T.) // Pause:=False
//oDoc:Close( 0 )
ENDIF
//oWord:Quit()
else
msginfo("kein Serienbrief")
endif
return nil
I let the user "create" a Doc file linked to the data I produce.
I also let him Edit the page
I also let him merge the data to email or a new document.
Code below:
I also let him Edit the page
I also let him merge the data to email or a new document.
Code below:
Code: Select all
// ******************************************************************************************************
FUNCTION MSWORD_NEW( cAlias )
//This creates a new Word Doc that has the link to the data
LOCAL oDlg, oWord, oDoc
LOCAL cDataFile, cFilename := SPACE( 200 )
LOCAL cStr, i, cSubDir
LOCAL lOK := .F.
LOCAL lInuse := SELECT( cAlias ) <> 0
DEFINE DIALOG oDlg RESOURCE "DOCUMENT_NEW"
REDEFINE GET cFilename ID 10 OF oDlg UPDATE
REDEFINE BUTTON ID 30 OF oDlg DEFAULT ACTION ( lOK := .T. , oDlg:END() )
REDEFINE BUTTON ID 40 OF oDlg ACTION oDlg:END()
ACTIVATE DIALOG oDlg CENTER VALID ( lOK )
//Take any illegal characters out of cFilename
cFilename := STRTRAN( cFilename, "\", "" )
cFilename := STRTRAN( cFilename, "/", "" )
cFilename := STRTRAN( cFilename, ":", "" )
cFilename := STRTRAN( cFilename, "*", "" )
cFilename := STRTRAN( cFilename, "?", "" )
cFilename := STRTRAN( cFilename, "<", "" )
cFilename := STRTRAN( cFilename, ">", "" )
cFilename := STRTRAN( cFilename, "|", "" )
IF lOK .AND. ! EMPTY( cFilename )
cSubDir := ALLTRIM( defpath() ) + "Documents\" + ALLTRIM( cAlias )
IF ! IsDirectory( cSubDir )
i := MakeDir( cSubDir )
IF i == 0
//? "Directory", cSubDir, "successfully created"
ELSEIF i == 5
? "Folder already exists: ", cSubDir
ELSE
? "Error creating folder: ", cSubDir, "OS Error: " + LTrim( Str( i ) )
lOK := .F.
ENDIF
ENDIF
IF lOK = .T.
cFilename := ALLTRIM( cSubDir + "\" + ALLTRIM( cFilename ) )
//? cFilename
IF ! lInuse
NETUSE( cAlias )
ENDIF
cDataFile := NEEDFILE( "TXT" )
//? cDataFile
MSWORD_CREATEDATA( cDataFile, cAlias )
//WINEXEC("TASKKILL /F /IM WINWORD.EXE") //Kill any Existing WINWORD.EXE - when this crashes, the process is left open.
//INKEY(2) //Wait a bit
IF ! lInuse
( cAlias ) ->( DBCLOSEAREA() )
ENDIF
//Create a new doc that has the merge fields
//MSGINFO( "Now make your letter" )
oWord := CREATEOBJECT( "Word.Application" )
oDoc := oWord:Documents:Add() //Makes new doc.
oDoc:MailMerge:MainDocumentType := 0 //wdFormLetters=0 // sets the mail merge main document type
oDoc:MailMerge:EditMainDocument()
oDoc:MailMerge:OpenDataSource( cDataFile )
//VB6:
//word.ActiveDocument.SaveAs FileName:=cDatei, FileFormat:=wdFormatDocument, LockComments:=False, Password:="", AddToRecentFiles:=True, WritePassword _
// :="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, _
// SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:=False
//Method:
//SaveAs(FileName, FileFormat, LockComments, Password, AddToRecentFiles, WritePassword, ReadOnlyRecommended, EmbedTrueTypeFonts, SaveNativePictureFormat, SaveFormsData, SaveAsAOCELetter)
oDoc:SaveAs( cFilename, 0, .F., "", .T., "", .F., .F., .F., .F., .F. ) //wdFormatDocument = 0
oWord:Visible = .T.
//oDoc:PrintOut( .F. ) - Method
ENDIF
ENDIF
RETURN
// ******************************************************************************************************
// ******************************************************************************************************
// ******************************************************************************************************
// ******************************************************************************************************
// ******************************************************************************************************
FUNCTION MSWORD_EDIT( cAlias )
LOCAL oSel
LOCAL oWord
LOCAL oDoc
LOCAL cSubDir := ALLTRIM( defpath() ) + "Documents\" + ALLTRIM( cAlias )
LOCAL lInuse := SELECT( cAlias ) <> 0
LOCAL cDatafile, cDocument
//oDoc:PrintOut( .F. ) - Method
//WINEXEC("TASKKILL /F /IM WINWORD.EXE") //Kill any Existing WINWORD.EXE - when this crashes, the process is left open.
//INKEY(2) //Wait a bit
/*
//Create a new doc that has the merge fields
MSGINFO("Now make your letter")
oWord := CREATEOBJECT( "Word.Application" )
oDoc := oWord:Documents:Add() //Makes new doc.
oDoc:MailMerge:MainDocumentType:=0 //wdFormLetters=0 // sets the mail merge main document type
oDoc:MailMerge:EditMainDocument()
oDoc:MailMerge:OpenDataSource(cfilename)
oWord:Visible = .T.
*/
cDocument := cGetFile( "*.DOC", "Select a Document", 1, cSubDir, .F., .T. )
IF FILE( cDocument )
IF ! lInuse
NETUSE( cAlias )
ENDIF
cDatafile := NEEDFILE( "TXT" )
MSWORD_CREATEDATA( cDatafile, cAlias, "1" ) //Just create one word.
IF ! lInuse
( cAlias ) ->( DBCLOSEAREA() )
ENDIF
oWord := CREATEOBJECT( "Word.Application" )
//oDoc := oWord:Documents:Open( "C:\FWH\_MyProgs\PGA\Bin\Letters\TEST.doc" )
oDoc := oWord:Documents:Open( cDocument )
//word.Documents.Add DocumentType:=wdNewBlankDocument
//oDoc:Range:InsertAfter( "<toreplace>" + CHR( 13 ) ) //Types this in the DOC
//oDoc:Select() //Selects ALL document
//oSel = oWord:Selection
//WORDREPLACE( oSel, "<toreplace>", "Giordano Enrico Maria" )
//oDoc:SaveAs("mm") //Saves the file as mm.docx
//VB6:
//word.ActiveDocument.SaveAs FileName:=cDatei, FileFormat:=wdFormatDocument, LockComments:=False, Password:="", AddToRecentFiles:=True, WritePassword _
// :="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, _
// SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:=False
//Method:
//SaveAs(FileName, FileFormat, LockComments, Password, AddToRecentFiles, WritePassword, ReadOnlyRecommended, EmbedTrueTypeFonts, SaveNativePictureFormat, SaveFormsData, SaveAsAOCELetter)
//oDoc:SaveAs("My Letter",0,.F.,"",.T.,"",.F.,.F.,.F.,.F.,.F.) //wdFormatDocument = 0
//VB6:
//word.ActiveDocument.MailMerge.MainDocumentType = wdFormLetters
//Method: ??
oDoc:MailMerge:MainDocumentType := 0 //wdFormLetters=0 // sets the mail merge main document type
//VB6:
//word.ActiveDocument.MailMerge.OpenDataSource Name:=cDatenQuelle _
// , ConfirmConversions:=False, READONLY:=False, LinkToSource:=True, _
// AddToRecentFiles:=False, PasswordDocument:="", PasswordTemplate:="", _
// WritePasswordDocument:="", WritePasswordTemplate:="", Revert:=False, _
// Format:=wdOpenFormatAuto, Connection:="", SQLStatement:="", SQLStatement1 _
// :=""
//oDoc:MailMerge:OpenDataSource("c:\testdata.txt")
//VB6:
//word.ActiveDocument.MailMerge.EditMainDocument
oDoc:MailMerge:EditMainDocument()
//VB6:
//word.ActiveDocument.MailMerge.OpenDataSource Name:=cDatenQuelle
oDoc:MailMerge:OpenDataSource( cDatafile ) //"c:\moredata.txt")
//VB6:
//word.ActiveDocument.MailMerge.Fields.Add Range:=Selection.Range, Name:="ANREDE"
//oDoc:MailMerge:Fields:Add(oDoc:Range(),"ANREDE")
//VB6:
//word.Selection.TypeParagraph
//oWord:Selection:TypeParagraph()
//VB6:
//word.ActiveDocument.MailMerge.Fields.Add Range:=Selection.Range, Name:="NAME"
//oWord:ActiveDocument:MailMerge:Fields:Add(oDoc:Range(),"NAME")
//VB6:
//word.Selection.TypeText Text:=" "
//oWord:Selection:TypeText("This is some text")
//VB6:
//With ActiveDocument.MailMerge
// .Destination = wdSendToEmail
// .SuppressBlankLines = True
// With .DataSource
// .FirstRecord = wdDefaultFirstRecord
// .LastRecord = wdDefaultLastRecord
// End With
// .Execute Pause:=False
//End With
oDoc:MailMerge:Destination := 0
//wdSendToEmail = 2 //See Word Enumerated Constants: http://msdn.microsoft.com/en-us/library/aa211923.aspx
//wdSendToFax 3
//wdSendToNewDocument 0
//wdSendToPrinter 1
oDoc:MailMerge:SuppressBlankLines := .T.
oDoc:MailMerge:DataSource:FirstRecord := 1 // wdDefaultFirstRecord = 1
oDoc:MailMerge:DataSource:LastRecord := - 16 //wdDefaultLastRecord = -16
oDoc:MailMerge:MailAddressFieldName = "EMAIL"
// oDoc:MailMerge:MailSubject = "Email sent at: " + TIME()
// oWord:ActiveDocument:MailMerge:Execute( .F. ) // Pause:=False
//oWord:Visible = .T. //Makes Word active window
//oDoc:Close( 0 )
//oWord:Quit()
//oDoc:Select()
//oSel = oWord:Selection
//WORDREPLACE( oSel, "<amount", "R 10.00" )
//WORDREPLACE( oSel, "<name>", "Elaine" )
oWord:Visible = .T.
//oDoc:Close( 0 )
//oWord:Quit()
ENDIF //file not found
RETURN NIL
// ******************************************************************************************************
FUNCTION MSWORD_MERGE( cAlias )
LOCAL oSel, oWord, oDoc, oDlg
LOCAL cSubDir := ALLTRIM( defpath() ) + "Documents\" + ALLTRIM( cAlias )
LOCAL lInuse := SELECT( cAlias ) <> 0
LOCAL cDatafile, cDocument := ""
LOCAL cFilter := ""
LOCAL cSubject := SPACE( 100 )
LOCAL nDocOrEmail := 1
LOCAL lOk := .F.
LOCAL lCancelled:=.F.
IF ! lInuse
NETUSE( cAlias ) //For the Filter Function
ENDIF
DEFINE DIALOG oDlg RESOURCE "DOCUMENT_MERGE"
REDEFINE BUTTON ID 4007 OF oDlg ACTION ( cDocument := cGetFile( "*.DOC", "Select a Document", 1, cSubDir, .F., .T. ) ,oDlg:UPDATE())
REDEFINE SAY PROMPT cDocument ID 4001 OF oDlg UPDATE
REDEFINE BUTTON ID 4006 OF oDlg ACTION ( Filter( cAlias ), cFilter:=(cAlias)->(DBFILTER()) ,oDlg:UPDATE())
REDEFINE SAY PROMPT cFilter ID 4005 OF oDlg UPDATE
REDEFINE RADIO nDocOrEmail ID 4003, 4004 OF oDlg UPDATE //ON CHANGE (oDlg:UPDATE())
REDEFINE GET cSubject ID 4008 OF oDlg UPDATE WHEN (nDocOrEmail = 2)
REDEFINE BUTTON ID 30 OF oDlg DEFAULT ACTION ( lOk := Validate_Merge( cDocument, cFilter,nDocOrEmail,cSubject ) , oDlg:END() )
REDEFINE BUTTON ID 40 OF oDlg ACTION (lCancelled:=.T.,lOk:=.T.,oDlg:END())
ACTIVATE DIALOG oDlg CENTER VALID ( lOk )
IF ! lInuse
( cAlias ) ->( DBCLOSEAREA() )
ENDIF
//oDoc:PrintOut( .F. ) - Method
//WINEXEC("TASKKILL /F /IM WINWORD.EXE") //Kill any Existing WINWORD.EXE - when this crashes, the process is left open.
//INKEY(2) //Wait a bit
/*
//Create a new doc that has the merge fields
MSGINFO("Now make your letter")
oWord := CREATEOBJECT( "Word.Application" )
oDoc := oWord:Documents:Add() //Makes new doc.
oDoc:MailMerge:MainDocumentType:=0 //wdFormLetters=0 // sets the mail merge main document type
oDoc:MailMerge:EditMainDocument()
oDoc:MailMerge:OpenDataSource(cfilename)
oWord:Visible = .T.
*/
IF lOk == .T. .AND. lCancelled == .F.
IF ! lInuse
NETUSE( cAlias )
ENDIF
cDatafile := NEEDFILE( "TXT" )
MSWORD_CREATEDATA( cDatafile, cAlias , cFilter )
IF ! lInuse
( cAlias ) ->( DBCLOSEAREA() )
ENDIF
oWord := CREATEOBJECT( "Word.Application" )
//oDoc := oWord:Documents:Open( "C:\FWH\_MyProgs\PGA\Bin\Letters\TEST.doc" )
oDoc := oWord:Documents:Open( cDocument )
//word.Documents.Add DocumentType:=wdNewBlankDocument
//oDoc:Range:InsertAfter( "<toreplace>" + CHR( 13 ) ) //Types this in the DOC
//oDoc:Select() //Selects ALL document
//oSel = oWord:Selection
//WORDREPLACE( oSel, "<toreplace>", "Giordano Enrico Maria" )
//oDoc:SaveAs("mm") //Saves the file as mm.docx
//VB6:
//word.ActiveDocument.SaveAs FileName:=cDatei, FileFormat:=wdFormatDocument, LockComments:=False, Password:="", AddToRecentFiles:=True, WritePassword _
// :="", ReadOnlyRecommended:=False, EmbedTrueTypeFonts:=False, _
// SaveNativePictureFormat:=False, SaveFormsData:=False, SaveAsAOCELetter:=False
//Method:
//SaveAs(FileName, FileFormat, LockComments, Password, AddToRecentFiles, WritePassword, ReadOnlyRecommended, EmbedTrueTypeFonts, SaveNativePictureFormat, SaveFormsData, SaveAsAOCELetter)
//oDoc:SaveAs("My Letter",0,.F.,"",.T.,"",.F.,.F.,.F.,.F.,.F.) //wdFormatDocument = 0
//VB6:
//word.ActiveDocument.MailMerge.MainDocumentType = wdFormLetters
//Method: ??
oDoc:MailMerge:MainDocumentType := 0 //wdFormLetters=0 // sets the mail merge main document type
//VB6:
//word.ActiveDocument.MailMerge.OpenDataSource Name:=cDatenQuelle _
// , ConfirmConversions:=False, READONLY:=False, LinkToSource:=True, _
// AddToRecentFiles:=False, PasswordDocument:="", PasswordTemplate:="", _
// WritePasswordDocument:="", WritePasswordTemplate:="", Revert:=False, _
// Format:=wdOpenFormatAuto, Connection:="", SQLStatement:="", SQLStatement1 _
// :=""
//oDoc:MailMerge:OpenDataSource("c:\testdata.txt")
//VB6:
//word.ActiveDocument.MailMerge.EditMainDocument
oDoc:MailMerge:EditMainDocument()
//VB6:
//word.ActiveDocument.MailMerge.OpenDataSource Name:=cDatenQuelle
oDoc:MailMerge:OpenDataSource( cDatafile ) //"c:\moredata.txt")
//VB6:
//word.ActiveDocument.MailMerge.Fields.Add Range:=Selection.Range, Name:="ANREDE"
//oDoc:MailMerge:Fields:Add(oDoc:Range(),"ANREDE")
//VB6:
//word.Selection.TypeParagraph
//oWord:Selection:TypeParagraph()
//VB6:
//word.ActiveDocument.MailMerge.Fields.Add Range:=Selection.Range, Name:="NAME"
//oWord:ActiveDocument:MailMerge:Fields:Add(oDoc:Range(),"NAME")
//VB6:
//word.Selection.TypeText Text:=" "
//oWord:Selection:TypeText("This is some text")
//VB6:
//With ActiveDocument.MailMerge
// .Destination = wdSendToEmail
// .SuppressBlankLines = True
// With .DataSource
// .FirstRecord = wdDefaultFirstRecord
// .LastRecord = wdDefaultLastRecord
// End With
// .Execute Pause:=False
//End With
IF nDocOrEmail == 1
oDoc:MailMerge:Destination := 0 //New Document
ELSE
oDoc:MailMerge:Destination := 2 //Email
ENDIF
//wdSendToEmail = 2 //See Word Enumerated Constants: http://msdn.microsoft.com/en-us/library/aa211923.aspx
//wdSendToFax 3
//wdSendToNewDocument 0
//wdSendToPrinter 1
oDoc:MailMerge:SuppressBlankLines := .T.
oDoc:MailMerge:DataSource:FirstRecord := 1 // wdDefaultFirstRecord = 1
oDoc:MailMerge:DataSource:LastRecord := - 16 //wdDefaultLastRecord = -16
oDoc:MailMerge:MailAddressFieldName = "EMAIL"
oDoc:MailMerge:MailSubject = cSubject
oWord:ActiveDocument:MailMerge:Execute( .F. ) // Pause:=False
IF nDocOrEmail == 1
oWord:Visible = .T. //Makes Word active window
ELSE
oDoc:Close( 0 )
oWord:Quit()
ENDIF
//oDoc:Select()
//oSel = oWord:Selection
//WORDREPLACE( oSel, "<amount", "R 10.00" )
//WORDREPLACE( oSel, "<name>", "Elaine" )
//Word:Visible = .T.
//oDoc:Close( 0 )
//oWord:Quit()
ENDIF //lOK
RETURN NIL
// ******************************************************************************************************
STATIC FUNCTION Validate_Merge( cDocument, cFilter, nDocOrEmail,cSubject)
LOCAL lOk := .T.
IF EMPTY( cDocument ) .OR. ! FILE( cDocument )
lOk := .F.
MSGSTOP( "Select a document." )
ENDIF
IF lOk = .T.
IF nDocOrEmail==2.AND.EMPTY(cSubject)
lOk:=MSGYESNO("Email Subject not entered."+CRLF+CRLF+"Continue?")
ENDIF
ENDIF
IF lOk = .T.
IF EMPTY( cFilter )
lOk := MSGYESNO( "No filter has been selected." + CRLF + CRLF + "(All records will be used.)" + CRLF + CRLF + "Is this correct?" )
ENDIF
ENDIF
RETURN ( lOk )
// ******************************************************************************************************
STATIC PROCEDURE MSWORD_CREATEDATA( cDataFile, cAlias, cFilter )
//Create the data text file
LOCAL cStr, i
DEFAULT cFilter := ""
//These are the fieldname descriptions
/*
NETUSE( "FINFO" )
SETORDER("DBFFLDNUM")
cAlias := FILL( UPPER( ALLTRIM( cAlias ) ), LEN( FINFO->DBF ) )
FINFO->(DBSEEK(cAlias))
DO WHILE FINFO->DBF==cAlias .AND. !FINFO->(EOF())
cStr+=StrTran( ALLTRIM(FINFO->DESC) ,";","")+";"
FINFO->(DBSKIP(1))
ENDDO
*/
cStr := ""
FOR i := 1 TO ( cAlias ) ->( FCOUNT() )
cStr += StrTran( FieldName( i ), ";", "" ) + ";"
NEXT
cStr := LEFT( cStr, LEN( cStr ) - 1 ) //Take off last ";"
WriteLine( cStr, cDataFile ) //("Surname;First Name;Email", cDataFile )
IF cFilter="1"
//? "Write one line of data"
cStr := ""
FOR i := 1 TO ( cAlias ) ->( FCOUNT() )
cStr += ALLTRIM( StrTran( cStr( FieldGet( i ) ), ";", "" ) ) + ";"
NEXT
cStr := LEFT( cStr, LEN( cStr ) - 1 ) //Take off last ";"
WriteLine( cStr, cDataFile ) //("Surname;First Name;Email", cDataFile )
cFilter:=""
ELSE
//? "Run the filter",cAlias,cFilter
SELECT ( cAlias )
SET FILTER TO &cFilter
(cAlias)->(DBGOTOP())
DO WHILE !(cAlias)->(EOF())
//? (cAlias)->(RECNO())
cStr := ""
FOR i := 1 TO ( cAlias ) ->( FCOUNT() )
cStr += ALLTRIM( StrTran( cStr( FieldGet( i ) ), ";", "" ) ) + ";"
NEXT
cStr := LEFT( cStr, LEN( cStr ) - 1 ) //Take off last ";"
WriteLine( cStr, cDataFile ) //("Surname;First Name;Email", cDataFile )
(cAlias)->(DBSKIP( 1 ))
ENDDO
ENDIF
//? cDataFile
//cStr:=MEMOREAD(cDataFile)
//? cStr //WinExec(cDataFile)
RETURN
Many thanks
Ollie.
Using:
xHarbour Compiler build 1.2.1 (SimpLex) (Rev. 6406)
Borland C++ 5.5.1
FWH 9.04 (2009 Apr)
Ollie.
Using:
xHarbour Compiler build 1.2.1 (SimpLex) (Rev. 6406)
Borland C++ 5.5.1
FWH 9.04 (2009 Apr)
- RAMESHBABU
- Posts: 591
- Joined: Fri Oct 21, 2005 5:54 am
- Location: Secunderabad (T.S), India
- RAMESHBABU
- Posts: 591
- Joined: Fri Oct 21, 2005 5:54 am
- Location: Secunderabad (T.S), India