INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Jobs

Using my own MS Word 2013 document to start with

Using my own MS Word 2013 document to start with

(OP)
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

RE: Using my own MS Word 2013 document to start with

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.

RE: Using my own MS Word 2013 document to start with

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

RE: Using my own MS Word 2013 document to start with

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

RE: Using my own MS Word 2013 document to start with

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() && Use the Normal template 

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: https://msdn.microsoft.com/en-us/vba/word-vba/arti...

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.

RE: Using my own MS Word 2013 document to start with

(OP)
I appreciate your replies. I'll post back when I have the solution from your suggestions.

Thank you

Steve

RE: Using my own MS Word 2013 document to start with

(OP)
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

RE: Using my own MS Word 2013 document to start with

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

RE: Using my own MS Word 2013 document to start with

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.

RE: Using my own MS Word 2013 document to start with

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

RE: Using my own MS Word 2013 document to start with

(OP)
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

RE: Using my own MS Word 2013 document to start with

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

RE: Using my own MS Word 2013 document to start with

Quote (Steve)

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.

RE: Using my own MS Word 2013 document to start with

(OP)
Mike and Olaf, your last posts have been duly noted.

Thank you

Steve

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members!

Resources

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close