Elk programma heeft output. Vaak wordt het scherm gebruikt om informatie weer te geven, maar veelal ook een printer. Met VO2.6 wordt standaard ReportPro 2 meegeleverd, een prima rapport generator van DataPro Inc. Vaak zal ReportPro voldoende mogelijkheden bieden om uw rapporten te kunnen genereren, maar soms zijn er meer complexe rapporten noodzakelijk of willen uw klanten zelf rapporten ontwerpen met behulp van Crystal Reports.
Ik zelf heb indertijd gekozen voor Crystal Reports omdat ik de designer beter vind en Crystal Reports meer mogelijkheden biedt, vooral op het gebied van het exporteren van de rapporten. Het is een hele klus geweest om Crystal Reports goed te integreren in ons VO framework, maar we zijn zeer tevreden met het uiteindelijke resultaat.
In de komende maanden zal ik aan de hand van de demo applicatie MC_Crystal laten zien hoe je Crystal Reports in een VO applicatie kunt integreren. Na elk artikel zal de MC_Crystal demo applicatie verder uitgebreid zijn met de functies die in dat artikel zijn beschreven.
Op de website van de SDGN en op www.marti.nl/cavo vind u altijd de laatste versie van de MC_Crystal applicatie. U kunt deze applicatie inclusief bijbehorende AEF downloaden en uitpakken in de folder C:\MC_Crystal. Vervolgens kan de MC_Crystal.Aef geïmporteerd worden en kunt u de demo applicatie direct bekijken.
Diverse manieren om Crystal Reports te benaderen.
Er zijn diverse manieren om Crystal Reports aan te roepen. Crystal Reports versie 8.5 en versie 9 hebben naast de vertrouwde manieren om met externe applicatie te praten, ook een andere benadering via de Crystal Reports RDC. Deze methode wordt niet besproken in dit artikel.
De Crystal Reports ActiveX component
Crystal Reports wordt als OCX geregistreerd wanneer je het Crystal Reports op een PC installeert. Ik zelf ben ik niet zo gecharmeerd van ActiveX componenten omdat je deze eerst moet registreren op de PC waar je de componenten wilt gaan gebruiken. De praktijk leert dat hier wel eens problemen ontstaan bij klanten, dus hebben wij de andere, meer universele methode gebruikt.
De Crystal DLL prototypes
De meest handige en flexibele manier is het benaderen van Crystal Reports direct via de Crystal Reports API (Het direct benaderen van de Crystal Reports DLL’s). Het voordeel is dat we slechts de benodigde DLL’s in de applicatie folder hoeven te kopiëren om Crystal Reports te kunnen laten functioneren. Het bestand MC_Crystal.Zip (www.marti.nl/cavo/samples/mc_crystal.zip) bevat al de benodigde Crystal Reports DLL’s, zodat u zelf geen Crystal Reports geïnstalleerd hoeft te hebben om de MC_Crystal demo applicatie te kunnen compileren en bekijken.
Om de API te kunnen gebruiken, dienen er prototypes te zijn voor de verschillende functies en structuren binnen de Crystal Reports DLL’s. Ralf Krzyzaniak (www.ralfk.de) heeft veel werk gestoken in het maken van een Crystal Reports Class. De Crystal Reports prototypes en structuren komen dan ook grotendeels uit zijn Crystal Reports Library, alhoewel ze met enige API kennis gemakkelijk zelf zijn te genereren. Je kunt meer informatie vinden over de beschikbare functies in het Developer Helpfile CrystalDevHelp.chm onder het kopje Print Engine Functions. Dit helpfile bevat voorbeelden voor o.a. C, Delphi en dBase, dus deze kunnen gemakkelijk vertaald worden naar VO. Dit helpbestand wordt niet standaard geïnstalleerd, maar staat wel op de Cd-rom van Crystal Reports.
Een DLL prototype is een beschrijving waar een bepaalde functie of methode in een bepaalde DLL gevonden kan worden. In dit geval kan de functie PEOpenEngine gevonden worden in het bestand CRPE32.DLL. De code in VO is als volgt:
_DLL FUNC PEOpenEngine () AS SHORTINT PASCAL:CRPE32.PEOpenEngine
De meeste prototypes van de Crystal Reports DLL’s zijn in de MC_Crystal applicatie opgenomen en staan in de module _CrystalPrototypes.
De applicatie MC_Crystal
Het doel van dit artikel is om in stappen tot een applicatie te komen waarin Crystal Reports volledig wordt gebruikt in een VO applicatie. Hierbij wil ik ingaan op zaken zoals het exporteren van rapporten, het gebruik van subrapporten en het aansturen van rapporten via parameters die vanuit een VO applicatie aan Crystal Reports worden doorgegeven.
Deze eerste versie van MC_Crystal zal voornamelijk gaan over de applicatie zelf en het afdrukken van een simpel rapport vanuit VO. Let wel even op dat in deze versie er van uitgegaan wordt dat de bestanden in de folder C:\MC_Crystal staan. Mocht je de bestanden op een andere locatie hebben uitgepakt, dan zal deze versie van MC_Crystal niet goed functioneren. In de volgende deel zal hier meer aandacht aan besteed worden.
De start
Ik heb een standaard MDI applicatie gemaakt vanuit de ‘New Application Wizard’. Vervolgens de Crystal Reports DLL prototypes er in gekopieerd.
DBServer [DBName]
Om een rapport te kunnen maken, heb je data nodig. Hiervoor heb ik een simpele DBServer gemaakt vanuit de DB Editor. Deze tabel heet DBName en bevat de velden [NAAM"C"40] en [NR"C"10].
Crystal Report [Name1.Rpt]
Vervolgens heb ik in de Crystal Report Designer een rapport gemaakt met de naam [Name1.Rpt] waarin deze twee velden worden weergegeven.
De methodes van MC_Crystal
Na de standaard MDI applicatie en het bijbehorende menu uitgekleed te hebben, heb ik twee nieuwe menu-items aangemaakt die de methodes OpenDBName en PrintReportDBName1 van het StandardShellWindow opstarten. De code van deze twee methodes staat in de module _ShellMethods van de MC_Crystal applicatie.
OpenDBName
De methode OpenDBName doet niets anders dan de DBServer DBName openen zodat hier gegevens toegevoegd of gewijzigd kunnen worden.
METHOD OpenDBName() CLASS StandardShellWindow
LOCAL oTextBox AS TextBox
LOCAL oWindow AS StdDataWindow
LOCAL sName AS STRING
// Set the name of the table
sName:="Name.Dbf"
IF File(sName)
oWindow:=StdDataWindow{SELF,sName,FALSE}
oWindow:ViewAs(#FormView)
oWindow:Show()
ELSE
oTextBox:=TextBox{SELF, "File Open Error","Cannot open "+sName+"!"}
oTextBox:Type:=BUTTONOKAY
oTextBox:Show()
END
RETURN NIL

PrintReportDBName1
De methode PrintReportDBName1 laat een Crystal Report zien in het Crystal Preview Window en drukt deze vervolgens af op de printer. Om een rapport in Crystal Reports af te kunnen drukken dient het volgende te gebeuren:
- De Crystal Engine starten
- Het aanmaken van een print opdracht (PrintJob)
- De instellingen binnen de print opdracht aangeven
- Aangeven waar het rapport afgedrukt moet worden
- De printopdracht starten
- De printopdracht beeindigen
- De Crystal Engine stoppen.
Voor al deze stappen heeft Crystal Reports functies en routines. Je moet even in de gaten houden dat de functies kunnen mislukken. Je moet dus wel eventuele fouten afhandelen en hier netjes mee omgaan.
De volledige methode om een rapport af te drukken ziet u hieronder. Ik heb de gewoonte om veel commentaar in mijn code te zetten zodat het duidelijk zou moeten zijn wat er gebeurd.
METHOD PrintReportDBName1() CLASS StandardShellWindow
LOCAL oTextBox AS TextBox
LOCAL sReport AS STRING
LOCAL nJob AS INT
LOCAL nFailed AS DWORD
LOCAL hPreviewWindowAS PTR
// Set the name of the table
sReport:="C:\MC_Crystal\Name1.Rpt"
// Open the engine and print the report
DO CASE
CASE !File(sReport)
// The report does not exist
nFailed:=1
CASE !PEOpenEngine()
// The engine is not open!
nFailed:=2
CASE (nJob:=PEOpenPrintJob(String2Psz(sReport)))==0
// The report can not be opened
nFailed:=3
CASE !PEOutputToWindow(nJob,String2Psz("Name Report 1"),;
CW_USEDEFAULT,;
CW_USEDEFAULT,;
CW_USEDEFAULT,;
CW_USEDEFAULT,;
WS_VISIBLE+WS_CAPTION+WS_BORDER+WS_SYSMENU+;
WS_THICKFRAME+WS_MINIMIZEBOX+WS_MAXIMIZEBOX,0)
// Setting the output to window failed!
nFailed:=4
CASE !PEStartPrintJob(nJob,TRUE)
// The report can not be started
nFailed:=5
CASE !PEPrintWindow(nJob,TRUE)
// The Report can not be printed on the printer!
nFailed:=6
END
// Did the report start?
IF nFailed<>0
// Close the stuff
PEClosePrintJob(nJob)
PECloseEngine()
// The report failed
oTextBox:=TextBox{SELF, "Report NOT started!",;
"There is a problem with "+sReport+" --> "+AsString(nFailed)+"!"}
oTextBox:Type:=BUTTONOKAY
oTextBox:Show()
ELSE
// Repeat this loop until the Preview window is closed!
hPreviewWindow:=GetActiveWindow()
DO WHILE GetActiveWindow()==hPreviewWindow
// repeat until the reportwindow is closed!
GetAppObject():EXEC(EXECWHILEEVENT)
END
// Close the stuff
PEClosePrintJob(nJob)
PECloseEngine()
// The report is printed
oTextBox:=TextBox{SELF, "Report finished!","Report "+sReport+"!"}
oTextBox:Type:=BUTTONOKAY
oTextBox:Show()
END
RETURN NIL
Hieronder vindt u de functies die vanuit VO worden aangeroepen. De namen spreken eigenlijk voor zich.
PEOpenEngine() Returns ResultAS LOGIC
PEOpenPrintJob( sReportFilePath AS PSZ) Returns JobNumber AS SHORTINT
PEOutputToWindow( nPrintJob AS SHORTINT,
cTitle AS PSZ,
nLeft AS SHORTINT,
nTop AS SHORTINT,
nWidth AS SHORTINT,
nHeight AS SHORTINT,
nStyle AS LONG,
hWnd AS PTR) Returns ResultAS LOGIC
PEStartPrintJob( nPrintJob AS SHORTINT,
lWaitUntilDone AS LOGIC) Returns ResultAS LOGIC
PEPrintWindow( nPrintJob AS SHORTINT,
lWait AS LOGIC) Returns ResultAS LOGIC
De output in het standaard Crystal Reports Preview venster ziet er dan als volgt uit:

Als het preview venster wordt opgestart, wacht ik even met het sluiten van de opdracht en de Crystal Engine totdat het voorbeeld venster is afgesloten. Ik doe dit door te controleren of het actieve venster het voorbeeld venster van Crystal Reports is.
// Repeat this loop until the Preview windows is closed!
hPreviewWindow:=GetActiveWindow()
DO WHILE GetActiveWindow()==hPreviewWindow
// repeat until the reportwindow is closed!
GetAppObject():EXEC(EXECWHILEEVENT)
END
Wanneer er geen afdruk op de printer gemaakt moet worden dan dient het volgende gedeelte uit de code verwijderd te worden:
CASE !PEPrintWindow(nJob,TRUE)
// The Report can not be printed on the printer!
nFailed:=6
Met behulp van dit artikeltje moet het voor een iedere VO programmeur mogelijk zijn snel aan de slag te gaan met Crystal Reports.
De volgende keer wordt er dieper ingegaan op de locatie van bestanden en het rapport. Verder zal ik wat dieper ingaan op het gebruik en aansturen van subrapporten in Crystal Reports.
BronbestandenDownload de brondbestanden :
Crystal_Reports_en_Visual_Objects_deel_1.zip (2,5 mb).