stacking DoCmd.OpenReport View:=acViewPreview

  • Thread starter Thread starter AmendConstitution_ArnoldForPresident
  • Start date Start date
A

AmendConstitution_ArnoldForPresident

I have a loop to do [this subject] 5 times in a row (with different
reports). Unfortunately the code doesn't wait around for the user to
close the first preview before it proceeds (thus only 1 of the 5 gets
previewed by user).

Can I make the code "wait" until preview is complete, or what else
would be the cleanest solution? TIA
 
I'm nearly running blind with the n/g response time so I may walk over
a reply on this...

To pause code until preview is complete, my hokey workaround is a
global, and preceding the preview with
While bAReportIsOpen: DoEvents: Wend

and the last line in Report_open is bAReportIsOpen=true
and the last line in Report_close is bAReportIsOpen=false

Does this seem sound, for lack of anything else?
 
AmendConstitution_ArnoldForPresident said:
I have a loop to do [this subject] 5 times in a row (with different
reports). Unfortunately the code doesn't wait around for the user to
close the first preview before it proceeds (thus only 1 of the 5 gets
previewed by user).

Can I make the code "wait" until preview is complete, or what else
would be the cleanest solution? TIA

What version of Access are you using? If you're using Access 2002 or
later, you can specify a WindowMode:=acDialog argument, which will
prevent the next line of code from executing until the report you opened
on this line is closed.

But ... is there some reason you don't want to open all the reports at
once? Does the user *have* to preview one before you open the next?
 
Dirk Goldgar said:
What version of Access are you using? If you're using Access 2002 or
later, you can specify a WindowMode:=acDialog argument

Ah, okay, I'm on A97 and A2000.
I have a loop to do [this subject] 5 times in a row (with different
reports). Unfortunately the code doesn't wait around for the user to
close the first preview before it proceeds (thus only 1 of the 5 gets
previewed by user).
But ... is there some reason you don't want to open all the reports at
once? Does the user *have* to preview one before you open the next?

I'd be fine with that but it doesn't work that way. I misstated exactly
what I'm doing, and you are probably correct for the flip case: there
are not actually 5 reports; it's the same report each time. I just
vary the recordsource. In this situation, previews 2 through 5 are
essentially no-ops. Furthermore, A2002 may function differently too.

FWIW my technique is to set a global string as recordsource, a la
for i=1 to 5
gsRecSource=RecSourceArray(i)
DoCmd.OpenReport Reportname:=rptFoo View:=acViewPreview
next
and Report_Open reacts appropriately to the global. If I walk the code,
there's time to close each preview; at full speed, previews 2 through 5 die :(

Thanks very kindly for your assistance.
 
AmendConstitution_ArnoldForPresident said:
What version of Access are you using? If you're using Access 2002 or
later, you can specify a WindowMode:=acDialog argument

Ah, okay, I'm on A97 and A2000.
I have a loop to do [this subject] 5 times in a row (with different
reports). Unfortunately the code doesn't wait around for the user
to
close the first preview before it proceeds (thus only 1 of the 5
gets
previewed by user).
But ... is there some reason you don't want to open all the reports
at
once? Does the user *have* to preview one before you open the next?

I'd be fine with that but it doesn't work that way. I misstated
exactly
what I'm doing, and you are probably correct for the flip case: there
are not actually 5 reports; it's the same report each time. I just
vary the recordsource. In this situation, previews 2 through 5 are
essentially no-ops. Furthermore, A2002 may function differently too.

FWIW my technique is to set a global string as recordsource, a la
for i=1 to 5
gsRecSource=RecSourceArray(i)
DoCmd.OpenReport Reportname:=rptFoo View:=acViewPreview
next
and Report_Open reacts appropriately to the global. If I walk the
code,
there's time to close each preview; at full speed, previews 2 through
5 die :(

Thanks very kindly for your assistance.

Aside from the expedient you've already discovered, of looping with
DoEvents while the report is open (and you could also use SysCmd() to
check that), I can think of a way that might let you open all 5 versions
of the report at once, with different recordsources. This seems to work
in A97 through A2K2, but I've haven't done enough testing to ensure
there isn't a down side. Here's the idea: since the report has a class
module, you could open multiple *instances* of the same report. Code
might look like this:

Dim rpt As Report_rptFoo
Dim i As Integer

For i = 1 to 5
gsRecSource = RecSourceArray(i)
Set rpt = New Report_rptFoo
rpt.Visible = True
DoEvents
Set rpt = Nothing
Next i

You may have to do DoCmd.MoveSize with each report after it has been
made visible to keep them all from sitting on top of each other.

Interestingly, I'd have thought you'd have to keep an object set to each
report, and that the reports would close when their reference objects
went out of scope or were set to Nothing, but that doesn't seem to be
the case.
 
Dirk Goldgar said:
Aside from the expedient you've already discovered, of looping with
DoEvents while the report is open (and you could also use SysCmd() to
check that), I can think of a way that might let you open all 5 versions
of the report at once, with different recordsources. This seems to work
in A97 through A2K2, but I've haven't done enough testing to ensure
there isn't a down side. Here's the idea: since the report has a class
module, you could open multiple *instances* of the same report. Code
might look like this:

Dim rpt As Report_rptFoo
Dim i As Integer

For i = 1 to 5
gsRecSource = RecSourceArray(i)
Set rpt = New Report_rptFoo
rpt.Visible = True
DoEvents
Set rpt = Nothing
Next i

You may have to do DoCmd.MoveSize with each report after it has been
made visible to keep them all from sitting on top of each other.

I don't see any downside either! This is a keeper. If that changes,
I'll report back in this thread. This was also instructive to me.
Besides inspiring me to peruse Syscmd details, I found that
Report_rptFoo was a valid object. That was a big surprise - and that
it could be "New"-ed. Your help is all useful.
Interestingly, I'd have thought you'd have to keep an object set to each
report, and that the reports would close when their reference objects
went out of scope or were set to Nothing, but that doesn't seem to be
the case.

Me too, at first blush, but both you and Help on New use the word
"reference," so killing the reference doesn't kill the source. If you
set a reference to a printer and Nothing-ed it, the H.P. wouldn't die.
Apparently "New" is just like that with the addition of causing
creation. Or at least, that's what I'm adopting as my meager-minded
interpretation :)

