Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Using my own MS Word 2013 document to start with 3

Status
Not open for further replies.

Steve-vfp9user

Programmer
Feb 5, 2013
337
GB
Hi

I have been reading up Tamar Granor & Della Martin's Automating Microsoft Word and have a question with regards to using a Word document that we have created with a preset header (that contains an image and header text) and also a preset footer (this contains business details and page number of pages).

The start of the coding from TG & DM looks like this:

Code:
#Define CR Chr(13)
#Define wdStyleTypeParagraph 1
#Define wdStyleNormal -1
#Define wdAlignParagraphLeft 0
#Define wdAlignParagraphCenter 1
#Define wdCollapseEnd 0

Use _Samples + "TasTrade\Data\Customer"
Local oWord, oDocument, oRange
Local oBodyStyle, oMajorHeadingStyle, oMinorHeadingStyle
oWord = Createobject("Word.Application")
oWord.Visible = .T.
oDocument = oWord.Documents.Add() && Use the Normal template
oRange = oDocument.Range()

* Set up styles. Base body style on Normal.

oBodyStyle = oDocument.Styles.Add( "Body", wdStyleTypeParagraph )
With oBodyStyle

More code here....

Having read through the document, I'm not sure what I need to change so I can use our document which is held at:

d:\ourdocuments\quotes\default.doc

I tried:

Code:
oDocument = GetObject("ourdocuments\quotes\default.doc")
oDocument = oWord.Documents.Open("ourdocuments\quotes\default.doc")

This gives an error of "oWord" not found.

The rest of the coding I can change to use the fields and data from a table etc so no problem there, it's just the original default document we would like to use. I can post the whole block of code if required albeit I'm not sure it's required.

Any pointers would be appreciated.

Thank you

Steve
 
How should oWord be created, if you don't do
Code:
oWord = Createobject("Word.Application")
?

If you open your template doc file and modify it, you modify your template. You should look at using oWord.Documents.Add(), then look up in VBA reference how to parameterize Add to add a document with a template, which should be a dot file or dotx file in more modern Word versions, not a doc.

Bye, Olaf.
 
Steve, your code looks OK to me. Given that the error message is "oWord not found", that would suggest that the oWord variable has gone out of scope. From the code you posted, it's not evident whether or not that's the case, but it is something you should check. Try suspending the program when the error occurs, then check to see if oWord still exists (look for it in the Locals window in the debugger).

A couple of other points:

- It's not clear what the GetObject() call is doing in the line before the one that gives the error. It seems to be redundant.

- Keep in mind that you need to pass the absolute path of the document to the Open method, even if the document exists in your VFP default directory or search path. Word doesn't know about those paths. (But you don't need to pass the path if the document is in Word's default directory).

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Take a look at Chapter 5 and you'll see that we cover using your own templates (which is what you should be doing, rather than using a DOC file).

Tamar
 
Once more, more explicitly said: Above code of the book will allow you to create a document with a template, too, you just have to take the hint:

