find existence of autotext entries

K

Keith G Hicks

Well I tried this in the Access.FormsCoding newsgroup and got nothing so I'm
giving it a shot here.



I'm cleaning up some code from a previous programmer who liked to put "On
Error Resume Next" in places where he didnt' know how to test things in
lines above code that might crash. For example, there are lines like the
following:

Selection.InsertAfter "krh"
On Error Resume Next
Selection.Range.InsertAutoText

I really want to take otu the "On Error Resume Next" and replace it with a
test to see if the AutoTextEntry exists as follows:

Selection.InsertAfter "krh"
If <autotext entry("krh")> exists Then
Selection.Range.InsertAutoText
End If


But I have no idea how to do that. I know I can use NormalTemplate in some
way but that is a problem in and of itself because we're nto using the
Normal Template all the time. I need to search that and another as well.

Anyway, some specific info on how to do this would be wonderful.

Thanks,

Keith
 
D

Doug Robbins - Word MVP

If the Autotext entry does not exist, you will get a 5906 error. If there
is some particular way in which you want to handle those errors, you can set
up an error handler that checks for the number of the error and if it is
5906 does whatever it is that you want to do in that case. Otherwise, the
Resume Next is as good a way as any and to prevent the routine from falling
over on the occurrence of such an event.

--
Hope this helps.

Please reply to the newsgroup unless you wish to avail yourself of my
services on a paid consulting basis.

Doug Robbins - Word MVP, originally posted via msnews.microsoft.com
 
G

Graham Mayor

While I suspect Doug's approach will be the more realistic, your question
raises a question that might be worth exploring further.
I take it we can assume Word before 2007, as Word 2007 moved the goalposts
with respect to autotext entries with the introduction of building blocks?

When you request an autotext entry, Word looks into the active template
first, then in addin templates and finally in the normal template. This
appears rather more complex to arrange with vba (though if better
programmers than I are watching they will no doubt jump in).

While you can insert an autotext entry using vba from the attached (active)
template or from the normal template if it is present, it is not possible to
do so from an addin template without making that template the active
template. You could therefore check for the presence of the entry in the
active template then attach each add-in template in turn and check for the
presence of the autotext entry before restoring the original attached
template. Finally checking the normal template. If the entry is found in any
of these locations the macro quits. If not the user is given a message to
that effect.

Dim oAT As AutoTextEntry
Dim strAttach As String
Dim strFilename As String
Dim addInPath As String
Dim oAddIn As Template
Dim bFound As Boolean
strAttach = Templates(1).Path _
& Application.PathSeparator _
& ActiveDocument.AttachedTemplate
addInPath = Options.DefaultFilePath(wdStartupPath)
strFilename = Dir$(addInPath & "\*.dot")
bFound = False
For Each oAT In ActiveDocument.AttachedTemplate.AutoTextEntries
If oAT.name = "klr" Then
ActiveDocument.AttachedTemplate.AutoTextEntries("klr").Insert _
Where:=Selection.Range
bFound = True
Exit For
End If
Next oAT
If bFound = False Then
While Len(strFilename) <> 0
ActiveDocument.AttachedTemplate = addInPath _
& Application.PathSeparator _
& strFilename
For Each oAT In ActiveDocument.AttachedTemplate.AutoTextEntries
If oAT.name = "klr" Then
ActiveDocument.AttachedTemplate.AutoTextEntries("klr").Insert
_
Where:=Selection.Range
bFound = True
Exit For
End If
Next oAT
strFilename = Dir$()
Wend
ActiveDocument.AttachedTemplate = strAttach
End If
If bFound = False Then
For Each oAT In NormalTemplate.AutoTextEntries
If oAT.name = "klr" Then
NormalTemplate.AutoTextEntries("klr").Insert _
Where:=Selection.Range
bFound = True
Exit For
End If
Next oAT
End If
If bFound = False Then
MsgBox "Autotext entry not found"
End If



--
<>>< ><<> ><<> <>>< ><<> <>>< <>><<>
Graham Mayor - Word MVP


<>>< ><<> ><<> <>>< ><<> <>>< <>><<>
 
L

Lene Fredborg

…it is not possible to do so from an addin template without making that
template the active template…

Actually, you do not need to attach an add-in as the active template in
order to insert AutoText entries from it. You can do so using the Templates
object in combination with the AddIns object. The code below is an adjusted
version of the code posted by Graham. Also note that the code works in Word
2007.

Dim oAddIn As AddIn
Dim oAT As AutoTextEntry
Dim strAT_Name As String
Dim oTemplate As Template
Dim bFound As Boolean

bFound = False

'Name of AutoText to insert
strAT_Name = "krh"

For Each oAT In ActiveDocument.AttachedTemplate.AutoTextEntries
'Check AttachedTemplate
If oAT.Name = strAT_Name Then

ActiveDocument.AttachedTemplate.AutoTextEntries(strAT_Name).Insert _
Where:=Selection.Range
bFound = True
Exit Sub
End If
Next oAT

If bFound = False Then
For Each oAddIn In AddIns
'Check currently loaded add-ins
If oAddIn.Installed = False Then Exit For
Set oTemplate = Templates(oAddIn.Path &
Application.PathSeparator & oAddIn.Name)
For Each oAT In oTemplate.AutoTextEntries
If oAT.Name = strAT_Name Then
oTemplate.AutoTextEntries(strAT_Name).Insert _
Where:=Selection.Range
bFound = True
'Clean up and stop
Set oTemplate = Nothing
Exit Sub
End If
Next oAT
Next oAddIn
End If

If bFound = False Then
'Check NormalTemplate
For Each oAT In NormalTemplate.AutoTextEntries
If oAT.Name = strAT_Name Then
NormalTemplate.AutoTextEntries(strAT_Name).Insert _
Where:=Selection.Range
bFound = True
Exit Sub
End If
Next oAT
End If
If bFound = False Then
MsgBox "AutoText '" & strAT_Name & "' not found"
End If

--
Regards
Lene Fredborg - Microsoft MVP (Word)
DocTools - Denmark
www.thedoctools.com
Document automation - add-ins, macros and templates for Microsoft Word
 
G

Graham Mayor

While researching this the method I proposed was one suggested by Microsoft
and does in fact work - however as ever there is more than one way to skin a
cat. Thanks for pointing out this one :)

--
<>>< ><<> ><<> <>>< ><<> <>>< <>><<>
Graham Mayor - Word MVP


