I let the user "create" a Doc file linked to the data I produce.
I also let him merge the data to email or a new document.
// ******************************************************************************************************
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