Code:
oDocument = oWord.Documents.Add() && [highlight #FCE94F]Use the Normal template[/highlight]

No parameterization of the Add() method of the documents collection adds a new empty document based on normal.dot/normal.dotx.

To have another template you create a word document and save it as dotx (as you talk about Office 2013).

Now look at the reference about the Documents.Add() method:
Using a template means providing its full file name (including drive letter) as the first parameter, you can skip all the other parameters. The second parameter put to true (or .T. in VFP) would mean you add the template file to the current word session documents collection for editing it itself, not for using it as a template. But again, just skip this and further parameters and the template is loaded as the template of a new document.

So finally it would be as easy as
Code:
oDocument = oWord.Documents.Add("d:\ourdocuments\quotes\default.dotx") && Use the default.dotx template
But first save your default.doc as a default.dotx

Bye, Olaf.
 
I appreciate your replies. I'll post back when I have the solution from your suggestions.

Thank you

Steve
 
All

I have been working on a solution with some of the suggestions posted on this thread. Whilst I suspect my coding could be altered, the whole thing works and more so, exactly as we require it.

The whole object of this was to create a copy of a document that was already set up (like a template with headers and footers) then be able to add the required fields to it so the user could then type in whatever they wanted and save the document and also the fact that should the document already exist, then it shouldn't be overwritten by the process but just opened to be updated.

This is what I came upwith if it helps anyone else:

Code:
* Create a MS Word (Version 2013) document 

CLEAR

STORE SPACE(34) TO mqlongquote  &&  Used to store reference number for the quote e.g. SW-1234-17

USE MYQUOTES SHARED
GO myrecno  && myrecno is referenced from a record selected from a grid

STORE ALLTRIM(QLONGQUOTE) TO mqlongquote  && Store the quote reference to the variable

mfileandpath=SYS(5)+SYS(2003)+"\longquote\default.doc"  && This is the default document I have created

IF FILE(SYS(5)+SYS(2003)+"\longquote\"+mqlongquote+'.doc')  &&  If already exists, we don't want to overide it
	WAIT CLEAR
	nmessage=MESSAGEBOX("INFO: Long quote reference "+mqlongquote+" already exists. "+ ;
	  "Open the document now?"+SPACE(10), ;
	  4+64+0,"System Message")
	IF nmessage=7
		CLEAR
		RETURN
	ELSE
		DO OPENLONGQUOTE
		CLEAR
		WAIT CLEAR
		WAIT "Your MS Word document is now opening" WINDOW NOWAIT
		RETURN
	ENDIF

ELSE	&&	If no document exists, create a new one

	DO CREATELONGQUOTE

	WAIT CLEAR
	
	WAIT "You can now edit your MS Word document" WINDOW NOWAIT
ENDIF

CLOSE DATABASES
CLEAR
RETURN

***********************
PROCEDURE OPENLONGQUOTE
***********************

DECLARE INTEGER ShellExecute IN shell32.dll ;
  INTEGER hhdWin, ;
  STRING cAction, ;
  STRING cFileName, ;
  STRING cParams, ;
  STRING cDir, ;
  INTEGER nShowWin

lcFileName = mqlongquote+'.doc'

lcPath = SYS(5)+SYS(2003)+"\longquote\"

ShellExecute(0, "open", lcFilename, "", lcPath, 1) 

CLEAR

RETURN

*************************
PROCEDURE CREATELONGQUOTE
*************************

WAIT "Creating and opening a Free Text MS Word quote document Ref: "+ALLTRIM(mqlongquote)+ ;
  ", please wait...." WINDOW NOWAIT

COPY FILE SYS(5)+SYS(2003)+"\longquote\default.doc" TO SYS(5)+SYS(2003)+"\longquote\"+mqlongquote+'.doc'

LOCAL oDocument, oRange

oWord = Createobject("Word.Application")
oWord.Visible = .T.
oDocument = oWord.Documents.Open(SYS(5)+SYS(2003)+"\longquote\"+mqlongquote+'.doc')

USE MYQUOTES SHARED
GO myrecno

*  I am using variables to store the table data
*  as someone else may want to update the record
*  whilst the word document is being worked on

STORE SPACE(80)				TO mqlongquote
STORE CTOD("  /  /    ")	TO mquotedate
STORE SPACE(80)				TO mqpropcust
STORE SPACE(50)				TO msadd01, msitename, msadd02, msadd03, msadd04
STORE SPACE(15)				TO mspcode 
STORE SPACE(80)				TO mqsubject

*  Now store the record fields to the variables

STORE QLONGQUOTE 			TO mqlongquote
STORE QUOTEDATE				TO mquotedate
STORE QPROPCUST				TO mqpropcust
STORE SADD01				TO msadd01
STORE SITENAME				TO msitename
STORE SADD02				TO msadd02
STORE SADD03				TO msadd03
STORE SADD04				TO msadd04
STORE SPCODE				TO mspcode
STORE QSUBJECT				TO mqsubject

*  +CHR(9) TAB aligns the information on the word document

oRange = oDocument.Range()
oRange.InsertAfter("Quote Ref No.: "+CHR(9)+mqlongquote)
oRange.InsertParagraphAfter()
oRange.InsertAfter("Date: "+CHR(9)+CHR(9)+DTOC(mquotedate))
oRange.InsertParagraphAfter()
oRange.InsertAfter("Client: "+CHR(9)+CHR(9)+mqpropcust)
oRange.InsertParagraphAfter()
oRange.InsertAfter("Site: "+CHR(9)+CHR(9)+PROPER(msadd01))
oRange.InsertParagraphAfter()
oRange.InsertAfter(CHR(9)+CHR(9)+ALLTRIM(PROPER(msitename))+" "+ALLTRIM(PROPER(msadd02)))
oRange.InsertParagraphAfter()
oRange.InsertAfter(CHR(9)+ CHR(9)+ALLTRIM(PROPER(msadd03))+" "+ALLTRIM(PROPER(msadd04)))
oRange.InsertParagraphAfter()
oRange.InsertAfter(CHR(9)+CHR(9)+UPPER(mspcode))
oRange.InsertParagraphAfter()
oRange.InsertAfter("Subject: "+CHR(9)+mqsubject)

RETURN

I appreciate the guidance from those who posted.

Thank you

Steve
 
If I've understood your code right, what's missing is the saving of the file. You appear to be opening the default document as a template, then programmatically inserting your data, then leaving it open for the user to edit. That's fine. The trouble is that, sooner or later, the user is likely to hit the Save button, which will overwrite the original document. I assume that's not what you want. If that's correct, you need to programmatically save it under a new name before giving it to the user,

Also, on a minor point, I see you have taken my advice about passing the fully qualified filename to Word. Using SYS(5) and SYS(2003) for that is fine, but keep in mind you can also use FULLPATH(), which is slightly cleaner and has the advantage that it works for files anywhere in the VFP search path.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike, you overlook the fact the original default.doc is copied to a file named mqlongquote+'.doc'

The reason Mike may not have spotted it is because that isn't making use of templates the usual way. It feels wrong, though it might be what you want. So just to ensure I'll make one thing very clear: Any changes you do to default.doc will not affect any already copied versions of it. The real value of templates is, they are inherited by a document based on a template so changing them also changes all documents created with them.

It might be exactly what you want, eg when you create quotes in the sense of an estimate on a project, you might have some standard text you put in front of any quote you hand out, but then don't want past quotes to get changed when changing the template. Well, that is not the type of template Office has in mind when talking about templates, so that's where the confusion starts, as it is a totally understandable type of template, too. One that is not only concerned with layout and fonts, one that is quasi-static, but may change over long periods of time.

And don't get me wrong, it would work, that the documents inheriting from a real word template could all be different and stay different. It's just a preamble text or such a thing, which would also change retrospective, not the whole document will be erased and reset, when a default.dotx template is changed, but that may already be too much alteration you won't want to have. I wonder if Office allows a document based on a template to be disconnected from its template, but I never heard of such a feature. you could still do that, when you convert final documents to PDF, as that freezes all content of the document anyway, so PDF creation is kind of the necessary process step if your quotes (estimates) would be really template based. Sending a doc(x) as attachment also makes it unnecessary to send the normal.dot(x) along with it, it would be worth experimenting a bit what that really does.

Bye, Olaf.
 
You're right, Olaf. I did overlook the COPY FILE - even after re-reading the code two or three times. I guess I was distracted by all the Wait windows (which I feel are unnecessary, but that's another story). I do agree that it would be better to use a template in the way it is designed for.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Olaf and Mike

Please allow me to clarify:

The default.doc is the starting point for the actual business template that contains the header and footer details. This is never changed but makes it easier for the user to have a starting point. The default.doc never changes (But could be if telephone numbers, business address details change etc).

The copied document that has been pointed out, is the actual working document that the user can enter there own details and save it at their leisure.

So what we have is a starting point which is copied to another document (with a linked reference number) that the user can enter details when the document is called for again if one exists with the linked reference number, the users last entries will be present but if one does not exist, a new basic template is copied from the default.

I hope that makes sense and in answer to the question, yes, that is what we are after.

Just on a final note, the use of wait windows has been implemented due to the fact that there is a delay from the time the document is requested and before before the Word document opens. For some reason I cannot get the Word document to pop up so to speak, it remains on the taskbar

I forgot to mention we are using Windows 10, VFP9 with SP2 and Microsoft Office Word 2013.

Once again, I appreciate your time and feedback.

Thank you

Steve
 
Steve,

My point about the Wait windows was that it seemed unnecessary to tell the user "Your MS Word document is now opening" or "You can now edit your MS Word document" when the document is about to appear on the screen. However, if it really takes a long time for that to happen (more than, say, four or five seconds) then I can understand why you are doing this.

In any case, it's not a big issue, and shouldn't detract from your main question.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Steve said:
The default.doc never changes (But could be if telephone numbers, business address details change etc).

Well, that is what I mean with "quasi-static, but may change over long periods of time."

You surely never want old documents to change, once your business address changes. These are documents which reflect the state as it was when they were generated.

So what remains is you should just find another name to talk about this, as templates have another meaning in the sense Office uses them. If all the header and footer contain is your business relevant information like logo and address, that would qualify for a template, too. As said I am a bit unsure about the way docs inherit content from template files, so I just tried (without VFP, just manually) Changes made in a dotx template are not injected into a document based on an older version of the dotx template.

So you can use the Office template method without the need to copy files in VFP.

Creating a file from template is then made this way:

Code:
Local lcTemplate, lcNewdocx, loWord, loDocument

lcTemplate =SYS(5)+SYS(2003)+"\longquote\default.dotx"
lcNewdocx = SYS(5)+SYS(2003)+"\longquote\"+mqlongquote+".docx" && previously NOT found with FILE()
loWord = CreateObject("Word.Application")
loWord.Visible = .T.
loDocument = oWord.Documents.Add(lcTemplate)
loDocument.SaveAs(lcNewdocx)

And to open a document already existing and not just have it appear in the task bar:

Code:
Local lcOlddocx, loWord, loDocument

lcOlddocx = SYS(5)+SYS(2003)+"\longquote\"+mqlongquote+".docx" && previously found with FILE()
loWord = CreateObject("Word.Application")
loWord.Visible = .T.
loDocument = oWord.Documents.Open(lcOlddocx)

Don't use ShellExecute, you simply don't have control about what happens with the file you open. With explicit Word.Application automation you open the docx in there and make the application visible.

There's a lot more to say, but let's keep it at that for the moment.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top