<>>< ><<> ><<> <>>< ><<> <>>< <>><<>
 
G

Graham Mayor

The method is complicated for Word 2007 by the use of Building Blocks and
the possibility that the entry may not contained in the autotext gallery
(though hopefully you might know where to look before searching). For Word
2007 to look at all possible hiding places I had come up with the following,
before seeing your post. I was about to post this on my web site, for future
reference, but the site server is playing up. If I was superstitious I would
blame the date ;)


Sub InsertMyBuildingBlock()
Dim strAttach As String
Dim strFilename As String
Dim addInPath As String
Dim strText As String
Dim oTempl As Template
Dim bFound As Boolean
Dim i As Long

'Define the required building block entry
strText = "Building Block Name"

'Record the attached template path
strAttach = ActiveDocument.AttachedTemplate.FullName
'record the addin path
addInPath = Options.DefaultFilePath(wdStartupPath)
'Define the startup template names
strFilename = Dir$(addInPath & "\*.dot?")
'Set the found flag default to False
bFound = False
'Check each building block entry in the attached template

For i = 1 To ActiveDocument.AttachedTemplate.BuildingBlockEntries.Count
If ActiveDocument.AttachedTemplate.BuildingBlockEntries(i).name =
strText Then
ActiveDocument.AttachedTemplate.BuildingBlockEntries(strText).Insert
_
Where:=Selection.Range
'set the found flag to true
bFound = True
'and stop looking
Exit For
End If
Next i

'If the entry has not been found
If bFound = False Then
'Make each startup template in turn the active template
While Len(strFilename) <> 0
ActiveDocument.AttachedTemplate = addInPath _
& Application.PathSeparator _
& strFilename
'Check each building block entry in the current attached template
For i = 1 To
ActiveDocument.AttachedTemplate.BuildingBlockEntries.Count
If
ActiveDocument.AttachedTemplate.BuildingBlockEntries(i).name = strText Then
ActiveDocument.AttachedTemplate.BuildingBlockEntries(strText).Insert
_
Where:=Selection.Range
'set the found flag to true
bFound = True
Exit For
End If
Next i
strFilename = Dir$()
Wend
'Re-attach the original document template
ActiveDocument.AttachedTemplate = strAttach
End If

'If the entry has still not been found
'check the normal template (which could already have been
'checked as the active template) but as there is little
'speed penalty, I have not trapped the extra check
If bFound = False Then
For i = 1 To NormalTemplate.BuildingBlockEntries.Count
If NormalTemplate.BuildingBlockEntries(i).name = strText Then
NormalTemplate.BuildingBlockEntries(strText).Insert _
Where:=Selection.Range
'set the found flag to true
bFound = True
Exit For
End If
Next i
End If
'If the entry has still not been found
'finally check the Building Blocks.dotx template
If bFound = False Then
Templates.LoadBuildingBlocks
For Each oTempl In Templates
If oTempl.name = "Building Blocks.dotx" Then Exit For
Next
For i = 1 To Templates(oTempl.FullName).BuildingBlockEntries.Count
If Templates(oTempl.FullName).BuildingBlockEntries(i).name =
strText Then
Templates(oTempl.FullName).BuildingBlockEntries(strText).Insert
_
Where:=Selection.Range
'set the found flag to true
bFound = True
Exit For
End If
Next i
End If

'All sources have been checked and the entry is still not found
If bFound = False Then 'so tell the user.
MsgBox "Entry not found", vbInformation, "Building Block " _
& Chr(145) & strText & Chr(146)
End If
End Sub


--
<>>< ><<> ><<> <>>< ><<> <>>< <>><<>
Graham Mayor - Word MVP

<>>< ><<> ><<> <>>< ><<> <>>< <>><<>
 
L

Lene Fredborg

I agree about Word 2007. However, when I said that it would work in Word 2007
as well, I imagined that the item to insert was for certain an item contained
in the autotext gallery.

--
Regards
Lene Fredborg - Microsoft MVP (Word)
DocTools - Denmark
www.thedoctools.com
Document automation - add-ins, macros and templates for Microsoft Word
 
K

Keith G Hicks

Graham,

Thanks very much for this. It's just what I was looking for. I really
appreciate it! (Thank you to Lene too for your input)

Keith
 
D

Doug Robbins - Word MVP

So something like 40 lines of code is better than On Error Resume Next,
which in some circumstances at least can be a perfectly acceptable method of
dealing with a situation, or better than making use of the specific Error
Number that is returned to perform a specific action if that error occurs?

You have not said what that action should be and rather than cast aspersions
on the original programmer who used the On Error Resume Next, I would sit
back and think about what your successor will think of you when he comes
across those 40 odd lines of code.


--
Hope this helps,

Doug Robbins - Word MVP

Please reply only to the newsgroups unless you wish to obtain my services on
a paid professional basis.
 
G

Graham Mayor

I have had no internet access all day so I couldn't get back before now. I
have now added the code (with modifications along the lines you suggested)
with an alternative version for Word 2007 that should cover all
eventualities http://www.gmayor.com/word_vba_examples.htm#Autotext

--
<>>< ><<> ><<> <>>< ><<> <>>< <>><<>
Graham Mayor - Word MVP


<>>< ><<> ><<> <>>< ><<> <>>< <>><<>
 
G

Graham Mayor

I did say in my original reply that your revised on error method was the
more realistic option :) . The expanded method was more of an exercise to
cover all eventualities. It essentially inserts the entry from wherever it
is located, prioritising the search by attached, template, add-in, normal
template (then building blocks.dotx for Word 2007).

If you know where the autotext entry is stored, before you try and insert it
with vba, then there is no need to look elsewhere for it.

--
<>>< ><<> ><<> <>>< ><<> <>>< <>><<>
Graham Mayor - Word MVP


<>>< ><<> ><<> <>>< ><<> <>>< <>><<>
 
D

Doug Robbins - Word MVP

Hi Graham,

Yes, I saw the qualification in your initial response and my retort was not
of course directed at you.

--
Hope this helps.

Please reply to the newsgroup unless you wish to avail yourself of my
services on a paid consulting basis.

Doug Robbins - Word MVP, originally posted via msnews.microsoft.com
 
G

Gordon Bentley-Mix

I have to side with Doug on this one. There seems to be an implicit and
unstated belief that On Error Resume Next (OERN) is "sloppy" code used only
by neophytes who don't know how to do "real" error handling. I beg to
differ.

