Using WithEvents  on Crystal Reports 8.5 sections

Posted on 2003-12-01
Last Modified: 2011-09-20
Hi Experts,

Below are VB6 code lines that works with crystal reports.
I got this from crystal reports site.
What is does is open a given crystal reports and when you try to preview it (using RDC),
it will then capture the value for each object (formula, fieldname, etc.) for each report section.
Display each value on a given lists box.

What I wanted is to make these into a sort of a function/procedure to work with all reports.
It will be something like a function that takes the report name as parameter and then using that one, will then grab all object for all report section.

I can't seem to make it work because of the WIthEvents keyword. It seems A WithEvents variable cannot be a generic object variable.
Because each report will have a diff'rent number of sections (some may contain as less as 5 and others will be as much as 15), I'd like to have a function that will have these declared generically.

Using WithEvents might not be the only solution so I'm hoping any of you guys can show me a way to make this work.

I can send the complete sourcecode(with the form, reports and sample database) if any of you guys wanted it. Just indicate the email address where to send to.

If this is not the right area (as I can see there are 2 sections for VB namely VB controls and VB DB, please let me know so that I can move this on the right topic area.

Thanks a lot,

Dim Report As CRAXDRT.Report
Dim crApplication As New CRAXDRT.Application

' these sections must be declared with events in order to grab the values
' from inside the sections
Dim WithEvents crSectionRH  As CRAXDRT.Section
Dim WithEvents crSectionPH As CRAXDRT.Section
Dim WithEvents crSectionD As CRAXDRT.Section
Dim WithEvents crSectionGF As CRAXDRT.Section

Dim crObject As Object
Dim crTextObject As CRAXDRT.TextObject
Dim crFieldObject As CRAXDRT.FieldObject

Private Sub Form_Load()
Screen.MousePointer = vbHourglass

Set Report = crApplication.OpenReport(App.Path & "\report1.rpt")

' set the all the sections
Set crSectionRH = Report.Sections("RH")
Set crSectionPH = Report.Sections("PH")
Set crSectionD = Report.Sections("D")
Set crSectionGF = Report.Sections("GF")

CRViewer1.ReportSource = Report
Screen.MousePointer = vbDefault

End Sub

Private Sub FillListBox(ByRef crSection As CRAXDRT.Section)

' check each object in the section
For Each crObject In crSection.ReportObjects
    ' we are only considering two cases right now 1. if it is a text object, or if it is a field object
    Select Case crObject.Kind
        Case CRAXDRT.CRObjectKind.crTextObject:
            Set crTextObject = crObject
            ' add the name and the value to the list box so you can see what is happening
            List1.AddItem crTextObject.Name
            List1.AddItem "  " & crTextObject.Text
        Case CRAXDRT.CRObjectKind.crFieldObject:
            Set crFieldObject = crObject
            ' add the name and the value to the list box so you can see what is happening
            List1.AddItem crFieldObject.Name
            List1.AddItem "  " & crFieldObject.Value
    End Select
    Set crTextObject = Nothing
    Set crFieldObject = Nothing

End Sub

Private Sub crSectionRH_Format(ByVal pFormattingInfo As Object)

Call FillListBox(crSectionRH)

End Sub

Private Sub crSectionGF_Format(ByVal pFormattingInfo As Object)

Call FillListBox(crSectionGF)

End Sub
Private Sub crSectionPH_Format(ByVal pFormattingInfo As Object)

Call FillListBox(crSectionPH)
End Sub

Private Sub crSectionD_Format(ByVal pFormattingInfo As Object)

Call FillListBox(crSectionD)

End Sub

Private Sub Form_Resize()
CRViewer1.Top = 0
CRViewer1.Left = List1.Left + List1.Width + 50
CRViewer1.Height = ScaleHeight
CRViewer1.Width = ScaleWidth - CRViewer1.Left

End Sub

Private Sub List1_Click()

End Sub


Question by:jrmn
  • 2
LVL 30

Expert Comment

ID: 9849684
I'm not sure I understand exactly what you want, but if you wish to raise a generic event from a number of particular events you can do this:

1. Create a class which declares your required objects Withevents
2. When handling the events, raise a generic event which has the object type as a string parameter
3. Declare the class you just created Withevents in another class
4. The class created in step 4 now receives one event even underneath it all there are a whole bunch of objects.

Some very basic example code that will give you an idea of what I am talking about:

Event GenericEvent(ByVal sType as String, ByVal sData as String)

 these sections must be declared with events in order to grab the values
' from inside the sections
Dim WithEvents crSectionRH  As CRAXDRT.Section
Dim WithEvents crSectionPH As CRAXDRT.Section
Dim WithEvents crSectionD As CRAXDRT.Section
Dim WithEvents crSectionGF As CRAXDRT.Section

Dim crObject As Object
Dim crTextObject As CRAXDRT.TextObject
Dim crFieldObject As CRAXDRT.FieldObject

' Event handlers... all specific events are redirected to one generic event.
Private Sub crSectionRH_Format(ByVal pFormattingInfo As Object)
  RaiseEvent GenericEvent("SectionRH", pFormattingInfo.Data)
End Sub

Private Sub crSectionGF_Format(ByVal pFormattingInfo As Object)
  RaiseEvent GenericEvent("SectionGF", pFormattingInfo.Data)
End Sub

Author Comment

ID: 9854626
Hi nmcdermaid,

Thanks for the reply. I'd like to know if you know crystal reports so that we can discuss this as clearly as possible.

Is there a way to have the WithEvents declaration generic?
I mean for each report, assume you don't know how many sections are being use. Say detail section could be actually of 2 sections detailA and detailB.
If we are going to declare each section specifically, I guess the code will work only for few reports that has the same number of sections we declare for the WithEvents.
I'd like to have a way of having a function that will work for all reports.
Say myreport.rpt have 6 sections (RH, PH, Da(detail section A), Db(detail section B), GH and GF)

1. First we open the report.
2. Then we will check how many sections are there for this report.
3. Check what section(s) are being suppressed (as it is very possible and usually, report header and footer sections are being suppressed at designed time)
4. Then given these information, (say we know that only 4 sections are being used and we know which section (name) are these), we will then declare a WithEvents for each of these sections.
5. Each of these declared sections (WithEvents) will be use the GenericEvent we will be providing.

Is this possible?

As I have said, using WithEvents might not be the only solution. I am hoping to get another solution.

If you like, I can give you the complete source codes and other files you might need so that you can try it at your end.
Just let me know where to send it to (email).

LVL 30

Accepted Solution

nmcdermaid earned 120 total points
ID: 9856898
The limitation is in the parameters in the event rasied by the Crystal library.

If you are lucky, the object returned by the event will contain the section name, so you would only have to declare one section withevents, and the object event raised by it would be for all sections in the report, and the object contains the name and can be handled accordingly.

However I doubt if it works that way, so you need to make a class wrapper that forces it to work that way!!

This is the only way I can think of making that class wrapper:

1. Make a class that declares 100 sections withevents (damn ugly but you can't declare arrays with events)

2. Have a method in the class which allows you to assign section names to the internal sections object variables in the class. In the method you will need to use a big ugly case statement to pick the correct section object variable, and an index to move along the 100 object variables.

3. Have 100 event handlers for those 100 sections objects. (Ugly ugly ugly). In each event handler, raise a single event which passes the Object as well as the section name.

Then in the class you are currently working on, make one instance of the class I have just described. Use the method I described at point 2 to add sections dynamically as required. Handle the event described in point 3 to handle the sections dynamically.

Its ugly but it work (as long as you don't have more than 100 sections! ;))

Someone may have a better way to do this but basically these are the limitations which make me think that this is the only way to do wha you want.

-You can't declare an object variable withevents as an array (or collection)
-The event raised by the Crystal library is per each section object rather than one for the entire report.


Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

There are many ways to remove duplicate entries in an SQL or Access database. Most make you temporarily insert an ID field, make a temp table and copy data back and forth, and/or are slow. Here is an easy way in VB6 using ADO to remove duplicate row…
You can of course define an array to hold data that is of a particular type like an array of Strings to hold customer names or an array of Doubles to hold customer sales, but what do you do if you want to coordinate that data? This article describes…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

920 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now