Printnig CR9 Subreport from VB6

Posted on 2004-04-19
Last Modified: 2010-05-18
I am attempting to write a VB6 viewer for Crystal Reports 9.  My viewer receives the report name from a database and properly logs into the SQL server, prompts for parameters and displays the report, etc, BUT I am having lots of truoble printing.

I have attempted code with the commondialog control and with smiple crystal printing options, but have been unable to properly print subreports.  I have several reports that contain nodemand subreports.  When the user drills down, everything works find on the display, but when they click print, they get the main report, even though they are viewing the subreport

The catch is, my code needs to be report independent - I need to be able to pass any report with any number of subreports into the viewer, and when the user clicks print, the VB6 code needs to determine what subreport they are viewing, etc and they need to get what they are currently looking at.

HELP Please.  Any suggestions would be appreciated.

Question by:jmitchell13760
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
LVL 100

Expert Comment

ID: 10861534
Do you mean ONDEMAND subreports?

What code are you using to print the reports?

LVL 100

Expert Comment

ID: 10861549
This is for .NET and exporting but it may be useful for printing


Author Comment

ID: 10861750
I have attempted so many solutions that my code at the moment is rather a hack-job.  I believe if I had a fixed report that I could add the name of the subreport in and it may work with the code below (I haven't had time to test it yet) but as is the code doesn't know how to access the subreport.  In my current situation it is an ondemand subreport, but I need the code to be flexible enough to work with any type.  

I believe my basic problem right now I that I need the code to look at the current tab (which I can't figure out how to access) - determine whether it is a subreport or main report, then create a subreport object I can print.  I'm lost though - in way over my head.

I've been compiling together multiple CR examples without luck.  I could email anyone the actual source project (very small and simple) if it would make this easier to understand.

Dim CRAppl As New CRAXDRT.Application
Dim CRRep As CRAXDRT.Report

Dim SubReport As CRAXDRT.Report 'Declare a subreport object
Dim DrillDownReport As CRAXDRT.Report 'Declare a report object to hold the drill down reports
Dim colAreas As CRAXDRT.Areas 'holds the collection of Areas returned by the DrillDown Report object
Dim CurrentArea As CRAXDRT.Area ' Declare a variable to hold the current Area when formatting the report to print group
Dim blnDrill As Boolean 'Boolean variable to hold whether a Drilldown on a Group is occurring
Dim myEvent As crviewer9libctl.CRVEventInfo 'to capture click event
Dim CurrentGroup As String 'hold the value of the Group which was clicked
Dim Groups() As String 'Array to hold all group tabs open
Dim NewGroupArray() As String 'Array to hold temporary group list
Dim CurrentWindow As Integer 'value of Current Active Window
Dim i As Integer 'variable used as a count variable
Dim iWindow As Integer 'holds the index of the current view

Private Sub Form_Load()
  Set CRRep = CRAppl.OpenReport(frm_ReportSelection.Text4.Text)
'The following sets the database location for all tables that are
'used in the report

'Where i is a Long that will be used to increment in a For..Next loop
'depending on the number of tables that exist in the report
Dim i As Long

'From the Report object CrystalReport, we take the current database used
'with the report and assigns it to DbName using the Database property
Set DbName = CRRep.Database

'From the Database object DbName, we take all the tables from the database
'used with the report and assign it to DbTables using the Tables property
Set DbTables = DbName.Tables
Set DbTable = DbTables.Item(1)

frm_ReportSelection.txt_DllName.Text = DbTable.DllName 'gets the DLL name currently in use in the report

frm_ReportSelection.txt_ServerName.Text = DbTable.LogOnServerName

'If the original datasource is used, LogOnServer can be used since it just opens up the connection
'and Crystal uses the original connection

If frm_ReportSelection.Check1.Value = 1 Then
    For i = 1 To DbTables.Count
        'From the DatabaseTables object DbTables, we extract one item (the first table)
        'using the Item property (in CRW, the tables would be listed in order in
        'Database|Set Location)
        Set DbTable = DbTables.Item(i)
        'The SetLogOnInfo method opens up a connection to the database and forces the report
        'to use this connection instead of the one specified in the report. It is then useful
        'if you want to change location of the database for the report. You must set this
        'method for each table. If you want to use the same connection as specified in the report,
        'you can also use the LogOnServer method
        DbTable.SetLogOnInfo frm_ReportSelection.txt_ServerName.Text, , frm_ReportSelection.txt_UserID.Text, frm_ReportSelection.txt_Password.Text
        Next i
End If
Screen.MousePointer = vbHourglass
CRViewer1.ReportSource = CRRep
CRViewer1.DisplayTabs = True
CRViewer1.EnableDrillDown = True
CRViewer1.EnableGroupTree = True
CRViewer1.EnableHelpButton = False
CRViewer1.EnablePopupMenu = False
CRViewer1.EnableSelectExpertButton = True

CRViewer1.EnableExportButton = True

CRViewer1.EnableNavigationControls = True
CRViewer1.EnablePrintButton = True
CRViewer1.EnableSearchControl = True
CRViewer1.EnableSearchExpertButton = True
CRViewer1.EnableZoomControl = True
CRViewer1.EnableStopButton = True


CRRep.EnableParameterPrompting = True
'CRRep.VerifyOnEveryPrint = False

   Screen.MousePointer = vbDefault
End Sub
Private Sub OLDCRViewer1_PrintButtonClicked(UseDefault As Boolean)

    UseDefault = False
    On Error GoTo Cancel
    CommonDialog1.CancelError = True
UseDefault = False

With CommonDialog1
'Set the default minimum page
.Min = 1
'Set the FromPage to be default to the first page:
.FromPage = .Min
'Set the default maximum page to be the number of pages in the report;
.Max = CRRep.PrintingStatus.NumberOfPages
'Set the ToPage to be default to the last page of the report:
.ToPage = .Max
'Invoke the Printer Setup dialog box
'.flags = cdlPDAllPages

'Print the report according the settings for the start page and end page:
CRRep.PrintOut False, , , .FromPage, .ToPage
End With
Exit Sub
    If Err.Number <> cdlCancel Then
        MsgBox Err.Number & " : " & Err.Description, vbExclamation + vbOKOnly, _
            "Printing Error"
    End If

'Create an instance of the Printer Setup dialog box
'Set the handle of the Printer Setup dialog box to the form
'CRRep.PrinterSetup frmCrViewer.hWnd

'The 'Print' dialog box will appear by default
'The 'Print' dialog box needs to be displayed if you want the user
'to set start page and stop page, the number of copies, and collate
End Sub

Private Sub Form_Resize()
   CRViewer1.Top = 0
   CRViewer1.Left = 0
   CRViewer1.Height = ScaleHeight
   CRViewer1.Width = ScaleWidth
End Sub

'*                                                               *
'* This Procedure captures the CloseButtonClicked Event of the   *
'* CRViewer. It will resort the Groups array if the window that  *
'* was closed was a Group. This is necessary as the Tab Window   *
'* index will readjust itself to represent the closed window.    *
'* Thus if a window was previously indexed as 5, once a window   *
'* was closed this window will now be indexed as 4. As we use    *
'* current window index to find the Group from the array we must *
'* also change the indexing of the Group array                   *
'*                                                               *
Private Sub CRViewer1_CloseButtonClicked(UseDefault As Boolean)
    'Determine if the CurrentWindow is the main report, the subreport
    'or a Drilled Down Group. In this case 1 is the Main Report
    '2 is the Subreport, and any number higher than 2 is a Group
    If CurrentWindow > 2 Then
        ReDim NewGroupArray(UBound(Groups) - 1) 'Redim the array with the number of elements in the Group array - 1
        Dim i As Integer
        For i = LBound(Groups) To UBound(Groups) 'cycle through the Group array and get values
            If i < CurrentWindow Then 'if the array item is less than the current group
                NewGroupArray(i) = Groups(i) 'then copy it to the same spot
            ElseIf i > CurrentWindow Then 'if the array item is higher than the current group
                NewGroupArray(i - 1) = Groups(i) 'then copy it to it's current spot - 1 to make up for the closed group
            End If
        Next i
        ReDim Groups(UBound(NewGroupArray)) 'Reset the Groups array
        For i = LBound(NewGroupArray) To UBound(NewGroupArray)
            Groups(i) = NewGroupArray(i) 'copy all of the values from the NewGroupArray to the Groups array
        Next i
    End If
End Sub

'*                                                                                    *
'* This Procedure will capture the Double-click event that is necessary to Drill-Down *
'* on a group. With the Event captured it is able isolate the EventInfo Object's Text *
'* Property. This will hold the name of the Group which was clicked. It stores this   *
'* Group name in a variable to be later assigned to the Group array. This event will  *
'* be fired if the user double-clicks on the 2nd Tab (Subreport).                     *
'*                                                                                    *

Private Sub CRViewer1_DblClicked(ByVal x As Long, ByVal y As Long, EventInfo As Variant, UseDefault As Boolean)
    'double click on a field in the viewer and retrieve the current value cilcked upon
     If CRViewer1.ActiveViewIndex = 2 Then 'check to see if current window is subreport
        Set myEvent = EventInfo
        CurrentGroup = myEvent.Text
     End If
End Sub
'*                                                                       *
'* The DrillOnGroup event occurs when drilling down (double-clicking) on *
'* a group field viewer window. If this event is fired it sets a Boolean *
'* variable to True. This variable will be used in other procedures to   *
'* determine which action is to be carried out                           *
'*                                                                       *

'Private Sub CRViewer1_DrillOnGroup(GroupNameList As Variant, ByVal DrillType As crviewer9libctl.CRVEventInfo, UseDefault As Boolean)
'    blnDrill = True
'End Sub
'*                                                                       *
'* This procedure will overwrite the default action of the Print Button  *
'* if it is clicked. It essentially determines the CurrentWindow using   *
'* ActiveViewIndex Property of the CRViewer. If it is determined that the*
'* Current Window is a Group, that is an ActiveWindowIndex greater than 2*
'* then it will use the ActiveViewIndex as the index of the Group() array*
'* to retrieve the value of the GroupName trying to be printed. It will  *
'* then assign this value to the RecordSelectionFormula of our secondary *
'* report object(DrillDownReport). Through some formatting of this report*
'* we are able to suppress all the fields except the Group Header and the*
'* Details section so as to resemble the output of a Drill-Down.         *
'* If the ActiveViewIndex is 2 then it will print the report object      *
'* containing the subreport information (SubReport).                     *
'* If the ActiveViewIndex is 1 then it will print the Main Report object *
'*                                                                       *

Private Sub CRViewer1_PrintButtonClicked(UseDefault As Boolean)
    UseDefault = False
    'On Error GoTo Cancel
    CommonDialog1.CancelError = True
UseDefault = False

'**************New Ciode
    UseDefault = False 'override Default actions
    If CRViewer1.ActiveViewIndex > 2 Then 'check if current window is a group
        iWindow = CRViewer1.ActiveViewIndex
        Set DrillDownReport = Report2.OpenSubreport("Customer") 'Open the DrillDownReport using the Report2 object
        DrillDownReport.RecordSelectionFormula = "{ado.Country} = '" & Groups(iWindow) & "'" 'change selection formula to return only current group
         For i = 1 To DrillDownReport.Areas.Count 'use the for loop to determine what kind of area is on the report
           If DrillDownReport.Areas.Item(i).Kind = crDetail Then 'If Area is the Detail section then
               DrillDownReport.Areas.Item(i).HideForDrillDown = False 'turn off the HideForDrillDown
           ElseIf DrillDownReport.Areas(i).Kind <> crGroupHeader Then 'Suppress all other Areas other than Group Header
               DrillDownReport.Areas(i).Suppress = True
           End If
         Next i
        MsgBox "Printing the Drill-down report for " & Groups(iWindow), vbOKOnly, "Printing Drill-Down"
        DrillDownReport.PrintOut True 'Print out the Drill Down Report, prompting for user
        Set DrillDownReport = Nothing 'clean up Drill down report object for next time print is clicked
    ElseIf CRViewer1.ActiveViewIndex = 2 Then 'if Current window is Subreport
        MsgBox "Printing the Subreport", vbOKOnly, "Printing Subreport"
With CommonDialog1
'Set the default minimum page
.Min = 1
'Set the FromPage to be default to the first page:
.FromPage = .Min
'Set the default maximum page to be the number of pages in the report;
.Max = SubReport.PrintingStatus.NumberOfPages
'Set the ToPage to be default to the last page of the report:
.ToPage = .Max
'Invoke the Printer Setup dialog box
'.flags = cdlPDAllPages

SubReport.PrintOut False, , , .FromPage, .ToPage
End With
        'SubReport.PrintOut True
        MsgBox "Printing Main Report", vbOKOnly, "Printing Main Report"
With CommonDialog1
'Set the default minimum page
.Min = 1
'Set the FromPage to be default to the first page:
.FromPage = .Min
'Set the default maximum page to be the number of pages in the report;
.Max = Report.PrintingStatus.NumberOfPages
'Set the ToPage to be default to the last page of the report:
.ToPage = .Max
'Invoke the Printer Setup dialog box
'.flags = cdlPDAllPages

Report.PrintOut False, , , .FromPage, .ToPage
End With
End If
End Sub

'*                                                                         *
'* The ViewChanging event occurs when there has been a request for the     *
'* view in the Report Viewer to change. Views refer to the main Preview    *
'* Tab and drill down tabs that appear in the Report Viewer as the user    *
'* interacts with the report. If the blnDrill variable has been set to     *
'* True then get the NewViewIndex and assign the Group name to the Groups  *
'* array with the index of the NewViewIndex. It then turns off the blnDrill*
'*                                                                         *
Private Sub CRViewer1_ViewChanging(ByVal oldViewIndex As Long, ByVal newViewIndex As Long)
    'set the CurrentWindow every time tabs are changed. This is used to keep track
    'of which window the user is trying to close
    CurrentWindow = newViewIndex
    If blnDrill = True Then 'if Tab is changed due to a Drill down then
        ReDim Preserve Groups(UBound(Groups) + 1) 'add Group name to Groups array
        Groups(newViewIndex) = CurrentGroup
        blnDrill = False
    End If
End Sub

Accepted Solution

modulo earned 0 total points
ID: 11871823
PAQed, with points refunded (250)

Community Support Moderator

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Crystal Reports: 5 Tests for Top Performance It is complete, your masterpiece report.  Not only does it meet your customer’s expectations, it blows them out the water, all they want is beautifully summarised and displayed in a myriad of ways. …
There have always been a lot of questions related to when Crystal Reports evaluates report components (such as formulas, summaries, cross-tabs, charts, to name a few examples). Crystal Reports uses a two-pass reporting process to provide greater …
I've attached the XLSM Excel spreadsheet I used in the video and also text files containing the macros used below.…
Finding and deleting duplicate (picture) files can be a time consuming task. My wife and I, our three kids and their families all share one dilemma: Managing our pictures. Between desktops, laptops, phones, tablets, and cameras; over the last decade…

739 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