For example, I have several similar templates that contain UserForms with
MultiPage controls on them. On a couple of the Pages there are a series of
OptionButtons, and selecting one changes the "configuration" of the Page -
modifying Labels, setting the visibility of TextBoxes, changing the
alignment of controls, etc. The last step of this "configuration" process is
to set focus to a particular control (the first TextBox on the Page). As
part of the UserForm initialisation process, I select one of the
OptionButtons on each Page as the default. However, because the UserForm
loads with the first Page displayed, trying to set focus to a particular
control on any of the other pages generates an error because the control
isn't visible. I know I could go through a lot of work to prevent this
error - make a particular Page "active" by setting the .Value property of
the MultiPage control, run the "configuration" process, make the first Page
"active" again - but why bother? I know the only time this error is going to
occur is during the initialisation of the UserForm; I know that it has
absolutely no impact on the user and that there's nothing that the user
could do to prevent it anyway; and I know that I just want the code to
continue executing in spite of the error. OERN is _exactly_ what's required.

Of course, I don't mean that OERN should be used exclusively or that it
doesn't get abused by some developers. In fact, I always try to handle
errors gracefully, but even then I don't always make use of "specific Error
Number... to perform a specific action if that error occurs". In fact,
most of the time, I know that there are really only a limited number of
errors that could occur, and the response to any error is generally the
same. A simple example is related to working with document variables.

As you know, there is no .Exists method/property for document variables, and
if you try to perform certain actions using non-existent document variables
it generates an error. I don't know the specific Error Number/s, but using a
process (developed with the kind assistance of Greg Maxey) I can accommodate
this shortcoming quite elegantly using a simple Boolean function. The code
looks like this:

Public Function fcnFindVariable(myVariableName As String) As Boolean
Dim myValue As String
fcnFindVariable = False
On Error Resume Next
myValue = myDoc.Variables(myVariableName).Value
If Err.Number = 0 Then fcnFindVariable = True
End Function

Basically, all this function does is try to get the value from a particular
document variable, and of course, if the document variable doesn't exist an
error is generated. I don't need to know the Error Number to achieve my
desired goal. (In fact, note the use of OERN within the function.) I invoke
this function whenever I retrieve a value from a document variable; e.g.:

Public Function fcnGetTextVariableValue(myVariableName As String) As String
Dim Temp As String
With myDoc
If fcnFindVariable(myVariableName) = True Then '<== HERE!!!
With .Variables(myVariableName)
If .Value <> " " Then Temp = .Value Else Temp = ""
End With
Else: Temp = ""
End If
End With
fcnGetTextVariableValue = Temp
End Function

Any error that might be generated is handled gracefully, and because there's
no need for the user to do anything if an error does occur I just provide a
generic, "unnotified" response to the error - in this case by returning a
zero-length string.

I use a similar approach when saving values into document variables. In this
case, I know that if I try to write a value into a document variable that
doesn't exist it will generate an error. OTOH, if I try to create a document
variable that already exists it will also generate an error. Therefore, I
test for the existence of the document variable (using my Boolean function
from above) and respond accordingly.

For an example that's perhaps a bit more on point, here is how I approach
inserting AutoText:

Public Sub InsertATEntry(myBkmkName As String, myATEntryName As String,
Optional bRestoreBkmk As Boolean = False)
With myDoc
If .Bookmarks.Exists(myBkmkName) Then
Dim myRange As Range
Set myRange = .Bookmarks(myBkmkName).Range
On Error GoTo ATEError
.AttachedTemplate.AutoTextEntries(myATEntryName).Insert myRange,
True
If bRestoreBkmk = True Then .Bookmarks.Add myBkmkName, myRange
Else: Debug.Print "ATE Bkmk: " & myBkmkName
End If
End With
Exit Sub

ATEError:
MsgBox "The required AutoText entry " & myATEntryName & " could not be
found." & vbCr & "Please contact the Service Desk for assistance.",
vbCritical, "AutoText Error"
Debug.Print myBkmkName & " " & myATEntryName
End Sub

It's a bit different from the OP's situation and from the solution that
Graham provided because the AutoText entries are always stored in the
attached template, but it does provide an example of error handling that
doesn't just rely on OERN and that notifies the user when an error occurs
and provides instruction on what to do in response to the error condition.
Of course, the only time the error handling is invoked is during development
because I always thoroughly test my templates before releasing them to
production. ;-P

And thus ends my defense of OERN...
 
D

Doug Robbins - Word MVP

Hi Gordon,

Just one thing about what you said - It is NOT necessary for a document
variable to exist to assign a value to it.

All you need is to use

ActiveDocument.Variables("varname").Value = "Whatever"

and the variable is created and the value is assigned to it

Also, the error number returned if you try and get the value of document
variable that does not exist is 5825

--
Hope this helps,

Doug Robbins - Word MVP

Please reply only to the newsgroups unless you wish to obtain my services on
a paid professional basis.

Gordon Bentley-Mix said:
I have to side with Doug on this one. There seems to be an implicit and
unstated belief that On Error Resume Next (OERN) is "sloppy" code used only
by neophytes who don't know how to do "real" error handling. I beg to
differ.

For example, I have several similar templates that contain UserForms with
MultiPage controls on them. On a couple of the Pages there are a series of
OptionButtons, and selecting one changes the "configuration" of the Page -
modifying Labels, setting the visibility of TextBoxes, changing the
alignment of controls, etc. The last step of this "configuration" process
is to set focus to a particular control (the first TextBox on the Page).
As part of the UserForm initialisation process, I select one of the
OptionButtons on each Page as the default. However, because the UserForm
loads with the first Page displayed, trying to set focus to a particular
control on any of the other pages generates an error because the control
isn't visible. I know I could go through a lot of work to prevent this
error - make a particular Page "active" by setting the .Value property of
the MultiPage control, run the "configuration" process, make the first
Page "active" again - but why bother? I know the only time this error is
going to occur is during the initialisation of the UserForm; I know that
it has absolutely no impact on the user and that there's nothing that the
user could do to prevent it anyway; and I know that I just want the code
to continue executing in spite of the error. OERN is _exactly_ what's
required.

Of course, I don't mean that OERN should be used exclusively or that it
doesn't get abused by some developers. In fact, I always try to handle
errors gracefully, but even then I don't always make use of "specific
Error Number... to perform a specific action if that error occurs". In
fact, most of the time, I know that there are really only a limited number
of errors that could occur, and the response to any error is generally the
same. A simple example is related to working with document variables.

