Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Word automation question
Message
De
31/05/2003 06:16:03
Cetin Basoz
Engineerica Inc.
Izmir, Turquie
 
 
À
30/05/2003 14:13:18
Information générale
Forum:
Visual FoxPro
Catégorie:
Autre
Divers
Thread ID:
00794194
Message ID:
00794843
Vues:
19
This message has been marked as the solution to the initial question of the thread.
>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

* Assuming VFP7 and later 'As ...' added to get help from IntelliSense
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

* Create a balloon object for feedback
Local loBalloon
loBalloon = oWord.Assistant.NewBalloon

With oDocument.MailMerge
  * Attach the data to the document
  .CreateDataSource("dummyfilename.doc",,,;
      "Customer_ID, Company, Contact_name")
  .EditDataSource

  * CreateDataSource inserted the table with an extra blank row
  loTable = oWord.ActiveDocument.Tables(1)
  * Now open the data source and put the data into the document
  With loBalloon
  	.Heading = 'Starting scan....'
  	.Show
  endwith
  Scan
    loRow = loTable.Rows.Add() && Add as if we had no extra at top
    
    For Ix = 1 To Fcount()
      loRow.Cells[ Ix ].Range.InsertAfter(;
        Trim(Eval(Fields(Ix)))) && Trans if not all char
    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
Çetin Basöz

The way to Go
Flutter - For mobile, web and desktop.
World's most advanced open source relational database.
.Net for foxheads - Blog (main)
FoxSharp - Blog (mirror)
Welcome to FoxyClasses

LinqPad - C#,VB,F#,SQL,eSQL ... scratchpad
Précédent
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform