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.