As you know, there is no .Exists method/property for document variables,
and if you try to perform certain actions using non-existent document
variables it generates an error. I don't know the specific Error Number/s,
but using a process (developed with the kind assistance of Greg Maxey) I
can accommodate this shortcoming quite elegantly using a simple Boolean
function. The code looks like this:

Public Function fcnFindVariable(myVariableName As String) As Boolean
Dim myValue As String
fcnFindVariable = False
On Error Resume Next
myValue = myDoc.Variables(myVariableName).Value
If Err.Number = 0 Then fcnFindVariable = True
End Function

Basically, all this function does is try to get the value from a
particular document variable, and of course, if the document variable
doesn't exist an error is generated. I don't need to know the Error Number
to achieve my desired goal. (In fact, note the use of OERN within the
function.) I invoke this function whenever I retrieve a value from a
document variable; e.g.:

Public Function fcnGetTextVariableValue(myVariableName As String) As
String
Dim Temp As String
With myDoc
If fcnFindVariable(myVariableName) = True Then '<== HERE!!!
With .Variables(myVariableName)
If .Value <> " " Then Temp = .Value Else Temp = ""
End With
Else: Temp = ""
End If
End With
fcnGetTextVariableValue = Temp
End Function

Any error that might be generated is handled gracefully, and because
there's no need for the user to do anything if an error does occur I just
provide a generic, "unnotified" response to the error - in this case by
returning a zero-length string.

I use a similar approach when saving values into document variables. In
this case, I know that if I try to write a value into a document variable
that doesn't exist it will generate an error. OTOH, if I try to create a
document variable that already exists it will also generate an error.
Therefore, I test for the existence of the document variable (using my
Boolean function from above) and respond accordingly.

For an example that's perhaps a bit more on point, here is how I approach
inserting AutoText:

Public Sub InsertATEntry(myBkmkName As String, myATEntryName As String,
Optional bRestoreBkmk As Boolean = False)
With myDoc
If .Bookmarks.Exists(myBkmkName) Then
Dim myRange As Range
Set myRange = .Bookmarks(myBkmkName).Range
On Error GoTo ATEError
.AttachedTemplate.AutoTextEntries(myATEntryName).Insert
myRange, True
If bRestoreBkmk = True Then .Bookmarks.Add myBkmkName, myRange
Else: Debug.Print "ATE Bkmk: " & myBkmkName
End If
End With
Exit Sub

ATEError:
MsgBox "The required AutoText entry " & myATEntryName & " could not be
found." & vbCr & "Please contact the Service Desk for assistance.",
vbCritical, "AutoText Error"
Debug.Print myBkmkName & " " & myATEntryName
End Sub

It's a bit different from the OP's situation and from the solution that
Graham provided because the AutoText entries are always stored in the
attached template, but it does provide an example of error handling that
doesn't just rely on OERN and that notifies the user when an error occurs
and provides instruction on what to do in response to the error condition.
Of course, the only time the error handling is invoked is during
development because I always thoroughly test my templates before releasing
them to production. ;-P

And thus ends my defense of OERN...
--
Cheers!

Gordon Bentley-Mix
Word MVP

Doug Robbins - Word MVP said:
So something like 40 lines of code is better than On Error Resume Next,
which in some circumstances at least can be a perfectly acceptable method
of dealing with a situation, or better than making use of the specific
Error Number that is returned to perform a specific action if that error
occurs?

You have not said what that action should be and rather than cast
aspersions on the original programmer who used the On Error Resume Next,
I would sit back and think about what your successor will think of you
when he comes across those 40 odd lines of code.


--
Hope this helps,

Doug Robbins - Word MVP

Please reply only to the newsgroups unless you wish to obtain my services
on
a paid professional basis.
 
D

Doug Robbins - Word MVP

Oh, one other thing - neophytes don't bother with error trapping!

--
Hope this helps,

Doug Robbins - Word MVP

Please reply only to the newsgroups unless you wish to obtain my services on
a paid professional basis.

Gordon Bentley-Mix said:
I have to side with Doug on this one. There seems to be an implicit and
unstated belief that On Error Resume Next (OERN) is "sloppy" code used only
by neophytes who don't know how to do "real" error handling. I beg to
differ.

For example, I have several similar templates that contain UserForms with
MultiPage controls on them. On a couple of the Pages there are a series of
OptionButtons, and selecting one changes the "configuration" of the Page -
modifying Labels, setting the visibility of TextBoxes, changing the
alignment of controls, etc. The last step of this "configuration" process
is to set focus to a particular control (the first TextBox on the Page).
As part of the UserForm initialisation process, I select one of the
OptionButtons on each Page as the default. However, because the UserForm
loads with the first Page displayed, trying to set focus to a particular
control on any of the other pages generates an error because the control
isn't visible. I know I could go through a lot of work to prevent this
error - make a particular Page "active" by setting the .Value property of
the MultiPage control, run the "configuration" process, make the first
Page "active" again - but why bother? I know the only time this error is
going to occur is during the initialisation of the UserForm; I know that
it has absolutely no impact on the user and that there's nothing that the
user could do to prevent it anyway; and I know that I just want the code
to continue executing in spite of the error. OERN is _exactly_ what's
required.

Of course, I don't mean that OERN should be used exclusively or that it
doesn't get abused by some developers. In fact, I always try to handle
errors gracefully, but even then I don't always make use of "specific
Error Number... to perform a specific action if that error occurs". In
fact, most of the time, I know that there are really only a limited number
of errors that could occur, and the response to any error is generally the
same. A simple example is related to working with document variables.

As you know, there is no .Exists method/property for document variables,
and if you try to perform certain actions using non-existent document
variables it generates an error. I don't know the specific Error Number/s,
but using a process (developed with the kind assistance of Greg Maxey) I
can accommodate this shortcoming quite elegantly using a simple Boolean
function. The code looks like this:

Public Function fcnFindVariable(myVariableName As String) As Boolean
Dim myValue As String
fcnFindVariable = False
On Error Resume Next
myValue = myDoc.Variables(myVariableName).Value
If Err.Number = 0 Then fcnFindVariable = True
End Function

Basically, all this function does is try to get the value from a
particular document variable, and of course, if the document variable
doesn't exist an error is generated. I don't need to know the Error Number
to achieve my desired goal. (In fact, note the use of OERN within the
function.) I invoke this function whenever I retrieve a value from a
document variable; e.g.:

