Avoiding ActiveDocument

B

Beeawwb

Hi All,

I've been reading various posts mentioning avoiding using ActiveDocument, eg
Dim oDoc as Document
Set oDoc = Documents.Add(Filename:="NNN")

What I'm trying to get my head around is, this assumes that the document has
been saved, doesn't it? What if you're creating a brand new document for the
first time, or something like that?

I only ask because here at work, we load templates from our Intranet (e.g.
https://.../Domino/library/Standard...D2558CA256DC700098F69/$FILE/HADVICE+v2003.dot),
which always open as read only documents, and they never actually get saved
(we edit them, and then import them into our imaging system which does the
saves them in its native format). When I'm running macros to format these
documents before they get imported, I have to use oDoc.ActiveDocument to say
which document I'm formatting.

Is there any other way of doing this, or am I correct in assuming that I
must reference the ActiveDocument, and then set oDoc as nothing on exiting
the macro.

Thanks for your help,

-Bob
 
S

Shauna Kelly

Hi Bob

Yes, avoiding ActiveDocument is generally a good idea. The reason is that
Word is prone to having creative ideas about what constitutes the "Active"
document. Grabbing a reference to the document you know is the one you want
to work with, and using that reference, ensures that you are dealing with
the right document. It also helps prevent mistakes in your code when you
have more than one document open, and it makes the code easier to read.

With the Documents collection, in general you *Open* an existing document,
but you *Add* a new one.

To open an existing document you can do this:

dim oDoc as Document
set oDoc = Documents.Open(FileName:="blabla.doc" )
There are a dozen or so other parameters to the .Open method. Look up VBA
help for full details.

To create a new document you use the .Add method of the .Documents
collection, like this:

dim oDoc as Document
set oDoc = Documents.Add(Template:="asdf.dot")
There are several other parameters of the .Add method, also described in the
VBA help.

You can omit the Template parameter if you want to base your new document on
Normal.dot. But just for the record, this
set oDoc = Documents.Add
oDoc.AttachedTemplate = "mytemplate.dot"
is *not* the same as this
set oDoc = Documents.Add(Template:="mytemplate.dot")

As an example of how you might use all this, consider a case where you
wanted to create a new document and copy into it the first paragraph of text
from an existing document. You could do something like this:


Dim oExistingDoc As Document
Dim oNewDoc As Document

Set oExistingDoc = Documents.Open(FileName:="test1.doc", _
ReadOnly:=True, AddToRecentFiles:=False)

Set oNewDoc = Documents.Add(Template:="mytemplate.dot")

oNewDoc.Paragraphs(1).Range.FormattedText = _
oExistingDoc.Paragraphs(1).Range

oExistingDoc.Close SaveChanges:=False

The only time I ever use ActiveDocument is where I have a tool that is
initiated by the user, and I need to know what document the user has open
and wants to apply the tool to. In that case, I use
set oDoc = ActiveDocument
once, and thereafter work with oDoc.

Hope this helps.

Shauna Kelly. Microsoft MVP.
http://www.shaunakelly.com/word
 
R

Russ

Bob,
Dim oMyFirstDoc as Word.Document
Dim oMySecondDoc as Word.Document

Set oMyFirstDoc = Documents.Add...
Starts a new document (it may be based on a template (normal.dot by
default))
Set oMySecondDoc = Documents.Open...
Opens a saved document
See 'working with documents' in Word VBA help by typing in 'document'.


If you have more than one document available in Word, then setting each of
them to a document object name makes it less likely to be working on the
wrong document with activedocument and by definition the document doesn't
have to be active to be worked on, when referred to as a document object
name.
It doesn't matter whether they are already saved or not.
You can refer to specific document when they have been set to a document
object. Setting them to Nothing at the end of a subroutine, when they are
not needed anymore, frees up memory for other subroutines to use.

Or you can refer to them by filename.. Documents("Document1").Activate.

Your oDoc.ActiveDocument that you mentioned must have oDoc set to an
instance of the Word application object because that is the parent object of
activedocument object or property.
 
J

Jay Freedman

Reading between the lines -- please correct me if I'm wrong about this -- I
think Bob's setup is that he is indeed *opening* the template, which is
marked read-only; modifying the in-memory copy of the template, and passing
that in-memory copy to the imaging system to be saved. This is a seriously
bad idea.

Bob, the whole intention of templates in Word is that you *add* a document
*based on* a template, as shown in Shauna's example of the Documents.Add
method. The parameter you pass to the Add method is the name of the template
to use, but that template isn't open for modification -- all changes go into
the document. That document is the thing whose identity is stored in the
oNewDoc variable. After that, it doesn't matter whether oNewDoc is the
"active" document or some other document is "active"; any changes that are
made to oNewDoc will go into the correct place.

--
Regards,
Jay Freedman
Microsoft Word MVP
Email cannot be acknowledged; please post all follow-ups to the newsgroup so
all may benefit.
 
B

Beeawwb

Hi again everyone, and thanks for your detailed responses. I think I may be
confusing things by not really understanding what I'm asking either, and I'm
not really sure how to explain it.

To clarify, based on Jay's response, I'll take you through what happens, and
how the system here works.

We have a number of Word templates, that are our "standard letters". When
somebody wants to write a letter, they open these .dot files, from our
Intranet. This is because they are used around the country, so our intranet
webpage is the only central location that *everybody* has access to. These
..dot files contain their own macros (written by our head office) to delete
blocks of text (e.g. "I don't need to say that, double click the "Delete"
button and that paragraph is removed). The files are read only, and protected
for legal reasons (so you can't just add any old text you want).

There are about 50 different letters to choose from. All these letters can
be printed on 4 different letterheads. The problem is, when head office
designed these templates, they set the default printer tray to tray 3. Our
staff have great difficulty changing the printer tray to other letterhead (eg
Tray 2, or 4) manually, as the templates are so rigid. So I took it upon
myself to design a macro to change printer trays.

What happens is, I call a form which has 4 buttons. These buttons are
labelled based on which printer is being used (there are 4 to choose from,
all loaded differently). Staff click which letterhead they want (Company 1,
company 2, etc), and then are asked to confirm various print options, and
finally to print the document.

I was having a lot of difficulty recently with unqualified code, but I've
finally sorted this out, and the macro is working fine referencing
ActiveDocument. The question arises because with (potentially) 100 staff
using this macro, and 50 documents to choose from, I will never know which
document has been opened, and hence Documents.Add and Documents.Open won't
work.

Essentially, Jay is correct. We open a document, edit the in memory copy,
and then our imaging system imports the "in memory" document to itself. It's
a dumb way of doing things, I know. Unfortunately I didn't design the system,
I just use it and mop up the problems it creates. :p

Sorry for the extremely long winded post, and thanks again for your help.
Thanks to this newsgroup my understanding of how Word / Office / VBA works is
coming a long way!

-Bob
 
R

Russ

Bob,
See below.
Hi again everyone, and thanks for your detailed responses. I think I may be
confusing things by not really understanding what I'm asking either, and I'm
not really sure how to explain it.

To clarify, based on Jay's response, I'll take you through what happens, and
how the system here works.

We have a number of Word templates, that are our "standard letters". When
somebody wants to write a letter, they open these .dot files, from our
Intranet. This is because they are used around the country, so our intranet
webpage is the only central location that *everybody* has access to. These
.dot files contain their own macros (written by our head office) to delete

blocks of text (e.g. "I don't need to say that, double click the "Delete"
button and that paragraph is removed). The files are read only, and protected
for legal reasons (so you can't just add any old text you want).

There are about 50 different letters to choose from. All these letters can
be printed on 4 different letterheads. The problem is, when head office
designed these templates, they set the default printer tray to tray 3. Our
staff have great difficulty changing the printer tray to other letterhead (eg
Tray 2, or 4) manually, as the templates are so rigid. So I took it upon
myself to design a macro to change printer trays.

What happens is, I call a form which has 4 buttons. These buttons are
labelled based on which printer is being used (there are 4 to choose from,
all loaded differently). Staff click which letterhead they want (Company 1,
company 2, etc), and then are asked to confirm various print options, and
finally to print the document.

I was having a lot of difficulty recently with unqualified code, but I've
finally sorted this out, and the macro is working fine referencing
ActiveDocument. The question arises because with (potentially) 100 staff
using this macro, and 50 documents to choose from, I will never know which
document has been opened, and hence
Your print routine would normally assume that the user would want to print
the currently active document, unless you use some means to query for which
document.
I didn't want you to think that you only had an opportunity to create a doc
object reference when a file is first opened or added. Anytime you think you
may want to reference the current active document later among other opened
documents, you could create the reference.
Dim myDoc as Word.Document
Set myDoc = ActiveDocument

If only one document is opened, then no reference other than the object
called ActiveDocument is needed.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top