Printing error: Cannot perform this operation on a closed dataset
Hello,
I have developed an end-user reporting application using ADO following all
the examples in the demos and tutorials. I have a Report Explorer and allow
the user to develop custom reports The backend database is Microsoft SQL
Server. The app is written in Delphi 5. Everything works well except
printing. When Print Preview is opened to display the report, it shows the
report correctly. I then click on the Print button, bring up the Print
Dialog box and when I hit OK, a message box comes up that says "Accessing
data" and then I get an immediate AV with the message "Cannot perform this
operation on a closed dataset". I've tried a lot of things, but I can't get
past this error. Do you have any idea what the problem is?
Thanks (and thanks for the help in the past also),
Les Bloom
I have developed an end-user reporting application using ADO following all
the examples in the demos and tutorials. I have a Report Explorer and allow
the user to develop custom reports The backend database is Microsoft SQL
Server. The app is written in Delphi 5. Everything works well except
printing. When Print Preview is opened to display the report, it shows the
report correctly. I then click on the Print button, bring up the Print
Dialog box and when I hit OK, a message box comes up that says "Accessing
data" and then I get an immediate AV with the message "Cannot perform this
operation on a closed dataset". I've tried a lot of things, but I can't get
past this error. Do you have any idea what the problem is?
Thanks (and thanks for the help in the past also),
Les Bloom
This discussion has been closed.
Comments
set to true on the DataPipeline which is connected to the Report.
Cheers,
Jim Bennett
Digital Metaphors
http://www.digital-metaphors.com
info@digital-metaphors.com
Thanks for answering.
The OpenDataSource properties are true for all the pipelines I have. I have
4 pipelines: one each for Folders, Items, Tables and Fields as in the
standard end-user Report Explorer based application. I definitely can
generate reports and see them in Print Preview. I get the error only after
I click on Print in the default Print Dialog.
- Les
which affects the ADOConnection? Be aware the the report events will fire
again when you choose to print the report after previewing, unless
Report.CachePages is true and the selected printer wasn't changed in the
print dialog. Are you loading templates or changing anything with the
Report.DataPipeline in code? Can you reproduce the problem using our ADO SQL
Server end user demo on your database?
Cheers,
Jim Bennett
Digital Metaphors
http://www.digital-metaphors.com
info@digital-metaphors.com
I have written no code which affects the ADOConnection. I am not loading
templates or changing anything with Report.DataPipeline in code.
I can reproduce the problem using the ADO SQL Server end user demo on my
database. I have not modified the demo code at all except for the
TADOConnection ConnectionString property and I get the exact same error in
the exact same place.
- Les
demo? Can you test with Delphi 6 or 7 too?
Cheers,
Jim Bennett
Digital Metaphors
http://www.digital-metaphors.com
info@digital-metaphors.com
I am using D5/RB4.11. I do not have the ability to test with other versions
of Delphi.
To set up the system, I ran your included SQL scripts
(CreateEndUserTables.SQL) to add the necessary End User table support to my
database. I also changed the TADOConnection ConnectionString property to
point to my database, login, pw, etc. I then compiled the application
("Demos\4. End User Databases\2. SQL Server 7\2. ADO").
To run it, I start the app, click OK on the main form to create the Report
Explorer. I can create Reports, put them in folders, etc. without any
problems. To cause the error to occur, I select a report and click Print
Preview (or alternately, go into Designer and click the Preview tab). I can
see the report without any problem. I then click the Print button. That
brings up the Printer dialog box. It correctly points to the default
printer. I click OK to begin printing. The "Accessing data" dialog box
appears. the printer icon appears in the system tray, and then the error
message pops up ("Cannot perform this operation on a closed dataset").
I realize that there are newer versions of RB, however this basic piece of
functionality should work, should it not? We have already shipped product
with the existing versions and would like to add the Report Explorer feature
to it (that's actually the reason we bought the "Pro" version in the first
place).
Thanks again for your help and insight.
- Les
Here's another clue / observation: If I don't Preview the report first, but
instead just click on the Report Explorer "Print" button, the Print Dialog
comes up and when I hit OK, the report prints perfectly on the printer. It
appears that by Previewing the report first, the database tables are perhaps
closed (??) causing the error to later occur when printing is invoked.
- Les
I think I fixed it by changing the source code in the TppReport.RequestPage
in ppreport.pas. I took the Engine.Reset out of the "if" clause as in the
code below. It looks like the Reset needs to be called before Previewing as
well as before printing. Does this make sense to you? Am I causing any
harm by doing this? Everything seems to work fine now.
- Les
{ TppReport.RequestPage }
procedure TppReport.RequestPage(Sender: TObject; aPageSetting:
TppPageSettingType;
aPageNo: Longint; aPageList: TStrings);
begin
inherited RequestPage(Sender, aPageSetting, aPageNo, aPageList);
{generate the pages}
try
Printing := True;
try
{set page size}
if not(Engine.Page.PrinterSetup.IsEqual(PrinterSetup)) then
begin
Engine.Page.PrinterSetup := PrinterSetup;
// Engine.Reset; // Les commented out 8/22/03
end;
Engine.Reset; // Les added line here instead 8/22/03
Engine.RequestPage(aPageSetting, aPageNo, aPageList);
except
on EPrintError do
begin
Engine.Printing := False;
Engine.Reset;
raise;
end;
on EAccessViolation do
begin
Engine.Printing := False;
Engine.Reset;
raise EPrintError.Create('Cannot generate report.');
end;
on EPrinter do
begin
Engine.Printing := False;
Engine.Reset;
raise EPrintError.Create('Cannot generate report.');
end;
end; {try, except}
finally
Printing := False;
end; {try, finally}
{if the user cancels the job, notify devices, reset engine}
if Engine.StopPrinting then
Engine.Reset;
end; {procedure, RequestPage}
Jim,
The solution below is not such a good idea. By changing the source code as
below, whenever you view the previous or next pages in Print Preview, you
end up resetting the engine and start regenerating the report from the
beginning instead of from where you are at.
I came up with a bettter fix. Instead of changing your source code, I
added an event handler which gets called whenever the Print Dialog is
created. In that handler, I reset the engine as follows:
procedure TfrmRbForm.PrintDialogCreateEvent(Sender: TObject);
begin
ppReport1.Engine.Reset;
end;
This works well. Do you see any downside to this?
Thanks,
- Les
it should repaginate when you print to the printer. Calling
Report.Engine.Reset will clear the page cache and the engine will have to
regenerate the pages. That should be fine. Can you download and test with RB
7.03 www.digital-metaphors.com to see if your problem persists in the latest
version?
Cheers,
Jim Bennett
Digital Metaphors
http://www.digital-metaphors.com
info@digital-metaphors.com
I wouldn't mind downloading the latest version and testing it, but I'm
nervous about it. Does that mean I have to uninstall the version I have,
then install the trial version and, after the test, reinstall my full
version?
- Les
wouldn't interfere with your current development using your installed
version of RB.
Cheers,
Jim Bennett
Digital Metaphors
http://www.digital-metaphors.com
info@digital-metaphors.com