Public Function fcnGetTextVariableValue(myVariableName As String) As
String
Dim Temp As String
With myDoc
If fcnFindVariable(myVariableName) = True Then '<== HERE!!!
With .Variables(myVariableName)
If .Value <> " " Then Temp = .Value Else Temp = ""
End With
Else: Temp = ""
End If
End With
fcnGetTextVariableValue = Temp
End Function

Any error that might be generated is handled gracefully, and because
there's no need for the user to do anything if an error does occur I just
provide a generic, "unnotified" response to the error - in this case by
returning a zero-length string.

I use a similar approach when saving values into document variables. In
this case, I know that if I try to write a value into a document variable
that doesn't exist it will generate an error. OTOH, if I try to create a
document variable that already exists it will also generate an error.
Therefore, I test for the existence of the document variable (using my
Boolean function from above) and respond accordingly.

For an example that's perhaps a bit more on point, here is how I approach
inserting AutoText:

Public Sub InsertATEntry(myBkmkName As String, myATEntryName As String,
Optional bRestoreBkmk As Boolean = False)
With myDoc
If .Bookmarks.Exists(myBkmkName) Then
Dim myRange As Range
Set myRange = .Bookmarks(myBkmkName).Range
On Error GoTo ATEError
.AttachedTemplate.AutoTextEntries(myATEntryName).Insert
myRange, True
If bRestoreBkmk = True Then .Bookmarks.Add myBkmkName, myRange
Else: Debug.Print "ATE Bkmk: " & myBkmkName
End If
End With
Exit Sub

ATEError:
MsgBox "The required AutoText entry " & myATEntryName & " could not be
found." & vbCr & "Please contact the Service Desk for assistance.",
vbCritical, "AutoText Error"
Debug.Print myBkmkName & " " & myATEntryName
End Sub

It's a bit different from the OP's situation and from the solution that
Graham provided because the AutoText entries are always stored in the
attached template, but it does provide an example of error handling that
doesn't just rely on OERN and that notifies the user when an error occurs
and provides instruction on what to do in response to the error condition.
Of course, the only time the error handling is invoked is during
development because I always thoroughly test my templates before releasing
them to production. ;-P

And thus ends my defense of OERN...
--
Cheers!

Gordon Bentley-Mix
Word MVP

Doug Robbins - Word MVP said:
So something like 40 lines of code is better than On Error Resume Next,
which in some circumstances at least can be a perfectly acceptable method
of dealing with a situation, or better than making use of the specific
Error Number that is returned to perform a specific action if that error
occurs?

You have not said what that action should be and rather than cast
aspersions on the original programmer who used the On Error Resume Next,
I would sit back and think about what your successor will think of you
when he comes across those 40 odd lines of code.


--
Hope this helps,

Doug Robbins - Word MVP

Please reply only to the newsgroups unless you wish to obtain my services
on
a paid professional basis.
 
G

Gordon Bentley-Mix

Hmm... I think I may have known that at some point, and I just tested it (by
commenting out the one line of code that checks for the existence of a
document variable and adding it if it doesn't exist before writing a value
into it) and can confirm that it does indeed work without error. I guess
maybe it was just a case of not trusting the compiler to do something
automatically when there was a way to do it explicitly. I've been guilty of
that before - like using

If .Bookmarks.Exists(myBkmkName) = True Then

instead of just

If .Bookmarks.Exists(myBkmkName) Then

and relying on the implicit, compiler-generated "True" to control execution.
I think the commonly used term is "pedantic" (or "control freak") but I
prefer "meticulous"... <g>

Thanks for the tip!
--
Cheers!

Gordon Bentley-Mix
Word MVP

Doug Robbins - Word MVP said:
Hi Gordon,

Just one thing about what you said - It is NOT necessary for a document
variable to exist to assign a value to it.

All you need is to use

ActiveDocument.Variables("varname").Value = "Whatever"

and the variable is created and the value is assigned to it

Also, the error number returned if you try and get the value of document
variable that does not exist is 5825

--
Hope this helps,

Doug Robbins - Word MVP

Please reply only to the newsgroups unless you wish to obtain my services
on
a paid professional basis.

Gordon Bentley-Mix said:
I have to side with Doug on this one. There seems to be an implicit and
unstated belief that On Error Resume Next (OERN) is "sloppy" code used
only by neophytes who don't know how to do "real" error handling. I beg to
differ.

For example, I have several similar templates that contain UserForms with
MultiPage controls on them. On a couple of the Pages there are a series
of OptionButtons, and selecting one changes the "configuration" of the
Page - modifying Labels, setting the visibility of TextBoxes, changing
the alignment of controls, etc. The last step of this "configuration"
process is to set focus to a particular control (the first TextBox on the
Page). As part of the UserForm initialisation process, I select one of
the OptionButtons on each Page as the default. However, because the
UserForm loads with the first Page displayed, trying to set focus to a
particular control on any of the other pages generates an error because
the control isn't visible. I know I could go through a lot of work to
prevent this error - make a particular Page "active" by setting the
.Value property of the MultiPage control, run the "configuration"
process, make the first Page "active" again - but why bother? I know the
only time this error is going to occur is during the initialisation of
the UserForm; I know that it has absolutely no impact on the user and
that there's nothing that the user could do to prevent it anyway; and I
know that I just want the code to continue executing in spite of the
error. OERN is _exactly_ what's required.

Of course, I don't mean that OERN should be used exclusively or that it
doesn't get abused by some developers. In fact, I always try to handle
errors gracefully, but even then I don't always make use of "specific
Error Number... to perform a specific action if that error occurs". In
fact, most of the time, I know that there are really only a limited
number of errors that could occur, and the response to any error is
generally the same. A simple example is related to working with document
variables.

As you know, there is no .Exists method/property for document variables,
and if you try to perform certain actions using non-existent document
variables it generates an error. I don't know the specific Error
Number/s, but using a process (developed with the kind assistance of Greg
Maxey) I can accommodate this shortcoming quite elegantly using a simple
Boolean function. The code looks like this:

Public Function fcnFindVariable(myVariableName As String) As Boolean
Dim myValue As String
fcnFindVariable = False
On Error Resume Next
myValue = myDoc.Variables(myVariableName).Value
If Err.Number = 0 Then fcnFindVariable = True
End Function

