Data Access Worldwide Knowledge Base
Article ID 2251 Article Title HOWTO: Find out if a CRW report was finished Article URL http://www.dataaccess.com/kbasepublic/KBPrint.asp?ArticleID=2251 KBase Category VDF11 Date Created 10/17/2006 Last Edit Date 11/28/2006
Article Text
QUESTION:
One of the main differences that I discovered between the classic API based CRW interface and the CRW XI RDC interface is that while you see the output being generated in a reportview window your program can continue. I however want to know when a report is finished and, because of this change, I can no longer rely on the fact that when runreport finished the report is finished too. How do I find out if the report was finished?
ANSWER:
In the RDC interface the Report object has a child object called PrintStatus. One of the properties of this object is called Progress. The values for this property are NotStarted, InProgress, Completed, Failed, Cancelled and Halted.
To use the PrintStatus object the Report object must be available. When you send RunReport to the Crystal Object in your application the report is opened, output is started and the report is closed. So if you query the PrintStatus after the RunReport has finished, you will be too late. In fact in order to query the status we need to alter the RunReport message and send the CloseReport ourselves.
So normally you do:
Object oTestReport Is A cCrystal
Set psReportName To "MySpecialReport.Rpt"
End_Object
Object oStartButton Is A Button
Procedure OnClick
Send RunReport Of oTestReport
End_Procedure
End_Object
If we change this to:
Object oTestReport Is A cCrystal
Set psReportName To "MySpecialReport.Rpt"
Procedure RunReport
Boolean bOK
Set pbHasErrors to false
// direct to local error handler
Set Old_Error_Object_id to Error_Object_id
Move Self To Error_Object_id
Get OpenReport to bOK
If (bOK) Begin
Send OutputReport
End
// restore error handler
Get Old_Error_Object_id to Error_Object_id
End_Procedure
End_Object
We can add the PrintStatus testing to the OnClick method. For example:
Object oStartButton Is A Button
Procedure OnClick
Variant vPrintStatus
Handle hoReport hoStatus
Integer iStatus
Send RunReport Of oTestReport
Get ReportObject Of oTestReport To hoReport
If (hoReport > 0) Begin
Get ComPrintingStatus Of hoReport To vPrintStatus
If (Not (IsNullComObject (vPrintStatus))) Begin
Get Create U_cCrystalPrintingStatus To hoStatus
If (hoStatus > 0) Begin
Set pvComObject of hoStatus To vPrintStatus
While (iStatus <> crPrintingCompleted)
Get ComProgress Of hoStatus To iStatus
Loop
Send Destroy Of hoStatus
End
End
End
Send CloseReport Of oTestReport
End_Procedure
End_Object
If you implement above you will find out that there is a major problem. We ask too often if the report was finished or not. In fact so often that the report never prints. To solve this problem we need a timer object that from time to time finds out if the report was finished.
If you drag a timer object to the view and modify it to:
Object oTimer1 Is A DfTimer
Procedure OnTimer Integer wParam Integer lParam
Variant vPrintStatus
Handle hoReport hoStatus
Integer iStatus
Get ReportObject Of oTestReport To hoReport
If (hoReport > 0) Begin
Get ComPrintingStatus Of hoReport To vPrintStatus
If (Not (IsNullComObject (vPrintStatus))) Begin
Get Create U_cCrystalPrintingStatus To hoStatus
If (hoStatus > 0) Begin
Set pvComObject of hoStatus To vPrintStatus
Get ComProgress Of hoStatus To iStatus
Send Destroy Of hoStatus
End
End
End
If (iStatus = crPrintingCompleted) Begin
// Somewhere store that report was finished
Send CloseReport Of oTestReport
End
End_Procedure // OnTimer
End_Object
You have a solution.
But, it can be done with a class too that integrates both the timer and the cCrystal object making it easier. Find a new subclass of cCrystal attached to this KB item. You need to register the class in the classlist for VDF11 before you can use it.
In AppSrc.zip you find:
cWSCrystal.Pkg: New cCrystal based class
OrdersCR2.rv: Modified OrdersCR.rv with sample code on usage
In IDESrc.zip you find the DFC, DFO and Bitmap that you can use to make Studio aware of the new class. Refer to the VDF documentation if you do not know how to register a class in the VDF11.1 Studio.
2006.Nov.28: Add IF statements for the several handles in above code blocks.
Contributed By:
Vincent Oorsprong
Company: Data Access Worldwide
email: vincent.oorsprong@dataaccess.eu
Web Site: http://www.dataaccess.eu
Web Links Related to this Article
File AppSrc.zip
URL=http://www.dataaccess.com/KBasePublic/Files/2251.AppSrc.zip
File IDESrc.zip
URL=http://www.dataaccess.com/KBasePublic/Files/2251.IDESrc.zip
Email this Article
Email this Article to a Colleague
Send Feedback on this Article to Data Access Worldwide
Copyright ©2010 Data Access Corporation. All rights reserved.
The information provided in the Data Access Technical Knowledge Base is provided "as is" without warranty of any kind. Data Access Corporation disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. In no event shall Data Access Corporation or its suppliers be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages, even if Data Access Corporation or its suppliers have been advised of the possibility of such damages. Some states do not allow the exclusion or limitation of liability for consequential or incidental damages so the foregoing limitation may not apply.