469,269 Members | 1,006 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,269 developers. It's quick & easy.

Late binding not the answer to Reference.IsBroken

I've read many postings about the problem of Access.References.IsBroken
and the consensus seems to be that late binding is the cure-all.

I have a very complex Access application that needs hundreds of lines
of code to format a Word document in a very specific way.

Because my clients have various versions of Word, the problem of broken
references comes up. I wish Microsoft had implemented a reasonable
solution, so that VBA could do just what a user does (unticking the
MISSING references; it shouldn't be that difficult)! But the
References.Remove method fails miserably just when you need it most.

Late binding would be a disaster for me. If I had to convert every
Word.Range and Word.Style and Word.Table etc into an Object, every time
I make a minor change to the app, I'd not only go crazy but also
introduce new bugs.

So I'm hoping there is an API that I can call that will in effect
untick the MISSING references. Anyone know of such an API?

Thanks.

Nov 13 '05 #1
14 4119
On 19 May 2005 08:01:33 -0700, "Composer" <ke**********@beeb.net> wrote:
I've read many postings about the problem of Access.References.IsBroken
and the consensus seems to be that late binding is the cure-all.

I have a very complex Access application that needs hundreds of lines
of code to format a Word document in a very specific way.

Because my clients have various versions of Word, the problem of broken
references comes up. I wish Microsoft had implemented a reasonable
solution, so that VBA could do just what a user does (unticking the
MISSING references; it shouldn't be that difficult)! But the
References.Remove method fails miserably just when you need it most.

Late binding would be a disaster for me. If I had to convert every
Word.Range and Word.Style and Word.Table etc into an Object, every time
I make a minor change to the app, I'd not only go crazy but also
introduce new bugs.

So I'm hoping there is an API that I can call that will in effect
untick the MISSING references. Anyone know of such an API?


First, it sounds like you're raying you try to use code to remove the missing
reference at run-time, but if your code is written to handle late binding, you
don't need the reference checked, so uncheck it before delivering it rather
than have that be a run-time operation.

Next, what I do is use user-defined types to handle switching between early
and lat binding, so I can still use auto-sense and have the compiler help me
find typos, etc., then switch the binding just by commenting out one block of
type definitions and uncommenting another.

For instance, ...

' === Use the following definitions for early-binding ===

Public Type typWordApp
o As Word.Application
End Type

Public Type typWordDoc
o As Word.Document
End Type

' ...

' === Use the following definitions for late-binding ===

'Public Type typWordApp
' o As Object
'End Type
'
'Public Type typWordDoc
' o As Object
'End Type
'
'' ...

Now, when I want to create a reference to an MS Word application, I say
something like...

Dim wap as typWordApp

set wap.o = CreateObject("Word.Application")
Notice that I don't have to change anything to switch binding type except to
change which set of type definitions are used, and add or remove the refrence
to MS Word.
Nov 13 '05 #2
Thanks, Steve. I'll give that a try.

Nov 13 '05 #3
Steve, I've run into my first hurdle. I've done as you suggested with
typWordApp, and converted all instances of Word.Application in my code,
except for one.

The compiler complains about the following line:

Public Sub InitFromURL(URL As String, Optional WordApp As typWordApp)

Invalid optional parameter type. If I change it to

Public Sub InitFromURL(URL As String, Optional WordApp As typWordApp.o)

then I get a different compiler error: User-defined type not defined.
Have you come across this one?

Thanks.

Nov 13 '05 #4
On 19 May 2005 12:30:42 -0700, "Composer" <ke**********@beeb.net> wrote:
Steve, I've run into my first hurdle. I've done as you suggested with
typWordApp, and converted all instances of Word.Application in my code,
except for one.

The compiler complains about the following line:

Public Sub InitFromURL(URL As String, Optional WordApp As typWordApp)

Invalid optional parameter type. If I change it to

Public Sub InitFromURL(URL As String, Optional WordApp As typWordApp.o)

then I get a different compiler error: User-defined type not defined.
Have you come across this one?


I haven't come across it, but I know what's wrong. You can't use a
user-defined type as an optional parameter. I don't know why the compiler
accepts it even though it will always fail at run-time.

Post what the code looked like before - there's probably a simple way to
restructure the code to eliminate the need for the optional parameter.
Nov 13 '05 #5
Steve Jorgensen <no****@nospam.nospam> wrote in
news:de********************************@4ax.com:
On 19 May 2005 12:30:42 -0700, "Composer" <ke**********@beeb.net>
wrote:
Steve, I've run into my first hurdle. I've done as you suggested
with typWordApp, and converted all instances of Word.Application
in my code, except for one.

The compiler complains about the following line:

Public Sub InitFromURL(URL As String, Optional WordApp As
typWordApp)

Invalid optional parameter type. If I change it to

Public Sub InitFromURL(URL As String, Optional WordApp As
typWordApp.o)

then I get a different compiler error: User-defined type not
defined. Have you come across this one?


I haven't come across it, but I know what's wrong. You can't use
a user-defined type as an optional parameter. I don't know why
the compiler accepts it even though it will always fail at
run-time.

Post what the code looked like before - there's probably a simple
way to restructure the code to eliminate the need for the optional
parameter.


Why not just pass an object variable, then have an internal variable
that is of your custom type, and if the optional object variable is
passed, initialize the internal variable of your custom type.

If that makes any sense.

--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc
Nov 13 '05 #6
On Fri, 20 May 2005 22:45:45 GMT, "David W. Fenton"
<dX********@bway.net.invalid> wrote:
Steve Jorgensen <no****@nospam.nospam> wrote in
news:de********************************@4ax.com :
On 19 May 2005 12:30:42 -0700, "Composer" <ke**********@beeb.net>
wrote:
Steve, I've run into my first hurdle. I've done as you suggested
with typWordApp, and converted all instances of Word.Application
in my code, except for one.

The compiler complains about the following line:

Public Sub InitFromURL(URL As String, Optional WordApp As
typWordApp)

Invalid optional parameter type. If I change it to

Public Sub InitFromURL(URL As String, Optional WordApp As
typWordApp.o)

then I get a different compiler error: User-defined type not
defined. Have you come across this one?


I haven't come across it, but I know what's wrong. You can't use
a user-defined type as an optional parameter. I don't know why
the compiler accepts it even though it will always fail at
run-time.

Post what the code looked like before - there's probably a simple
way to restructure the code to eliminate the need for the optional
parameter.


Why not just pass an object variable, then have an internal variable
that is of your custom type, and if the optional object variable is
passed, initialize the internal variable of your custom type.

If that makes any sense.


In this case, using UDTs provides one huge advantage classes don't have.
There's a single module with 2 versions of one block of code that determines
whether early or late binding will be used for all the object types we need
from the MS Word library. With class modules, each class must be its own
distinct module, so everything isn't in just one place anymore.

Conditional compilation is no help, because conditional compilation variables
only apply within the modules in which they're defined, plus I've had too much
corruption using those, and resulting code tended to be hard to read and
modify.

Nov 13 '05 #7
I've done as David suggested, passing an Object as parameter, then
setting it to a UDT within the procedure. Everything seems to work.
Thanks to both of you!

Nov 13 '05 #8
As further thanks to you who have helped me, here's another way to do
it, which you might find to be less effort when switching between
Development mode and Delivery mode:

Instead of coding:

'Public Type objWordApp
' o As Word.Application
'End Type
'
'Public Type objWordDoc
' o As Word.Document
'End Type
'
Public Type objWordApp
o As Object
End Type

Public Type objWordDoc
o As Object
End Type

....you could more simply code:
Public Type objWordApp
' o As Word.Application
o As Object
End Type

Public Type objWordDoc
' o As Word.Document
o As Object
End Type

Nov 13 '05 #9
Steve Jorgensen <no****@nospam.nospam> wrote in
news:rh********************************@4ax.com:
On Fri, 20 May 2005 22:45:45 GMT, "David W. Fenton"
<dX********@bway.net.invalid> wrote:
Steve Jorgensen <no****@nospam.nospam> wrote in
news:de********************************@4ax.co m:
On 19 May 2005 12:30:42 -0700, "Composer"
<ke**********@beeb.net> wrote:

Steve, I've run into my first hurdle. I've done as you
suggested with typWordApp, and converted all instances of
Word.Application in my code, except for one.

The compiler complains about the following line:

Public Sub InitFromURL(URL As String, Optional WordApp As
typWordApp)

Invalid optional parameter type. If I change it to

Public Sub InitFromURL(URL As String, Optional WordApp As
typWordApp.o)

then I get a different compiler error: User-defined type not
defined. Have you come across this one?

I haven't come across it, but I know what's wrong. You can't
use a user-defined type as an optional parameter. I don't know
why the compiler accepts it even though it will always fail at
run-time.

Post what the code looked like before - there's probably a
simple way to restructure the code to eliminate the need for the
optional parameter.
Why not just pass an object variable, then have an internal
variable that is of your custom type, and if the optional object
variable is passed, initialize the internal variable of your
custom type.

If that makes any sense.


In this case, using UDTs provides one huge advantage classes don't
have. There's a single module with 2 versions of one block of code
that determines whether early or late binding will be used for all
the object types we need from the MS Word library. With class
modules, each class must be its own distinct module, so everything
isn't in just one place anymore.


I don't see what you've written as being at all related to my
suggestion.
Conditional compilation is no help, because conditional
compilation variables only apply within the modules in which
they're defined, plus I've had too much corruption using those,
and resulting code tended to be hard to read and modify.


Who said anything about conditional compilation?

--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc
Nov 13 '05 #10
On Sat, 21 May 2005 21:56:09 GMT, "David W. Fenton"
<dX********@bway.net.invalid> wrote:

....
Why not just pass an object variable, then have an internal
variable that is of your custom type, and if the optional object
variable is passed, initialize the internal variable of your
custom type.

If that makes any sense.


In this case, using UDTs provides one huge advantage classes don't
have. There's a single module with 2 versions of one block of code
that determines whether early or late binding will be used for all
the object types we need from the MS Word library. With class
modules, each class must be its own distinct module, so everything
isn't in just one place anymore.


I don't see what you've written as being at all related to my
suggestion.


Well, it didn't because I misread your suggestion. It seems you were talking
about wrapping the UDT in another custom class. That seems like a pretty
heavy pile of indirection when there's probably some simple way to just not
need the Word object as an optional parameter.

Nov 13 '05 #11
Steve Jorgensen <no****@nospam.nospam> wrote in
news:ep********************************@4ax.com:
On Sat, 21 May 2005 21:56:09 GMT, "David W. Fenton"
<dX********@bway.net.invalid> wrote:

...
Why not just pass an object variable, then have an internal
variable that is of your custom type, and if the optional object
variable is passed, initialize the internal variable of your
custom type.

If that makes any sense.

In this case, using UDTs provides one huge advantage classes
don't have. There's a single module with 2 versions of one block
of code that determines whether early or late binding will be
used for all the object types we need from the MS Word library.
With class modules, each class must be its own distinct module,
so everything isn't in just one place anymore.


I don't see what you've written as being at all related to my
suggestion.


Well, it didn't because I misread your suggestion. It seems you
were talking about wrapping the UDT in another custom class. That
seems like a pretty heavy pile of indirection when there's
probably some simple way to just not need the Word object as an
optional parameter.


No, I was saying no such thing.

I was saying to alter the optional parameter for the subroutine to
use an object variable and then, within the function, have a
variable that is your custom type definition that you assign the
optional parameter to, if it's been passed.

It was a simple suggestion and the original poster understood it and
made it work.

I'm not quite sure why you're reading an additional level of
complexity into my reply -- I said nothing about class wrappers, nor
did I imply it.

--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc
Nov 13 '05 #12
On Sun, 22 May 2005 16:51:08 GMT, "David W. Fenton"
<dX********@bway.net.invalid> wrote:
Steve Jorgensen <no****@nospam.nospam> wrote in
news:ep********************************@4ax.com :

....
Well, it didn't because I misread your suggestion. It seems you
were talking about wrapping the UDT in another custom class. That
seems like a pretty heavy pile of indirection when there's
probably some simple way to just not need the Word object as an
optional parameter.


No, I was saying no such thing.

I was saying to alter the optional parameter for the subroutine to
use an object variable and then, within the function, have a
variable that is your custom type definition that you assign the
optional parameter to, if it's been passed.

It was a simple suggestion and the original poster understood it and
made it work.

I'm not quite sure why you're reading an additional level of
complexity into my reply -- I said nothing about class wrappers, nor
did I imply it.


OK, I see it now. My confusion was with "Why not just pass an object
variable, then have an internal variable that is of your custom type?" I
interpreted "internal" to mean internal to the object, not to the called
procedure.

I still don't like the approach. We create a new UDT to wrap a Word document
with the idea that we only reference the contained object to invoke its
methods or examine its properties - then break that convention by unwrapping
and rewrapping the object just so we can pass an optional parameter, and we've
never even discussed why there needs to be an optional parameter there.

I'm not saying it couldn't be a reasonable compromise if there truly is a very
good reason for the optional parameter, and there's no reasonable alternate
construction, but the poster never even entertained the discussion of why the
optional parameter is employed here and whether other options might be as good
or better.
Nov 13 '05 #13
Steve Jorgensen <no****@nospam.nospam> wrote in
news:8c********************************@4ax.com:
On Sun, 22 May 2005 16:51:08 GMT, "David W. Fenton"
<dX********@bway.net.invalid> wrote:
Steve Jorgensen <no****@nospam.nospam> wrote in
news:ep********************************@4ax.co m:

...
Well, it didn't because I misread your suggestion. It seems you
were talking about wrapping the UDT in another custom class.
That seems like a pretty heavy pile of indirection when there's
probably some simple way to just not need the Word object as an
optional parameter.


No, I was saying no such thing.

I was saying to alter the optional parameter for the subroutine to
use an object variable and then, within the function, have a
variable that is your custom type definition that you assign the
optional parameter to, if it's been passed.

It was a simple suggestion and the original poster understood it
and made it work.

I'm not quite sure why you're reading an additional level of
complexity into my reply -- I said nothing about class wrappers,
nor did I imply it.


OK, I see it now. My confusion was with "Why not just pass an
object variable, then have an internal variable that is of your
custom type?" I interpreted "internal" to mean internal to the
object, not to the called procedure.

I still don't like the approach. We create a new UDT to wrap a
Word document with the idea that we only reference the contained
object to invoke its methods or examine its properties - then
break that convention by unwrapping and rewrapping the object just
so we can pass an optional parameter, and we've never even
discussed why there needs to be an optional parameter there.

I'm not saying it couldn't be a reasonable compromise if there
truly is a very good reason for the optional parameter, and
there's no reasonable alternate construction, but the poster never
even entertained the discussion of why the optional parameter is
employed here and whether other options might be as good or
better.


Well, that's a discussion that hasn't happened yet.

I provided a solution that solved the immediate problem. I find
myself in many cases running into architectural flaws in my own code
just like this, and it presents me with a choice:

1. implement the quick-and-dirty workaround, which takes 2 minutes,
OR

2. completely redesign the code to avoid the workaround, which can
take anywhere from 10 minutes to 10 hours.

If it's a choice betweeen 2 and 10 minutes, I choose 10 minutes. If
it's more complicated than that, and I just need to get it done, I
do the quick-and-dirty workaround.

I suspect you do exactly the same thing, and in the present
instance, there's a major re-design of code going on already by
implementing the custom type as an easy way to switch between early
and late binding, so it might be justified at this point to figure
out how to redesign to avoid passing the optional parameter.

But I just answered the question, more in the mode of the New Steve
Jorgensen, who is in favor of small changes that just make things
work, as opposed to the Old Steve Jorgensen, who favored going back
to Adam and Eve to fix such problems. ;)

--
David W. Fenton http://www.bway.net/~dfenton
dfenton at bway dot net http://www.bway.net/~dfassoc
Nov 13 '05 #14
On Mon, 23 May 2005 19:16:00 GMT, "David W. Fenton"
<dX********@bway.net.invalid> wrote:
Steve Jorgensen <no****@nospam.nospam> wrote in
news:8c********************************@4ax.com : ...But I just answered the question, more in the mode of the New Steve
Jorgensen, who is in favor of small changes that just make things
work, as opposed to the Old Steve Jorgensen, who favored going back
to Adam and Eve to fix such problems. ;)


Well, nothing's absolute, so don't expect to see me stop all overengineering
any day soon <g>.
Nov 13 '05 #15

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

21 posts views Thread by Mike MacSween | last post: by
1 post views Thread by JD Kronicz | last post: by
7 posts views Thread by PC Datasheet | last post: by
9 posts views Thread by Zlatko Matić | last post: by
30 posts views Thread by lgbjr | last post: by
6 posts views Thread by Tim Roberts | last post: by
14 posts views Thread by Siv | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by suresh191 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.