Basically, all this function does is try to get the value from a
particular document variable, and of course, if the document variable
doesn't exist an error is generated. I don't need to know the Error
Number to achieve my desired goal. (In fact, note the use of OERN within
the function.) I invoke this function whenever I retrieve a value from a
document variable; e.g.:

Public Function fcnGetTextVariableValue(myVariableName As String) As
String
Dim Temp As String
With myDoc
If fcnFindVariable(myVariableName) = True Then '<== HERE!!!
With .Variables(myVariableName)
If .Value <> " " Then Temp = .Value Else Temp = ""
End With
Else: Temp = ""
End If
End With
fcnGetTextVariableValue = Temp
End Function

Any error that might be generated is handled gracefully, and because
there's no need for the user to do anything if an error does occur I just
provide a generic, "unnotified" response to the error - in this case by
returning a zero-length string.

I use a similar approach when saving values into document variables. In
this case, I know that if I try to write a value into a document variable
that doesn't exist it will generate an error. OTOH, if I try to create a
document variable that already exists it will also generate an error.
Therefore, I test for the existence of the document variable (using my
Boolean function from above) and respond accordingly.

For an example that's perhaps a bit more on point, here is how I approach
inserting AutoText:

Public Sub InsertATEntry(myBkmkName As String, myATEntryName As String,
Optional bRestoreBkmk As Boolean = False)
With myDoc
If .Bookmarks.Exists(myBkmkName) Then
Dim myRange As Range
Set myRange = .Bookmarks(myBkmkName).Range
On Error GoTo ATEError
.AttachedTemplate.AutoTextEntries(myATEntryName).Insert
myRange, True
If bRestoreBkmk = True Then .Bookmarks.Add myBkmkName, myRange
Else: Debug.Print "ATE Bkmk: " & myBkmkName
End If
End With
Exit Sub

ATEError:
MsgBox "The required AutoText entry " & myATEntryName & " could not be
found." & vbCr & "Please contact the Service Desk for assistance.",
vbCritical, "AutoText Error"
Debug.Print myBkmkName & " " & myATEntryName
End Sub

It's a bit different from the OP's situation and from the solution that
Graham provided because the AutoText entries are always stored in the
attached template, but it does provide an example of error handling that
doesn't just rely on OERN and that notifies the user when an error occurs
and provides instruction on what to do in response to the error
condition. Of course, the only time the error handling is invoked is
during development because I always thoroughly test my templates before
releasing them to production. ;-P

And thus ends my defense of OERN...
--
Cheers!

Gordon Bentley-Mix
Word MVP

Doug Robbins - Word MVP said:
So something like 40 lines of code is better than On Error Resume Next,
which in some circumstances at least can be a perfectly acceptable
method of dealing with a situation, or better than making use of the
specific Error Number that is returned to perform a specific action if
that error occurs?

You have not said what that action should be and rather than cast
aspersions on the original programmer who used the On Error Resume Next,
I would sit back and think about what your successor will think of you
when he comes across those 40 odd lines of code.


--
Hope this helps,

Doug Robbins - Word MVP

Please reply only to the newsgroups unless you wish to obtain my
services on
a paid professional basis.

Graham,

Thanks very much for this. It's just what I was looking for. I really
appreciate it! (Thank you to Lene too for your input)

Keith

While I suspect Doug's approach will be the more realistic, your
question
raises a question that might be worth exploring further.
I take it we can assume Word before 2007, as Word 2007 moved the
goalposts
with respect to autotext entries with the introduction of building
blocks?

When you request an autotext entry, Word looks into the active
template
first, then in addin templates and finally in the normal template.
This
appears rather more complex to arrange with vba (though if better
programmers than I are watching they will no doubt jump in).

While you can insert an autotext entry using vba from the attached
(active) template or from the normal template if it is present, it is
not
possible to do so from an addin template without making that template
the
active template. You could therefore check for the presence of the
entry
in the active template then attach each add-in template in turn and
check
for the presence of the autotext entry before restoring the original
attached template. Finally checking the normal template. If the entry
is
found in any of these locations the macro quits. If not the user is
given
a message to that effect.

Dim oAT As AutoTextEntry
Dim strAttach As String
Dim strFilename As String
Dim addInPath As String
Dim oAddIn As Template
Dim bFound As Boolean
strAttach = Templates(1).Path _
& Application.PathSeparator _
& ActiveDocument.AttachedTemplate
addInPath = Options.DefaultFilePath(wdStartupPath)
strFilename = Dir$(addInPath & "\*.dot")
bFound = False
For Each oAT In ActiveDocument.AttachedTemplate.AutoTextEntries
If oAT.name = "klr" Then
ActiveDocument.AttachedTemplate.AutoTextEntries("klr").Insert _
Where:=Selection.Range
bFound = True
Exit For
End If
Next oAT
If bFound = False Then
While Len(strFilename) <> 0
ActiveDocument.AttachedTemplate = addInPath _
& Application.PathSeparator _
& strFilename
For Each oAT In ActiveDocument.AttachedTemplate.AutoTextEntries
If oAT.name = "klr" Then

ActiveDocument.AttachedTemplate.AutoTextEntries("klr").Insert _
Where:=Selection.Range
bFound = True
Exit For
End If
Next oAT
strFilename = Dir$()
Wend
ActiveDocument.AttachedTemplate = strAttach
End If
If bFound = False Then
For Each oAT In NormalTemplate.AutoTextEntries
If oAT.name = "klr" Then
NormalTemplate.AutoTextEntries("klr").Insert _
Where:=Selection.Range
bFound = True
Exit For
End If
Next oAT
End If
If bFound = False Then
MsgBox "Autotext entry not found"
End If



--
<>>< ><<> ><<> <>>< ><<> <>>< <>><<>
Graham Mayor - Word MVP

My web site www.gmayor.com

<>>< ><<> ><<> <>>< ><<> <>>< <>><<>


Well I tried this in the Access.FormsCoding newsgroup and got nothing
so
I'm giving it a shot here.



I'm cleaning up some code from a previous programmer who liked to put
"On
Error Resume Next" in places where he didnt' know how to test things
in
lines above code that might crash. For example, there are lines like
the
following:

Selection.InsertAfter "krh"
On Error Resume Next
Selection.Range.InsertAutoText

I really want to take otu the "On Error Resume Next" and replace it
with
a
test to see if the AutoTextEntry exists as follows:

Selection.InsertAfter "krh"
If <autotext entry("krh")> exists Then
Selection.Range.InsertAutoText
End If


