Dynamic Direct to Printer from Business Objects Enterprise XI ( Crystal Enterprise 11) using ASP.net/VB.Net
By Jon O. Roberts
This tutorial is design to demonstrate a method for allowing a user to request a report to sent to a print from Business Objects Enterprise XI (Crystal Enterprise 11 referred to as CE in this document). There are 3 pieces to this example:
- WebForm1
- Utilities
- PrinterDataTransfer
PrinterDataTranser
We Will start with the PrinterDataTransfer. This is a basic structure definition it is listed below:
'<summary>
' The PrinterDataTransfer structure functions as a data transfer object
' for passing multiple values related to printer settings as a single
' object from an event method in the ScheduleToDestination code-
' behind class to the Utilities method.
'< /summary>
Public Structure PrinterDataTransfer
Public PrinterName As String
Public Copies As Integer
Public FromPage As Integer
Public ToPage As Integer
End Structure
The PrintDataTransfer is used to hold then pass key information related to the printing of the report.
The Printer name is the print server \ printer name pathing (i.e. "\\myprintserver\myprinter"). Copies represents the number of copies of the report to print. From page is the page of the report to start printing from. To page is the last page of the report to print.
When you want to print a complete report of un determined size I would recommended setting FromPage to 1 and ToPage to 10000. This will insure that to complete report is captured to the printer.
Utilities
The Utilies.vb file is a helper class library. you can add this code by creating a new class file in vb.net and passing the code. The various comments in the code explain what each piece is used to do.
Imports System.Collections
Imports CrystalDecisions.Enterprise
Imports CrystalDecisions.Enterprise.Desktop
Imports CrystalDecisions.Enterprise.Viewing
Imports CrystalDecisions.ReportAppServer.Controllers
Imports CrystalDecisions.Enterprise.Dest
' The Utilities class contains the business logic
' for this tutorial. The code-behind classes manage
' aspx page issues and data binding. All business logic
' is retrieved from this Utilities class by means of
' method calls. All methods are public static as there
' is no need for this class to be instantiated.
Public Class Utilities
' In this method, a jagged array is created containing
' multiple inner arrays of two columns each. The array
' is then passed through a for loop to assign the inner
' array values to the key/value pairs of a sorted List
' instance upcast to the generic IDictionary interface. 'generic key/value collection interface, IDictionary
Public Shared Function GetAuthenticationTypes() As IDictionary
Dim mySortedList As New SortedList()
Dim outerJaggedArray As String()() = { New String() {"secEnterprise", "Enterprise"}, New String() {"secWindowsNT", "Windows NT"} }
Dim innerArray As String()
For Each innerArray In outerJaggedArray
mySortedList.Add(innerArray(0), innerArray(1))
Next
Return mySortedList
End Function
'Used to schedule report to the printer
Public Shared Sub ScheduleToPrinter(ByVal myInfoStore As InfoStore, ByVal reportID As String, ByVal myPrinterDataTransfer As PrinterDataTransfer)
' Gets the report.
Dim query As String = "Select SI_ID, SI_NAME, SI_PROCESSINFO, SI_SCHEDULEINFO " & "From CI_INFOOBJECTS Where SI_ID=" & reportID
Dim myInfoObjects As InfoObjects = myInfoStore.Query(query)
Dim myInfoObject As InfoObject = myInfoObjects(1)
Dim myReport As Report = CType(myInfoObject, Report)
'Creates an interface to the scheduling options for the report.
Dim mySchedulingInfo As SchedulingInfo = myReport.SchedulingInfo
' Runs the report once.
mySchedulingInfo.Type = CeScheduleType.ceScheduleTypeOnce
' Runs it right now.
mySchedulingInfo.RightNow = True
' Gets the printer options from the report plug in interface and set
' the printer options. These can be found under the Report object.
Dim myReportPrinterOptions As ReportPrinterOptions = myReport.ReportPrinterOptions
myReportPrinterOptions.Enabled = True
'The PrinterDataTransfer Structure is implemented here
myReportPrinterOptions.Copies = myPrinterDataTransfer.Copies
myReportPrinterOptions.FromPage = myPrinterDataTransfer.FromPage
myReportPrinterOptions.ToPage = myPrinterDataTransfer.ToPage
myReportPrinterOptions.PrinterName = myPrinterDataTransfer.PrinterName
'Tells the CMS to schedule the report.
myInfoStore.Schedule(myInfoObjects)
End Sub
' In this method, a query is passed to the InfoStore instance to retrieve
' the ID for a given folder identified by the folder Name parameter.
' The retrieved value is placed in an instance of the InfoObjects indexed
' class. If the indexed class has more than 0 rows, the first row of the
' (1-based) indexed class is then retrieved into an InfoObject instance,
' and the ID property of the InfoObject instance is assigned to a folderID
' Integer variable. This variable is then returned out of the method.
' If the indexed class has 0 rows, an Exception is thrown instead.
' <param name="infoStore">Manages access to the CMS repository.</param>
' <param name="folderName">The name of the folder.</param>
' <returns>The folder's ID as an Integer.</returns>
Public Shared Function GetFolderID(ByVal myInfoStore As InfoStore, ByVal folderName As String) As Integer
Dim query As String = "Select SI_ID From CI_INFOOBJECTS "Where SI_KIND='Folder' "And SI_NAME = '" & folderName & "'"
Dim myInfoObjects As InfoObjects = myInfoStore.Query(query)
If myInfoObjects.Count > 0 Then
Dim myInfoObject As InfoObject = myInfoObjects(1)
Dim folderID As Integer = myInfoObject.ID
Return folderID
Else
'insert your error handling code here
End If
End Function
' A new InfoObjects indexed class is created by calling the NewInfoObjectCollection
' method of the InfoStore instance. A new PluginManager instance is returned
' by the PluginManager Property of InfoStore. The GetPluginInfo method is
' called, passing in a string name of the InfoObject subclass type. This
' returns a PluginInfo instance that is specific to that subclass type. That
' PluginInfo instance is then passed as a parameter into the Add method of
' InfoObjects, which returns the InfoObject instance matching that particular
' subclass type. Finally, that instance is downcast to the subclass type: in
' this case, the Report type. Once this is done, several properties of Report
' are set. The new Report instance is now saved back to the CMS server by
' calling the Commit method of the InfoStore instance and passing in the
' InfoObjects indexed class which contains this Report instance.
' <param name="infoStore">Manages access to the CMS repository.</param>
' <param name="folderID">The ID of the folder where the report is to be added.</param>
' <param name="reportName">The path and name of the report to be added.</param>
Public Shared Sub AddReport(ByVal myInfoStore As InfoStore, ByVal folderID As Integer, ByVal reportName As String)
Dim myInfoObjects As InfoObjects = myInfoStore.NewInfoObjectCollection()
Dim myPluginManager As PluginManager = myInfoStore.PluginManager
Dim myPluginInfo As PluginInfo = myPluginManager.GetPluginInfo("CrystalEnterprise.Report")
Dim myInfoObject As InfoObject = myInfoObjects.Add(myPluginInfo)
Dim myReport As Report = CType(myInfoObject, Report)
myReport.Files.Add(reportName)
myReport.Properties.Add("SI_PARENTID", folderID)
myReport.EnableThumbnail = True
myInfoStore.Commit(myInfoObjects)
End Sub
End Class
WebForm1
Imports CrystalDecisions.Enterprise
Imports BusinessObjects.Enterprise.Dest
Imports CrystalDecisions.Enterprise.Desktop
Public Class WebForm1
Inherits System.Web.UI.Page
#Region " Web Form Designer Generated Code "
'This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container
Me.Identity1 = New CrystalDecisions.Enterprise.WebControls.Identity(Me.components, Me, "Identity1")
CType(Me.Identity1, System.ComponentModel.ISupportInitialize).BeginInit()
'
'Identity1
'
Me.Identity1.System = "mymachine" 'machine where CE resides
Me.Identity1.UserName = "administrator" 'CE administrator name
Me.Identity1.VisibleAuthentications.Add("Enterprise")
CType(Me.Identity1, System.ComponentModel.ISupportInitialize).EndInit()
End Sub
Protected WithEvents Identity1 As CrystalDecisions.Enterprise.WebControls.Identity
Private components As System.ComponentModel.IContainer
'NOTE: The following placeholder declaration is required by the Web Form Designer.
'Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object
Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
'CODEGEN: This method call is required by the Web Form Designer
'Do not modify it using the code editor.
InitializeComponent()
End Sub
#End Region
Dim strCEObj As String
Dim rptobj As New CrystalDecisions.CrystalReports.Engine.ReportDocument 'object to hold report from ce
Dim myIObjs As CrystalDecisions.Enterprise.InfoObjects
Dim myIObj As CrystalDecisions.Enterprise.InfoObject
Dim myerror As String
Dim strGuid As String
'Page load initialize objects
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Put user code to initialize the page here
Dim myistore As InfoStore 'derived from CrystalDecisions.Enterprise
Dim myobjs As InfoObjects 'derived from CrystalDecisions.Enterprise
Identity1.Password = "Password123" ' Administrator password for CE System
Identity1.Logon()
myistore = Identity1.InfoStore
strCEObj = "MyReport" ' Name of report in CE
GetReport(strCEObj) 'Get the report object
DirectPrint() 'Send Report to printer
System.Threading.Thread.Sleep(60000) 'Pause for 60 second to allow report to finish running
System.IO.File.Delete("c:\cetemptrpt\" & strGuid & ".rpt") 'Delete temp file
myobjs = myistore.Query("Select SI_FILES from CI_INFOOBJECTS where( SI_Name = '" & strGuid & "' AND SI_PROGID = 'CrystalEnterprise.Report' and si_instance = 0 ) ") '
myobjs.Item(1).DeleteNow() ' delete ce temp object
'myistore.Commit(myobjs) 'update ce database
End Sub
' publishes temp report object to ce and schedules to run and send to printer
Private Sub DirectPrint()
Dim Folderid As Integer
strGuid = Guid.NewGuid.ToString 'Get guid value to use as name for temp objects
rptobj.SaveAs("c:\cetemptrpt\" & strGuid & ".rpt") 'save temp report object to hardrive
Folderid = Utilities.GetFolderID(Identity1.InfoStore, "tempprint") ' get the id of tempfolder in ce using the utilities class
Utilities.AddReport(Identity1.InfoStore, Folderid, "c:\cetemptrpt\" & strGuid & ".rpt") 'publish temp report to temp ce folder
scheduleToPrinter() 'schedule temp report object to printer
End Sub
'Used to schedule temp report object published to ce to printer
Private Sub scheduleToPrinter()
Dim myrid As String
Dim robjs As CrystalDecisions.Enterprise.InfoObjects
Dim myPrinterDataTransfer As PrinterDataTransfer
myPrinterDataTransfer.Copies = Convert.ToInt32("1")
myPrinterDataTransfer.FromPage = Convert.ToInt32("1")
myPrinterDataTransfer.ToPage = Convert.ToInt32("100")
myPrinterDataTransfer.PrinterName = "\\myserver\myprinter"
robjs = Identity1.InfoStore.Query("Select * from CI_INFOOBJECTS where( SI_Name = '" & strGuid & "' AND SI_PROGID = 'CrystalEnterprise.Report' and si_instance = 0 )")
myrid = robjs.Item(1).ID.ToString
Utilities.ScheduleToPrinter(Identity1.InfoStore, myrid, myPrinterDataTransfer) 'Schedule the report to printer
End Sub
'used to retrieve report object from ce server
Private Sub GetReport(ByVal reportname As String)
Dim myQuery As String
Try
myQuery = "SELECT * FROM CI_INFOOBJECTS WHERE ( SI_NAME = '" & reportname & "' AND SI_PROGID = 'CrystalEnterprise.Report' and si_instance = 0 )"
myIObjs = Identity1.InfoStore.Query(myQuery)
myIObj = myIObjs.Item(1)
rptobj.Load(myIObj, Identity1.EnterpriseSession)
Catch ex As Exception
myerror = ex.Message & " " & ex.Source & " " & ex.StackTrace
End Try
End Sub
End Class
The above sample code use some basic will work fine with a report created with an xml data source. This example does not demonstrate the setting up of parameters or the defining of database login when publishing the temp report object.
If you have any questions please feel to drop me a line. or make a comment in the forums.
Until later this is your common mans developer signing off,
Jon Roberts
浙公网安备 33010602011771号