>Cetin,
>
>Thanks for the extensive sample and other references. I just ran it and it is a lot slicker than my code. I'll 'really' try it on monday at the office.
>
>Just wanted to THANK YOU for your help. This is not the first time you've saved my butt.
>
>Thanks,
>
>Henry
>
>P.S. Just out of curiosity, can you tell me why in my code, it either puts the data WITH the field titles or it leaves a blank row ? how can I change it to just start at the 1st row.
>
>I still think I'd rather use your elegant .ConvertToTable approach.
Honestly couldn't understand your problem exactly. I'll try :)
"The problem is that I can get one of 2 results:
1- the 1st row is actually inserted into the column titles making the whole merge unusable"
From your code as I understand you mean the one extra blank row added automatically by CreateDataSource(), right ?
"2- if I force an Add() at the beginning, all rows are inserted properly except I am left with the 1st row BLANK. How can I specifically delete a row ?"
This related with first problem, you begin the insertion from 3rd row and 2nd row is blank, right ?
To delete a specific row you use its index and call delete. ie: Delete 2nd row which we know is blank (you can do this anytime, before inserting others, in the middle of insertion or after inserting others) :
loTable.Rows(2).Delete
Actually in word (and Excel etc) whenever you see a 'plural' property it's 99% (who knows there isn't one not fitting this rule:) a collection. Collections have an item property to access members but 'item' property is the default property of a collection so you may choose not to explicitly add 'item'. You can access members of a collection either by its index (intellisense only lists 'Index as Number') or by its name if there is one. Excel is a good example IMHO for this :
oExcel.ActiveWorkBook.WorkSheets(1) && Access by index if you know - faster
oExcel.ActiveWorkBook.WorkSheets('SheetName') && Access by name - key
Once you have access to a collection member you get an object. ie: Row from Rows, WorkSheet from WorkSheets. Having the object on hand you could use its PEM.
Row object exposes a Delete method and Rows(i) is a Row object so this is legal :
Rows(i).Delete
For the ease of use you might think a collection as an array keeping object references to objects.
"Off the topic I find this cool in VFP :) In VFP you could do this :
use customer
dimension arrRecords[reccount()]
scan
scatter name arrRecords[recno()]
endscan
? arrRecords[5].Company
go 5
? Customer.Company
Pass the array to another private data session, directly bind controlsources to expressions like :
thisform.arrPassedFromCaller[thisform.nCurrentrecord].Company
Edit and send back. Well at least I've one neat place utilizing this in a real world app. where with only buffering and alike seemed almost impossible to do."
Back to topic :)
Now all you need was to delete the 'extra' row. Before doing it one final note. Earlier I said you could delete it before or after inserting other rows. The only difference I'm aware of is :
-If you delete before insertion newly added row contents are also bold (header format)
-If you delete after insertion newly added row content format is regular
But with mailmerge it's not important at all. You might even autoformat that table to one of those fancy formats :)
Here is a revised version of your code :
Clear All
Select Top 10 cust_id, company, contact ;
from "data\customer" ;
into Cursor mmCursor ;
order By cust_id
Local oWord As 'Word.application', ;
oDocument As "Word.Document", ;
loTable As 'Word.Table', ;
loRow As 'Word.Row'
oWord = Createobject("Word.Application")
oWord.Visible = .T.
oWord.Activate
oDocument = oWord.Documents.Add
Local loBalloon
loBalloon = oWord.Assistant.NewBalloon
With oDocument.MailMerge
.CreateDataSource("dummyfilename.doc",,,;
"Customer_ID, Company, Contact_name")
.EditDataSource
loTable = oWord.ActiveDocument.Tables(1)
With loBalloon
.Heading = 'Starting scan....'
.Show
endwith
Scan
loRow = loTable.Rows.Add()
For Ix = 1 To Fcount()
loRow.Cells[ Ix ].Range.InsertAfter(;
Trim(Eval(Fields(Ix))))
Endfor
Endscan
With loBalloon
.Heading = 'Scan ended. OK to delete row 2.'
.Show
loTable.Rows(2).Delete()
.Heading = 'Activating main doc.'
.Show
endwith
.EditMainDocument
Endwith
PS: Visible and Activate at top just to show what's going on and we give feedback with a assitant balloon (and during debug do like that to make it easy to close word - not to leave invisible open Word instances in case of error). Normally having those 2 lines at bottom speeds the overall process (but this is not true for all Office automation codes. Sometimes having at top results are faster).
Cetin