But I have no idea how to do that. I know I can use NormalTemplate in
some
way but that is a problem in and of itself because we're nto using
the
Normal Template all the time. I need to search that and another as
well.

Anyway, some specific info on how to do this would be wonderful.

Thanks,

Keith

 
G

Gordon Bentley-Mix

Touché!

And pedants go for overkill.
--
Cheers!

Gordon Bentley-Mix
Word MVP

Doug Robbins - Word MVP said:
Oh, one other thing - neophytes don't bother with error trapping!

--
Hope this helps,

Doug Robbins - Word MVP

Please reply only to the newsgroups unless you wish to obtain my services
on
a paid professional basis.

Gordon Bentley-Mix said:
I have to side with Doug on this one. There seems to be an implicit and
unstated belief that On Error Resume Next (OERN) is "sloppy" code used
only by neophytes who don't know how to do "real" error handling. I beg to
differ.

For example, I have several similar templates that contain UserForms with
MultiPage controls on them. On a couple of the Pages there are a series
of OptionButtons, and selecting one changes the "configuration" of the
Page - modifying Labels, setting the visibility of TextBoxes, changing
the alignment of controls, etc. The last step of this "configuration"
process is to set focus to a particular control (the first TextBox on the
Page). As part of the UserForm initialisation process, I select one of
the OptionButtons on each Page as the default. However, because the
UserForm loads with the first Page displayed, trying to set focus to a
particular control on any of the other pages generates an error because
the control isn't visible. I know I could go through a lot of work to
prevent this error - make a particular Page "active" by setting the
.Value property of the MultiPage control, run the "configuration"
process, make the first Page "active" again - but why bother? I know the
only time this error is going to occur is during the initialisation of
the UserForm; I know that it has absolutely no impact on the user and
that there's nothing that the user could do to prevent it anyway; and I
know that I just want the code to continue executing in spite of the
error. OERN is _exactly_ what's required.

Of course, I don't mean that OERN should be used exclusively or that it
doesn't get abused by some developers. In fact, I always try to handle
errors gracefully, but even then I don't always make use of "specific
Error Number... to perform a specific action if that error occurs". In
fact, most of the time, I know that there are really only a limited
number of errors that could occur, and the response to any error is
generally the same. A simple example is related to working with document
variables.

As you know, there is no .Exists method/property for document variables,
and if you try to perform certain actions using non-existent document
variables it generates an error. I don't know the specific Error
Number/s, but using a process (developed with the kind assistance of Greg
Maxey) I can accommodate this shortcoming quite elegantly using a simple
Boolean function. The code looks like this:

Public Function fcnFindVariable(myVariableName As String) As Boolean
Dim myValue As String
fcnFindVariable = False
On Error Resume Next
myValue = myDoc.Variables(myVariableName).Value
If Err.Number = 0 Then fcnFindVariable = True
End Function

Basically, all this function does is try to get the value from a
particular document variable, and of course, if the document variable
doesn't exist an error is generated. I don't need to know the Error
Number to achieve my desired goal. (In fact, note the use of OERN within
the function.) I invoke this function whenever I retrieve a value from a
document variable; e.g.:

Public Function fcnGetTextVariableValue(myVariableName As String) As
String
Dim Temp As String
With myDoc
If fcnFindVariable(myVariableName) = True Then '<== HERE!!!
With .Variables(myVariableName)
If .Value <> " " Then Temp = .Value Else Temp = ""
End With
Else: Temp = ""
End If
End With
fcnGetTextVariableValue = Temp
End Function

Any error that might be generated is handled gracefully, and because
there's no need for the user to do anything if an error does occur I just
provide a generic, "unnotified" response to the error - in this case by
returning a zero-length string.

I use a similar approach when saving values into document variables. In
this case, I know that if I try to write a value into a document variable
that doesn't exist it will generate an error. OTOH, if I try to create a
document variable that already exists it will also generate an error.
Therefore, I test for the existence of the document variable (using my
Boolean function from above) and respond accordingly.

For an example that's perhaps a bit more on point, here is how I approach
inserting AutoText:

Public Sub InsertATEntry(myBkmkName As String, myATEntryName As String,
Optional bRestoreBkmk As Boolean = False)
With myDoc
If .Bookmarks.Exists(myBkmkName) Then
Dim myRange As Range
Set myRange = .Bookmarks(myBkmkName).Range
On Error GoTo ATEError
.AttachedTemplate.AutoTextEntries(myATEntryName).Insert
myRange, True
If bRestoreBkmk = True Then .Bookmarks.Add myBkmkName, myRange
Else: Debug.Print "ATE Bkmk: " & myBkmkName
End If
End With
Exit Sub

ATEError:
MsgBox "The required AutoText entry " & myATEntryName & " could not be
found." & vbCr & "Please contact the Service Desk for assistance.",
vbCritical, "AutoText Error"
Debug.Print myBkmkName & " " & myATEntryName
End Sub

It's a bit different from the OP's situation and from the solution that
Graham provided because the AutoText entries are always stored in the
attached template, but it does provide an example of error handling that
doesn't just rely on OERN and that notifies the user when an error occurs
and provides instruction on what to do in response to the error
condition. Of course, the only time the error handling is invoked is
during development because I always thoroughly test my templates before
releasing them to production. ;-P

And thus ends my defense of OERN...
--
Cheers!

Gordon Bentley-Mix
Word MVP

Doug Robbins - Word MVP said:
So something like 40 lines of code is better than On Error Resume Next,
which in some circumstances at least can be a perfectly acceptable
method of dealing with a situation, or better than making use of the
specific Error Number that is returned to perform a specific action if
that error occurs?

You have not said what that action should be and rather than cast
aspersions on the original programmer who used the On Error Resume Next,
I would sit back and think about what your successor will think of you
when he comes across those 40 odd lines of code.


--
Hope this helps,

Doug Robbins - Word MVP

Please reply only to the newsgroups unless you wish to obtain my
services on
a paid professional basis.

Graham,

Thanks very much for this. It's just what I was looking for. I really
appreciate it! (Thank you to Lene too for your input)

Keith

While I suspect Doug's approach will be the more realistic, your
question
raises a question that might be worth exploring further.
I take it we can assume Word before 2007, as Word 2007 moved the
goalposts
with respect to autotext entries with the introduction of building
blocks?

When you request an autotext entry, Word looks into the active
template
first, then in addin templates and finally in the normal template.
This
appears rather more complex to arrange with vba (though if better
programmers than I are watching they will no doubt jump in).