Side musing...is "Nothing"-ing just an inexpensive defensive move now?
In A97+ or A00+ are {Set...=Nothing}'s still meaningful, or just
evidence of good form and stylishness by "Coders' coders?" :=)
 
AmendConstitution_ArnoldForPresident said:
I don't see any downside either! This is a keeper. If that changes,
I'll report back in this thread. This was also instructive to me.
Besides inspiring me to peruse Syscmd details, I found that
Report_rptFoo was a valid object. That was a big surprise - and that
it could be "New"-ed. Your help is all useful.


Me too, at first blush, but both you and Help on New use the word
"reference," so killing the reference doesn't kill the source. If you
set a reference to a printer and Nothing-ed it, the H.P. wouldn't die.
Apparently "New" is just like that with the addition of causing
creation. Or at least, that's what I'm adopting as my meager-minded
interpretation :)

Well, that's not exactly right. As a rule, when the last reference to
an object is destroyed, whether because you explicitly set it to Nothing
or because the reference variable goes out of scope or is reset, the
object itself is destroyed. When you use this same technique with forms
(e.g., Set frm = New Form_frmFoo), as is described in the help file, you
*must* keep a reference to the form instance for as long as you want the
form to remain open, because when the last reference to that form object
goes out of scope, the form will be closed and the instance will be
destroyed. The customary way around this is to add the instance to a
global collection of your own, from which you remove it when the form is
closed.

So why is it different with reports? Here's the key: when you open a
*form* in a normal way, via the user interface or the OpenForm method or
action, a reference to that form is added to the application's Forms
collection. It's this reference that keeps the form "alive". This is
called the "default instance" of the form. But when you open a
non-default instance of the form by using "Set object = New ...", a
reference to this instance is *not* added to the Forms collection. So
it's up to you to keep the object alive by maintaining a reference to
it.

I expected reports to work the same way. But my tests show that when
you use this technique to create an instance of the report, a reference
to the new instance *is* added to the Application's Reports collection,
just as it is when you use OpenReport or open the report via the user
interface. And since there's a reference to the report in the Reports
collection, the report remains open even after your local reference is
destroyed. All instances of the same report have the same name, so you
can't index the Reports collection by name to find a specific instance
among several, but if that doesn't bother you, you appear to be home
free. In my tests, I set the Caption property of each instance to a
different value so that it would be easy to find the one I want, whether
programmatically or while looking at the report preview windows.
Side musing...is "Nothing"-ing just an inexpensive defensive move now?
In A97+ or A00+ are {Set...=Nothing}'s still meaningful, or just
evidence of good form and stylishness by "Coders' coders?" :=)

Interesting you should ask. Some of my colleagues and I have been
discussing just this question. Theoretically, VB should destroy all
local variables when they go out of scope, so you shouldn't have to set
anything but a global or static object variable to Nothing. However,
there appears to have been a bug, at some time in the past and *maybe*
still in recent versions, when Access didn't always release and destroy
local object references as they went out of scope. This was reported as
happening with DAO objects like Recordset and Database objects. The
result was that Access wouldn't close, but would remain open (if
invisible) until you used Task Manager to blow it away.

I don't know the specifics of this bug, and I'm not entirely convinced
that it wasn't always a result of using static or global objects rather
than local ones. But if there *was* a bug, it would have affected
Access 97, and I don't know if it's fixed now -- in current SPs of A97
or in later versions of Access -- or not. So I still recommend the
practice of closing what you open and explicitly setting all object
variables to Nothing when you're done with them.
 
Back
Top