PUBLIC oWordDocument *** set the LOCALEID to English nlLocaleId=sys(3004) && Save local id =sys(3006,1033) && We will be sending instructions in English select first_name, last_name,notes ; from (home()+"samples\data\employee") ; into cursor test application.datatoclip("test",reccount(),3) && Copy to clipboard delimited with tabs wait window nowait "Creating Word Document..." oWordDocument=getobject("","word.basic") && Create word object-if already running get it with oWordDocument .appshow && Show word app - Word 7.0 support .filenewdefault && New file, default template .toggleportrait && Toggle page orientation (This is a toggle !) Portrait -> Landscape .editpaste && Paste clipboard data .EditSelectAll && Select entire doc .TextTotable(1) && Convert text to table - tabs (1) (Word table) .editgoto("\Table") && Find the table .nextcell .prevcell && Trick to go to first cell and select - should be an easier way :) for ix= 1 to fcount() && Skip header row-replacing header values with fieldnames .insert(field(ix)) && VFP pasted clipdata padded with spaces - not sutable for merging .nextcell endfor .TableDeleteColumn && Delete extra column .nextcell scan for ix= 1 to fcount() if type(field(ix))="M" lcData = eval(field(ix)) .insert(lcData) endif .nextcell endfor endscan .TableDeleteRow && Delete extra added row .editgoto("t") && Locate first table .tableselecttable && Select the table .tablecolumnwidth(,,,,1) && Table columnwidth autofit - only last parm .t. * If want to do mailmerge with this inserted table lcTempFile = "c:\temp\T"+sys(2015) && Temp filename .filesaveas(lcTempFile,0) && Save as a word doc for mailmerge .fileclose(1) && Close saving * Datasource ready, now create mailmerge main document .filenewdefault && If already have a template doc .filenew(cTemplateName) .MailMergeOpenDataSource(lcTempFile+".doc") && Set saved file as data source for mailmerge (Directly a table could be set via ODBC) .MailMergeEditMainDocument && Activate the main document .Insert("Dear ") && Start writing .insertmergefield("first_name") && Insert a merge field - any field in data table .insert(" ") .insertmergefield("Last_name") .Insert(","+chr(13)) .Insert("...Some text here..."+chr(13)) .insertmergefield("Notes") && Memo field .Insert("...Some text here..."+chr(13)) .Insert("Thanks.") * .MailMergeToDoc && Merge to a new document - For printer .MailMergeToPrinter * .FileSaveAs("c:\temp\frmletters.doc") && If want to save * .Fileexit(2) && Exit no save - directly print and exit w/o save lcCaption = .windowname() endwith DECLARE integer FindWindow in WIN32API string cNull, string cWinName declare integer GetClassName in WIN32API integer hWnd, string @cClass, integer nMaxBuffer hWnd = FindWindow(0,"Microsoft Word - "+lcCaption) && Get word win handle lpClassName = space(200) nBufLen = GetClassName(hWnd,@lpClassName,200) lcClass = substr(lpClassName,1,nBufLen) && Get word classname wait clear do while FindWindow(lcClass,0)<>0 && Suspend VFP execution till word exits enddo clear dlls erase (lcTempFile+".*") **** Set the LocaleId to the previous value =sys(3006,val(nlLocaleId))I don't think this approach would be faster than using ODBC though (word operations are unfortunately slow whether you use wordbasic or VBA commands-problem we are accustomed to speed with VFP). Just a way to insert merge header data w/o ODBC. I hadn't upgraded the mailmerge class in files\classes sections but still faster than this one :) You may also try this code to compare speed :
************************************************** * Start of code ************************************************** PUBLIC oWordDocument *** set the LOCALEID to English nlLocaleId=sys(3004) && Save local id =sys(3006,1033) && We will be sending instructions in English WAIT window nowait "Creating Word Document..." && Inform user cDSN = "DSN=Visual FoxPro Tables;UID=;PWD=;" cSourceDb = "SourceDB=C:\Program Files\vfp50\SAMPLES\DATA\Testdata.dbc" cSourceType = ";SourceType=DBC;" cOther = "Exclusive=No;BackgroundFetch=No;Collate=Machine;" cConnection = cDSN+cSourceDB+cSourceType+cOther cSQLStatement = "SELECT * FROM employee" oWordDocument=createobject("word.basic") && Create word object WITH oWordDocument .appshow && Show word app - Word 7.0 support .filenewdefault && New file, default template - Will create datasource .MailMergeOpenDataSource(,,,1,,,,,,, cConnection, cSQLStatement) .MailMergeEditMainDocument && Activate the main document .Insert("Dear ") && Start writing .insertmergefield("first_name") && Insert a merge field - any field in data table .insert(" ") .insertmergefield("Last_name") .Insert(","+chr(13)) .Insert("...Some text here..."+chr(13)) .insertmergefield("Notes") && Memo field .insertpara .Insert("...Some text here..."+chr(13)) .Insert("Thanks.") lcCaption = .windowname() ENDWITH DECLARE integer FindWindow in WIN32API string cNull, string cWinName declare integer GetClassName in WIN32API integer hWnd, string @cClass, integer nMaxBuffer hWnd = FindWindow(0,"Microsoft Word - "+lcCaption) && Get word win handle lpClassName = space(200) nBufLen = GetClassName(hWnd,@lpClassName,200) lcClass = substr(lpClassName,1,nBufLen) && Get word classname wait clear do while FindWindow(lcClass,0)<>0 && Suspend VFP execution till word exits enddo clear dlls **** Set the LocaleId to the previous value =sys(3006,val(nlLocaleId)) ************************************************** * End of code **************************************************This one uses ODBC and links to employee table (with link it requeries the table everytime it's activated). Word tries to use source exclusive so you might prefer to select into a temptable first (as done in mailmerge class).