While you can insert an autotext entry using vba from the attached
(active) template or from the normal template if it is present, it is
not
possible to do so from an addin template without making that template
the
active template. You could therefore check for the presence of the
entry
in the active template then attach each add-in template in turn and
check
for the presence of the autotext entry before restoring the original
attached template. Finally checking the normal template. If the entry
is
found in any of these locations the macro quits. If not the user is
given
a message to that effect.

Dim oAT As AutoTextEntry
Dim strAttach As String
Dim strFilename As String
Dim addInPath As String
Dim oAddIn As Template
Dim bFound As Boolean
strAttach = Templates(1).Path _
& Application.PathSeparator _
& ActiveDocument.AttachedTemplate
addInPath = Options.DefaultFilePath(wdStartupPath)
strFilename = Dir$(addInPath & "\*.dot")
bFound = False
For Each oAT In ActiveDocument.AttachedTemplate.AutoTextEntries
If oAT.name = "klr" Then
ActiveDocument.AttachedTemplate.AutoTextEntries("klr").Insert _
Where:=Selection.Range
bFound = True
Exit For
End If
Next oAT
If bFound = False Then
While Len(strFilename) <> 0
ActiveDocument.AttachedTemplate = addInPath _
& Application.PathSeparator _
& strFilename
For Each oAT In ActiveDocument.AttachedTemplate.AutoTextEntries
If oAT.name = "klr" Then

ActiveDocument.AttachedTemplate.AutoTextEntries("klr").Insert _
Where:=Selection.Range
bFound = True
Exit For
End If
Next oAT
strFilename = Dir$()
Wend
ActiveDocument.AttachedTemplate = strAttach
End If
If bFound = False Then
For Each oAT In NormalTemplate.AutoTextEntries
If oAT.name = "klr" Then
NormalTemplate.AutoTextEntries("klr").Insert _
Where:=Selection.Range
bFound = True
Exit For
End If
Next oAT
End If
If bFound = False Then
MsgBox "Autotext entry not found"
End If



--
<>>< ><<> ><<> <>>< ><<> <>>< <>><<>
Graham Mayor - Word MVP

My web site www.gmayor.com

<>>< ><<> ><<> <>>< ><<> <>>< <>><<>


Well I tried this in the Access.FormsCoding newsgroup and got nothing
so
I'm giving it a shot here.



I'm cleaning up some code from a previous programmer who liked to put
"On
Error Resume Next" in places where he didnt' know how to test things
in
lines above code that might crash. For example, there are lines like
the
following:

Selection.InsertAfter "krh"
On Error Resume Next
Selection.Range.InsertAutoText

I really want to take otu the "On Error Resume Next" and replace it
with
a
test to see if the AutoTextEntry exists as follows:

Selection.InsertAfter "krh"
If <autotext entry("krh")> exists Then
Selection.Range.InsertAutoText
End If


But I have no idea how to do that. I know I can use NormalTemplate in
some
way but that is a problem in and of itself because we're nto using
the
Normal Template all the time. I need to search that and another as
well.

Anyway, some specific info on how to do this would be wonderful.

Thanks,

Keith

 
G

Greg Maxey

Understanding and admiring the scope of Graham's contribution, I still agree
with Doug that in this case the error handling seems to be the most
efficient approach. That said, I don't necessarily agree with the approach
used by the orignial coder. I don't think any of you really do either.

Selection.InsertAfter "krh"
On Error Resume Next
Selection.Range.InsertAutoText

Of course I have not seen all of the original code or the template, but I
will assume that the original coder has placed AutoText entries in the
document template that should function as intended without generating an
error. It the AutoText entry were inadvertenly (or intentionally) deleted
as some later time then the code as written would result in a seemingly
spurious "krh" entry that was intended to be something else.

If I was going to use the InsertAutoText method then I would probably
separate that out and call a sub routine from the main procedure each time I
wanted to place an AutoText entry at the selection. Perhaps something like
this:

Sub MainProcedure()
MyInsertAutoText "kroh"
End Sub

Sub MyInsertAutoText(ByRef pStr As String)
Dim oRng As Word.Range
Set oRng = Selection.Range
oRng.Text = pStr
On Error Resume Next
oRng.InsertAutoText
If Err.Number <> 0 Then
oRng.Comments.Add oRng, "A corresponding AutoText entry was not found."
Beep
End If
End Sub

This way the user of the document is made aware that document was not
constructed as the code intended.

Like Graham, I would also rather use the Insert method and attempt to
explicity insert the correct AutoText entry. However, it the entry was not
located in the template where I as the developer expected it to be, I would
not then go looking for it someplace else.

Sub MyInsertAutoText(ByRef pStr As String)
Dim oRng As Word.Range
Set oRng = Selection.Range
oRng.Text = pStr
On Error Resume Next
ActiveDocument.AttachedTemplate.AutoTextEntries(pStr).Insert Where:=oRng
If Err.Number <> 0 Then
oRng.Comments.Add oRng, "A corresponding AutoText entry was not found."
Beep
End If
End Sub

For Word2007, I use the more explicit BuildingBlocks over the general
BuildingBlockEntries because with the 20 different galleries and unlimited
categories it is very
possible to have two entries with the same name. BuildingBlockEntries uses
the first one in the indexed collection and so it may not be the intended
one.

Sub MainProcedure()
Templates.LoadBuildingBlocks
InsertSpecificBBE wdTypeAutoText, "General", "Test BE"
End Sub

Sub InsertSpecificBBE(ByRef pType As Long, pCat As String, pBBE As String)
Dim oTmp As Template
Dim oRng As Word.Range
Set oTmp = ActiveDocument.AttachedTemplate
Set oRng = Selection.Range
On Error GoTo Err_Handler
oRng.Text = pBBE
oTmp.BuildingBlockTypes(pType).Categories(pCat).BuildingBlocks(pBBE).Insert
oRng
Exit Sub
Err_Handler: 'Handles a missing entry
If Err.Number = 5941 Then
oRng.Comments.Add oRng, "A corresponding building block is not available
in the specified template."
End If
Set oTmp = Nothing
End Sub
 

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

Similar Threads

find existence of autotext entries 6
loop validation 2
looping validation 1
ActiveWindow RunTime Error 6
Save Autotext entry to User.dot 5
Autotext problem 2
AutoText in Word 2007 5
Forms and AutoText 0

Top