Samples from MORPHX IT -- steenandreasen.com
MORPHX IT Een inleiding tot Axapta X++ en de MorphX Development Suite Copyright © 2007 Steen Andreasen, www.steenandreasen.com
Samples from MORPHX IT -- steenandreasen.com
Editor: Steen Andreasen Layout: Steen Andreasen Omslag : Poul Cappelen en Ulla Bjulver Fotograaf: Ulla Bjulver Vertaald door : Cornelis Linda, Cuppens Gert, Vangheluwe Jeroen Denemarken 2007 ISBN: 87-991161-5-4 1e uitgave Alle rechten voorbehouden. De auteur heeft herbruikbare code in deze publicatie geschreven met het doel om door de lezers herbruikt te worden. U krijgt beperkte toestemming om de code in deze publicatie te herbruiken op voorwaarde dat de auteur wordt vermeld in de applicatie die deze code herbruikt en op voorwaarde dat de code zelf niet wordt verdeeld, online geplaatst, verkocht of commercieel gebruikt als een stand-alone product. Behalve deze specifieke uitzondering betreffende te herbruiken code, kan geen deel van deze publicatie op welke manier dan ook worden gebruikt of gereproduceerd zonder de voorafgaande schriftelijke toestemming van de auteursrechthouder behalve in het geval van korte citaten opgenomen in artikelen of overzichten. Elk ander gebruik zonder geschreven toestemming is verboden volgens de Deense auteursrechtwet. Als u enige onnauwkeurigheid ziet, gelieve dit te melden aan de auteur op het volgende e-mailadres:
[email protected]
Handelsmerken Alle begrippen die in dit boek worden vermeld en die gekend zijn als handelsmerk, zijn met hoofdletters geschreven. steenandreasen.com kan de nauwkeurigheid van deze informatie niet bevestigen. Het gebruik van een term in dit boek mag niet beschouwd worden als een uitspraak over de geldigheid van om het even welk handelsmerk.
Waarschuwing en afwijzing van verantwoordelijkheid U mag nooit om het even welk voorbeeld in dit boek in een productieomgeving uitproberen. De informatie in dit boek wordt verstrekt zonder meer. De auteur of steenandreasen.com kan niet verantwoordelijk worden gesteld voor om het even welk verlies of schade dat het gevolg geweest zou zijn van de informatie die dit boek bevat.
Samples from MORPHX IT -- steenandreasen.com
“met dank aan mijn lieve vrouw Ulla, en mijn zoon Oliver, die met me opstonden en me steunden bij het schrijven van dit boek. ” S. A.
Samples from MORPHX IT -- steenandreasen.com
Dankbetuiging
Ik dank iedereen die direct of indirect heeft bijgedragen tot de inhoud van dit boek door inspirerende commentaar en suggesties.
Een speciale bedanking is voor Lars Holm voor zijn bijdrage aan de Appendix Properties. Poul Cappelen en Ulla Bjulver www.photo-art.dk voor het ontwerp van de boekomslag. Jens Thrane, Christian Beck, Erik Pedersen, Lars Kjærsgaard, Jim Long, Hanne Paarup, Eric Fisher www.unitederp.com, Craig Brown www.edenbrook.co.uk, Daryl Spires www.avionsystems.co.uk, die het manuscript nagelezen, gecorrigeerd, geëditeerd hebben en , nog belangrijker, die me hebben aangemoedigd om vol te houden.
Samples from MORPHX IT -- steenandreasen.com
Aanbeveling van het boek "Steen Andreasen is een uitstekend Axapta Programmeur en Technical Manager – en hij is een geduldig leraar. In dit boek heeft Steen Andreasen zeer hard gewerkt om u, de lezer, mee te nemen op een aangename reis door de wereld van de Axapta ontwikkeling. Ik beveel dit boek van harte aan als verplichte lectuur voor iedere ontwikkelaar, ervaren of beginner, die een carrière wil opbouwen in de Axapta Programmatie. Hartelijk bedankt, Steen Andreasen, voor al je inspanningen en gulheid om een zo goed gestuructureerde waardevolle informatie open te stellen voor de gemeenschap. "
Met vriendelijke groeten,
Harish Mohanbabu Microsoft Dynamics Ax - MVP http://www.harishm.com/
MORPHX IT
Сontent VOORWOORD ................................................................................................ 7 INLEIDING ....................................................................................................... 8
Samples from MORPHX IT -- steenandreasen.com
Waarom dit boek belangrijk is ..........................................................................9 Structuur van het boek .....................................................................................9
1
RAPPORTEN ...................................................................................... 10 1.1
Report Wizard .............................................................................................. 10
1.2
Het maken van rapporten ........................................................................... 11
1.3
Report Query ................................................................................................ 14
1.4
Sjablonen...................................................................................................... 17 Rapportsjabloon ............................................................................................ 17 Sectiesjabloon ............................................................................................... 21
1.5
Ontwerpen .................................................................................................... 21 Het ontwerp maken ....................................................................................... 22 Auto-ontwerp ................................................................................................. 24 gegenereerd ontwerp .................................................................................... 28 Controls in het ontwerp .................................................................................. 29
1.6
Methodes in een Rapport............................................................................ 31 Report Runbase Raamwerk .......................................................................... 36 Dynamische Rapporten ................................................................................. 41 Gemeenschappelijke rapportmethoden ........................................................ 44
1.7
Speciale Rapporten ..................................................................................... 49 Een rapport uitvoeren vanuit X++ .................................................................. 49 Gebruik van tijdelijke tabellen ........................................................................ 51 Gekleurde rijen .............................................................................................. 53 Afdrukken met Microsoft Word ...................................................................... 55
1.8
Samenvatting ............................................................................................... 59
© 2007 Steen Andreasen
6 of 60
MORPHX IT
Voorwoord
Voorwoord
Samples from MORPHX IT -- steenandreasen.com
Succesvol programmeren is voornamelijk gebaseerd op het begrijpen van de gebruikersbehoeften en deze behoeften vertalen in een technisch werkende oplossing, een systeem. Het is bovendien essentieel dat de programmeur duidelijk begrijpt hoe dit systeem is aangepast zodat de wijzigingen gebruiksvriendelijk zijn en eenvoudig te behandelen bij een upgrade. Dit boek geeft een inleiding in de ontwikkelingsfase van Axapta. Het boek is niet alleen een oefening in de functionaliteit van Axapta maar omdat het gebaseerd is op mijn meer dan acht jaren van ervaring met Axapta, is het evenzeer een praktisch boek met zowel een hoop gecodeerde voorbeelden van productontwikkeling als klantgerichte oplossingen. De publicatie van dit boek staat al een hele tijd op mijn verlanglijstje. Tijdens mijn jarenlange werken met Axapta heb ik geleerd dat een praktisch en instructief boek voor Axapta niet beschikbaar is. Dit boek ,MORPHX IT, toont mijn professionele interesse in ERP systemen en Axapta in het bijzonder. Mijn reis als auteur door het publicatieproces was boeiend en het was aanmoedigend voor me om mail te krijgen van honderden mensen van de hele wereld. Ik kreeg commentaren en suggesties nadat ik een hoofdstuk van het boek voor download op het web had gezet. Dit verzekerde me dat er een sterke interesse en behoefte was aan het boek. Hopelijk geeft dit boek op zijn beurt inspiratie aan talloze mensen, de beginnelingen die hun eerste stappen zetten in Axapta, de lesgevers aan hogescholen en universiteiten waar het onderwijs van ERP systemen opgang maakt, en de meer ervaren Axapta professionelen in de bedrijfswereld. Veel programmeurs hebben ieder voor zich beetje bij beetje alle informatie moeten verzamelen, die ik in dit boek heb gepubliceerd. Het is mijn bedoeling om het werken in en met Axapta eenvoudiger te maken en te inspireren tot een voortdurende ontwikkeling.
Steen Andreasen
© 2007 Steen Andreasen
7 of 60
MORPHX IT
Inleiding
Inleiding
Samples from MORPHX IT -- steenandreasen.com
Dit boek is een inleiding tot de ontwikkelomgeving van Axapta, ook bekend onder de naam MorphX. MORPHX IT is geschreven als een praktisch boek. Met praktisch bedoel ik dat je dit boek moet gebruiken terwijl je werkt met Axapta. Dit maakt van het boek ook een waardevolle dagelijkse metgezel gezien er een aanzienlijk aantal voorbeelden in staan. Ik geloof dat het direct gebruiken van het systeem de eenvoudigste en snelste manier is om een nieuwe ontwikkelingstaal te leren. Je moet beschikken over een geïnstalleerde Axapta applicatie en je moet een basiskennis hebben over hoe de Axapta user interface eruit ziet. Deze informatie kan je vinden in de handleidingen van het standaardpakket. Centraal in dit boek is het gezichtspunt van de ontwikkelaar. Je kan dit boek gebruiken zonder enige kennis over Axapta. Natuurlijk zal het eenvoudiger zijn als je je eerste stappen in de applicatie zelf hebt gezet. Je zal er je voordeel uithalen als je de voorbeelden uitprobeert terwijl je het boek leest. De voorbeelden in dit boek zitten in de zip file MORPHXIT_1ED_EXAMPLES.ZIP dat bij het boek hoort. Axapta 3.0 Service Pack 4 was geïnstalleerd bij het schrijven van dit boek. Als je een andere Service Pack van Axapta 3.0 gebruikt, kan je hier en daar kleine verschillen zien. Het boek is geschreven voor mensen die geen voorkennis hebben van programmatie in Axapta. Een achtergrond als programmeur is handig maar niet noodzakelijk. Het boek kan ook gelezen worden door personen met een technische achtergrond of door Axapta applicatieconsulenten die de ontwikkelomgeving willen gebruiken. Als je een beginner bent, raad ik je aan om de hoofdstukken vanaf het begin van het boek te lezen omdat ieder hoofdstuk meer en meer details van de omgeving bijbrengt. Mogelijk zijn er begrippen die je niet direct begrijpt. Niet alle begrippen in een hoofdstuk worden direct uitgelegd. Ik heb hiervoor gekozen om de inhoud zo eenvoudig mogelijk te houden. Alle begrippen ineens uitleggen zou dit boek te theoretisch maken om dagelijks te gebruiken. Vaak zijn er verwijzingen naar andere secties in hetzelfde hoofdstuk of naar andere hoofdstukken, waar je meer informatie van een bepaald begrip kan opzoeken. Ben je een meer ervaren Axapta gebruiker, dan kan je hoofdstukken van het boek uitkiezen om meer te weten te komen over een bepaald onderwerp.
© 2007 Steen Andreasen
8 of 60
MORPHX IT
Inleiding
Waarom dit boek belangrijk is Gedurende de jaren dat ik met Axapta heb gewerkt, was ik me bewust van het gebrek aan documentatie over de Axapta ontwikkelomgeving. Beschouw dit boek als de nota’s die je zou willen hebben als je in Axapta begint te programmeren.
Samples from MORPHX IT -- steenandreasen.com
MORPHXIT is het eerste Axapta programmatieboek en kan beschouwd worden als een alternatief voor het volgen van cursussen om te leren programmeren in Axapta. Met dit boek heb je een metgezel die je de ontwikkelomgeving van Axapta snel zal leren kennen. Een gids die je zal leren om je applicatie zo aan te passen dat je code eenvoudiger te onderhouden is en gebruikersvriendelijker voor de applicatiegebruikers.
Structuur van het boek Bij het schrijven van het boek heb ik een keuze moeten maken van wat ik belangrijk vind voor een inleidend boek. Het web framework wordt niet in dit boek behandeld. Er zijn meerdere redenen waarom het web framework of raamwerk niet behandeld wordt. De focus lag op de kennis die een nieuwkomer in Axapta programmatie nodig heeft. Het zijn vaak ervaren Axapta programmeurs die met het web raamwerk starten. En voor de meeste klanten heb je de webonderdelen van Axapta niet nodig. Als ik een begrip in het boek behandel zoals een tool gebruikt in de ontwikkelingsomgeving, dan beschrijf ik niet alle velden, knoppen of kenmerken van de tool. Begrippen leg ik vaak uit zoals je dat doet als je iemand naast je hebt zitten. Dit gaat vooral op voor de Appendix MorphX Tools. Bij het lezen van dit boek zal je een heleboel praktische tips en aanbevelingen zien. Ik maak geen onderscheid tussen beide begrippen. Samen vormen ze mijn eigen set van regels die ik gebruik voor het programmeren of beheren van een ontwikkelproject in Axapta. De hoofdstukken in het boek volgen de drie voornaamste nodes in de Axapta ontwikkelomgeving, te beginnen met de inleidende hoofdstukken over de ontwikkelomgeving en ontwikkeltaal. Ze worden gevolgd door de hoofdstukken over hoe je de ontwikkelomgeving moet gebruiken. Achteraan in het boek vind je appendixhoofdstukken die verdere informatie bevatten over sommigen begrippen van het boek.
© 2007 Steen Andreasen
9 of 60
MORPHX IT
1
Rapporten
Rapporten
Samples from MORPHX IT -- steenandreasen.com
Rapporten in Axapta zijn gebaseerd op een query en een ontwerp (design) die beheerd worden in de Application Object Tree (AOT). Een rapport is enkel een definitie, het bevat geen gegevens en bij uitvoer zal het de gegevens die het nodig heeft, ophalen uit de databank. Als je een rapport uitvoert, heb je de optie om het rapport direct af te drukken, dan wel een batch job te definiëren om het rapport later uit te voeren op een afzonderlijke batch server. Stapelverwerking of batch processing wordt gebruikt voor lange rapporten zoals het maandelijks afdrukken van de klantenbalanslijsten. Axapta rapporten zijn zeer flexibel omdat MorphX tools voorziet om de rapportdefinitie te overschrijven zonder dat je hiervoor complexe programmatie moet doen. Door het gebruik van de MorphX omgeving, kan je data filteren of zelfs de opmaak van de printopdracht bij runtime wijzigen. Er zijn twee manieren om rapporten aan te maken in Axapta. Je kan de ingebouwde report wizard gebruiken, of je gebruikt de rapportgenerator, die je kan vinden in de AOT onder Reports. Dit hoofdstuk spitst zich toe op de technische aspecten van het aanmaken van rapporten en is niet bedoeld om de verschillende opties van het rapportdialoogvenster te behandelen. Hoewel het natuurlijk handig is als je de gebruikersinterface van Axapta begrijpt, moet je de report user interface niet begrijpen om je voordeel te halen uit de informatie in dit hoofdstuk. Als je niet vertrouwd bent met de eindgebruikersinterface voor rapporten, krijg je meer gedetailleerde informatie door de handleidingen in het standaardpakket na te lezen.
1.1
Report Wizard
De Report wizard is een hulpmiddel ontworpen om niet-technische personen toe te laten rapporten aan te maken. De wizard kan gestart worden via de toolbar menu Tools | Development tools | Wizards | Report Wizard. Dit is een goed startpunt om te leren werken met Axapta rapporten. De Report wizard is een eindgebruikerstool die je door de verschillende stappen gidst om een rapport aan te maken. Je hebt de mogelijkheid om een rapport, aangemaakt door de wizard, te bewaren in de AOT. Het is aangewezen voor nieuwe Axapta programmeurs om deze objecten, aangemaakt door de wizard, na te kijken om zo vertrouwd te geraken met de standaard elementen in een rapport. De Report Wizard is ook een goed hulpmiddel voor ervaren Axapta programmeurs die het kunnen gebruiken om de basisstructuur van het rapport te maken en die daarna de rapportgenerator gebruiken voor de laatste wijzigingen. Voor een stap-per-stapgids over de werking van de Report wizard verwijs ik naar de Appendix : Reports Wizard.
© 2007 Steen Andreasen
10 of 60
MORPHX IT
Samples from MORPHX IT -- steenandreasen.com
1.2
Rapporten
Het maken van rapporten
Als je de output bekijkt die door de report wizard wordt gegenereerd, kan je zien wat er vereist is om rapporten vanaf nul te bouwen met behulp van de rapportgenerator. Als je leert hoe je een nieuw rapport moet maken, is het nuttig om te starten bij enkele standaardrapporten in de AOT om te zien of je een bestaand rapport kan vinden dat al aan sommige vereisten voldoet. Kopieer dit rapport en wijzig de kopie waar nodig. Als je wil weten hoe je een rapport op een menu kan terugvinden in de AOT, kijk dan in het hoofdstuk Menu’s en menuopties. Als je start met de rapportgenerator, kunnen de handleidingrapporten of tutorial reports in het standaardpakket je ook verder helpen. Neem een kijkje in de AOT naar rapporten waarvan de naam begint met tutorial_. Axaptarapporten bestaan uit twee onderdelen. Ieder van die onderdelen wordt in de AOT voorgesteld als een vertakking of node. De Data Sources vertakking definieert welke gegevens er opgehaald moeten worden en de Designs vertakking bepaalt de opmaak en presentatie van het rapport. Figuur 1 rapport overzicht toont een overzicht van een doorsneerapport.
Figuur 1: Rapportoverzicht
© 2007 Steen Andreasen
11 of 60
MORPHX IT
Rapporten
Voorbeeld 1: mijn eerste rapport
Samples from MORPHX IT -- steenandreasen.com
Elementen gebruikt van het MORPHXIT_Reports project Report, MyReport Menu item output, MyReport Als eerste oefening ga je een rapport maken zoals getoond wordt in Figuur 1 rapportoverzicht. Het rapport drukt klantentransacties af, gegroepeerd per klant. Het voorbeeld wordt eenvoudig gehouden omdat het de bedoeling is de basisstappen te leren die nodig zijn om een rapport aan te maken. Verderop in dit hoofdstuk worden de details uitgelegd en meer elementen worden toegevoegd aan het voorbeeld. 1. Om een nieuw rapport aan te maken, selecteer je de Reports node in de AOT , klik met de rechtermuisknop en selecteer New Report. Een nieuw rapport met de naam "Report1" wordt aangemaakt. Open de property sheet en geef het rapport de naam "MyReport". 2. Voor dit rapport haal je je informatie uit de Customer hoofdtabel samen met de bijbehorende transactiegegevens van iedere klant. Dit bereik je door twee niveaus van gegevensbronnen of data sources voor de query te definiëren. Voor dit voorbeeld is de klantentabel op het eerste niveau en de klantentransactietabel is op het tweede niveau. Het ontwikkelen in Morphx gebeurt vaak via het verslepen van elementen (“drag and drop”). In dit geval ga je tabellen van de ene sectie van de AOT verslepen naar de gegevensbron van het rapport waar je mee bezig bent. Om de taak van het verslepen zo eenvoudig mogelijk te maken, laat Axapta je toe om verschillende zichten van de AOT openen. In dit geval open je een nieuw zicht van de AOT, en klik door tot de Data Dictionary/Tables vertakking. Selecteer de tabel CustTable. Klik de Data Sources/Query vertakking in je rapport open en versleep de CustTable naar de Data Sources/Query/Data Sources vertakking. Nu heb je het eerste niveau van de query toegevoegd. Klik de CustTable data sources vertakking in je rapport open. Versleep de tabel CustTrans naar de CustTable/Data Sources vertakking. 3. De twee gegevensbronnen van de query moeten gekoppeld worden om te vermijden dat alle transacties van de Customer Transaction tabel voor iedere klant worden afgedrukt. Ga naar de CustTrans vertakking in de Query en zet de eigenschap Relations op “Yes.” De vertakking CustTrans/Relations bevat nu een element dat beide tabellen aan elkaar koppelt. Het rapport drukt nu enkel de transacties af die behoren bij de klant die door het rapport behandeld wordt. 4. De query is nu klaar om gegevens op te halen voor het rapport; nu moeten we de presentatie van de gegevens aanpakken. Ga naar de Designs vertakking, klik met de rechtermuisknop en kies New Report Design. Een nieuw ontwerp met de naam "ReportDesign1" wordt aangemaakt. Navigeer naar de ReportDesign1 vertakking
© 2007 Steen Andreasen
12 of 60
MORPHX IT
Rapporten
en selecteer de Caption eigenschap; Geef hier de tekst "Customer transactions list" in.
Samples from MORPHX IT -- steenandreasen.com
5. Ga naar de ReportDesign1/AutoDesignSpecs vertakking. Selecteer de vertakking, klik met de rechtermuisknop en selecteer Generate Specs From Query. Je ontwerp omvat nu twee secties, één voor elke tabel in de query. 6. De laatste stap is de selectie van de velden die afgedrukt moeten worden. Selecteer de Query vertakking van je rapport, klik met de rechtermuisknop en kies Open New Window. Dit vereenvoudigt het verslepen van de af te drukken velden naar het ontwerp. Kies de velden AccountNum en Name van de CustTable data source en versleep de velden één voor een naar de sectie node CustTable_Body. Ga naar de CustTrans data source en versleep de velden Voucher, TransDate en AmountMST naar de sectie CustTrans_Body. 7. Je hebt nu een rapport zoals getoond in Figuur 1. Om het rapport uit te voeren, selecteer je de rapportnaam, klik met de rechtermuisknop en kies Open. Axapta toont een dialoogvenster voor het filteren, sorteren en andere afdrukopties. Klik op OK. Het volgende dialoogvenster is de printerdialoog. Kijk na of de printout verwijst naar “Screen” en klik op OK. Je rapport wordt nu afgedrukt naar het scherm. 8. Zoals je wellicht hebt opgemerkt, laat de opmaak te wensen over. Veel van de formatteringstaken kan je overlaten aan MorphX door aan te geven dat het rapport gebruik moet maken van een voorgedefinieerde rapportsjabloon of report template. Sjablonen geven MorphX de instructie om standaardrapportkenmerken aan te maken zoals hoofdingen. Om een sjabloon toe te voegen aan je rapport, ga je naar de Designs/reportDesign1 vertakking en zoek naar de eigenschap ReportTemplate. Klik op de pijl en kies de sjabloon InternalList. 9. Voer het rapport opnieuw uit door stap 7 te volgen. Het rapport heeft nu hoofdinginformatie zoals de rapportnaam, paginanummer, datum en tijd. Je hebt je eerste rapport gemaakt ! In het voorbeeld MyReport heb je niet één enkele lijn code moeten schrijven. Als je rapporten maakt in Axapta, moet je geen code schrijven voor data connecties en het positioneren van controls of schermvelden in de opmaak. MorphX doet dit allemaal voor je. Maak een query en selecteer de kolomvolgorde van je controls in het ontwerp. Je moet enkel gebruik maken van X++ als je meer complexe rapporten maakt waar het ophalen van gegevens te moeilijk is voor een query of als je een speciale opmaak nodig hebt. Als je het rapport uitvoerde, werden er twee dialoogvensters getoond. Probeer een menupunt te maken voor MyReport door MyReport te verslepen naar de Menu Items/Output vertakking. Je kan nu je rapport uitvoeren door het menupunt te
© 2007 Steen Andreasen
13 of 60
MORPHX IT
Rapporten
selecteren, met de rechtermuisknop te klikken en vervolgens Open te kiezen. De informatie die voordien in twee verschillende dialoogvensters werd getoond, zie je nu in één enkel venster. Het uitvoeren van een rapport via een menupunt activeert automatisch een meer verfijnde rapportraamwerk of report framework bij runtime. Dit is de dialoog die de gebruikers zullen zien. Meer details worden later in dit hoofdstuk behandeld.
Samples from MORPHX IT -- steenandreasen.com
1.3
Report Query
Er zijn situaties waarin een query niet voldoende is voor je vragen en je de gegevens moet ophalen met behulp van X++. Maar meestal haal je de gegevens voor een rapport op met een query die de gegevensbronnen of data sources voor het rapport definieert en aangeeft hoe deze met elkaar verbonden zijn. De rapportgenerator gebruikt een standaard Axapta query. Voor meer informatie over de opbouw van een query verwijs ik naar het hoofdstuk Queries. Voor je de query opbouwt, moet je beslissen welke tabellen je nodig hebt. Het is vaak het geval, zoals in het voorbeeld van MyReport, dat je gegevens moet afdrukken uit een enkel formulier of een reeks van aanverwante formulieren. In dit geval moet je de formulieren zelf nakijken om de namen van de benodigde tabellen op te zoeken. Voor uitleg over het bepalen van tabellen en velden op formulieren, verwijs ik naar het hoofdstuk Menus en menupunten. Nadat je de vereiste tabellen hebt bepaald, moet je nagaan hoe de gegevens gesorteerd moeten worden. Vervolgens moet je de gegevens filteren om overbodige records van het rapport uit te sluiten. De beslissing die je hier maakt, kan een grote invloed hebben op de systeemperformantie. Wat bijkomende planning op dit moment kan de uitvoertijd van het rapport aanzienlijk beperken. Zo zijn de selectiecriteria meer efficiënt als je ze plaatst op de tabel op het hoogste niveau in de gegevensbron. Je kan als algemene regel hanteren dat je het gebruik van de selectiecriteria moet beperken tot de eerste twee niveau’s van de gegevensbron. Als je rapport gegevens filtert op het derde niveau van de query, moet je je ontwerp herbekijken en proberen een meer doeltreffende manier te vinden. Krijg je hetzelfde resultaat door het gebruik van twee aparte rapporten ? Indien niet, kan je dan gebruik maken van een tijdelijke tabel om het gewenste resultaat te bekomen ? Voor de meeste rapporten zal je alle vereiste tabellen toevoegen aan de Query vertakking van het rapport. Als gegevens van gerelateerde tabellen worden gebruikt, moeten de tabellen gekoppeld worden in de query zoals je dat hebt gedaan met CustTable en CustTrans in het MyReport voorbeeld. Soms is het nodig om gegevens op te halen uit twee tabellen die geen relatie hebben die kan dienen als koppeling. In dit geval moet je kijken naar een andere tabel die een relatie heeft met beide tabellen waarop je je rapport wil baseren. Een voorbeeld hiervan is de afdruk van verkooporderlijnen gegroepeerd per klant. Er is geen directe relatie tussen de Customer tabel en de Sales Invoice Lines tabel. Daarom moet je de Customer Invoice Journal tabel gebruiken om het rapport te creëren. Zie Figuur 2: Relatie tussen
© 2007 Steen Andreasen
14 of 60
MORPHX IT
Rapporten
CustTable en CustInvoiceTrans. Je kan de drie tabellen toevoegen aan de query, of je kan enkel de tabel van het eerste niveau CustTable toevoegen als een gegevensbron en X++ gebruiken om de twee andere tabellen op te halen. Men geeft er doorgaans de voorkeur aan om een query te gebruiken in plaats van X++ aangezien deze werkwijze de gebruiker de voordelen biedt van de rapportdialoog-vensters. C ustTable
C ustInvoiceJour
InvoiceAccount
C ustomers 77
dat
62
C ustInvoiceTr ans
+CustInvoiceJour
C ustomer invoice journal
dat
C ustomer invoice lines 64
dat
Samples from MORPHX IT -- steenandreasen.com
Figuur 2 : Relatie tussen CustTable en CustInvoiceTrans
Het koppelen van gegevensbronnen kan op twee manieren gebeuren. Als de gegevensbronnen al een relatie hebben, dan moet de eigenschap Relation van de gegevensbron op het lagere niveau de waarde True hebben, zoals in MyReport. De relatie zal dan zichtbaar zijn onder de Relations vertakking voor de gekoppelde gegevensbron. Als er geen relatie getoond wordt, moet je de relatie zelf aanmaken onder de Relations vertakking en de eigenschap Relation moet de waarde False hebben. Het is aangewezen om een reeds bestaande relatie te gebruiken, eerder dan je eigen relatie aan te maken, omdat wijzigingen aan de data dictionary automatisch meegenomen worden in het rapport. De standaardkoppeling voor gegevensbronnen of data sources is de inner join, maar de join mode kan gewijzigd worden in de eigenschappen van de gekoppelde gegevensbron. Inner joins worden vaak gebruikt in bedrijfsrapportering waar je gegevens hebt in een hoofdtabel en je wil alle bijbehorende transacties afdrukken. Als je echter alle records van de hoofdtabel wil afdrukken, ook als er geen bijbehorende transacties bestaan, dan moet je join mode wijzigen naar OuterJoin op de transactietabel. Als je de Fields vertakking selecteert en met de rechtermuisknop klikt, kan je een veld of een aggregatiefunctie toevoegen. Normaal worden alle velden van de huidige tabel opgelijst en dus heeft het geen zin om bijkomende velden van de tabel toe te voegen. Als je een aggregatiefunctie toevoegt, worden alle velden verwijderd omdat je ze niet allebei kan gebruiken. Om de aggregatiefuncties te verwijderen, en de veldlijst te herstellen, verander je de Dynamic eigenschap van de Fields vertakking in Yes. De aggregatiefuncties kunnen gebruikt worden als je het aantal klanten per klantgroep wil tellen Je moet een tabel selecteren, een aggregatiefunctie kiezen en de te gebruiken velden. Voorbeeld 2: Aggregatiefunctie
Elementen gebruikt van het MORPHXIT_Reports project Report, MyReport_aggregate Menu item output, MyReport_aggregate Het volgende voorbeeld telt het aantal klanten per klantgroep. Het ontwerp is vereenvoudigd om de aandacht toe te spitsen op de aggregatiefuncties.
© 2007 Steen Andreasen
15 of 60
MORPHX IT
Rapporten
1. Voeg de Customer tabel toe aan de report query. Navigeer dan naar de Fields vertakking, klik met de rechtermuisknop en selecteer de aggregatiefunctie Count. De waarde van het count field moet AccountNum zijn.
Samples from MORPHX IT -- steenandreasen.com
2. Zet de eigenschap OrderMode van de CustTable data source op Group by. Als laatste stap moet je aangeven hoe de informatie gesorteerd moet worden. Ga naar de Sorting vertakking en voeg het veld CustGroup toe. Je hebt nu een query zoals getoond in Figuur 3: Aggregatiefunctie.
Figuur 3 : Aggregatiefunctie
3. De volgende stap is het maken van een ontwerp om het resultaat af te drukken. Creëer een auto design en kies voor Generate Specs From Query zoals dat gebeurd is in het MyReport voorbeeld. Je hebt nu een sectie voor CustTable met een field control voor het afdrukken van het veld CustGroup. Voeg het veld AccountNum toe. 4. Voer het rapport uit. Een rij zal gedrukt worden voor iedere klantengroep. Het veld AccountNum telt het aantal klanten in iedere klantengroep . Bij het gebruik van aggregatiefuncties moeten gegevens geselecteerd worden waarbij de “group by” parameter de waarde OrderMode heeft. De compiler zal een foutmelding geven als je de “order by” wil selecteren. Dit is logisch als je bedenkt dat informatie record per record wordt opgehaald bij het gebruik van “order by”. Als je OrderMode gebruikt als waarde voor de “group by” parameter, zal MorphX een enkel record ophalen voor iedere groep gebaseerd op de sorteervelden. Dit betekent dat alleen de velden aangeduid als sorteervelden een waarde zullen bevatten bij het gebruik van “group by”. Je kan zoveel aggregatiefuncties toevoegen als je nodig hebt. Zo kan je een transactielijst afdrukken met een aggregatie voor het minimum, maximum en gemiddelde bedrag. De Sorting vertakking onder de Data Sources vertakking wordt gebruikt om aan te geven hoe de output van het rapport gesorteerd moet worden. Hierbij kan je gebruik maken van indexen of velden. Je moet minstens één index of sorteerveld aanduiden. Bij het uitvoeren van het rapport kan de gebruiker de sorteervelden wijzigen. Bedenk dat het gebruik van een veld voor sorteren in plaats van een index de uitvoering van je rapport kan doen vertragen.
© 2007 Steen Andreasen
16 of 60
MORPHX IT
Rapporten
Samples from MORPHX IT -- steenandreasen.com
De sorteervelden hebben een eigenschap met de naam AutoSum. Deze eigenschap wordt gebruikt als je wil dat MorphX subtotalen afdrukt bij het wijzigen van de waarde van het sorteerveld. Auto Sums worden meer gedetailleerd uitgelegd als we Auto design behandelen. Bereiken of ranges worden gebruikt om de records te filteren. De standaardbereiken of default ranges worden gespecifieerd in de Range vertakking onder de data source vertakking. Bij uitvoer van het rapport krijgt de gebruiker de kans om nog extra bereiken toe te voegen of de standaardbereiken te verwijderen, afhankelijk van de waarden van de eigenschap van het bereik. Zo kan je voor een bereik een standaardwaarde opgeven en aanduiden of de gebruiker deze opgegeven waardes nog mag wijzigen. De eigenschappen of properties kunnen ook aangeven of het bereik vergrendeld of verborgen moet zijn. Als er geen bereik wordt opgegeven, zal het eerste element van iedere index voor de tabel gebruikt worden als standaardbereik bij het uitvoeren van het rapport. Bij wijze van test kan je het rapport MyReport uitvoeren. Je zal zien dat een standaardset van bereiken is toegevoegd. Voeg nu het veld AccountNum toe aan de Data sources/CustTable/Ranges vertakking. Als je MyReport nu uitvoert, zal alleen het bereik AccountNum getoond worden.
1.4
Sjablonen
In Axapta heb je twee verschillende types sjablonen : de rapportsjablonen ( report templates) en de sectiesjablonen (section templates). De sjablonen verschijnen als de eerste twee ingangen onder de Report vertakking in de AOT.
Rapportsjabloon Rapportsjablonen worden gebruikt om de basisformattering van een rapport te definiëren, zoals de hoofding en voetregel (header en footer). Je kan sjablonen maken voor complexere gevallen zoals het gebruiken van gegevens van specifieke tabellen, maar hiermee beperk je ook het aantal gevallen waarin je dit sjabloon kan gebruiken. Rapportsjablonen worden doorgaans gebruikt voor informatie die geen betrekking heeft op een specifieke tabel, zoals een titel, paginanummering en lijnen. De sjabloon InternalList gebruikt in het MyReport voorbeeld, is een algemeen gebruikt rapportsjabloon. Dit sjabloon formatteert de rapportnaam, bedrijfsnaam, paginanummer, datum en tijd. Om de sjabloon te bekijken, zoek je ze op in de AOT, selecteer de sjabloonvertakking, klik met de rechtermuisknop en kies Edit om de visual editor te openen. Als je een rapportsjabloon aanmaakt met controls van een specifieke tabel, dan zal ieder rapport, gebaseerd op dit sjabloon, toch nog expliciet de tabel moeten declareren en de vereiste records ophalen. Example 3: Rapportsjabloon
Elements used from MORPHXIT_Reports project
© 2007 Steen Andreasen
17 of 60
MORPHX IT
Rapporten
Report template, MyInternalList Report, MyReport_MyInternalList In dit voorbeeld maak je een nieuw sjabloon, gebaseerd op de InternalList sjabloon. InternalList bevat de basisopmaak van een hoofding. Je gaat een proloog en een epiloog sectie toevoegen aan de nieuwe sjabloon. Het MyReport voorbeeld wordt uitgebreid met de nieuwe rapportsjabloon.
Samples from MORPHX IT -- steenandreasen.com
1. Maak eerst een kopie van MyReport en hernoem het nieuwe rapport “MyReport_MyInternalList”. 2. Ga naar de AOT en zoek het rapportsjabloon InternalList. Klik met je rechtermuisknop op de rapportsjabloon en kies Duplicate. Hernoem de nieuwe rapportsjabloon “MyInternalList”. 3. Klik met de rechtermuisknop op de naam van de rapportsjabloon; kies New en selecteer de rapportsectie Prolog De proloog zal een tekst en een nieuw paginabegin bevatten. Eerst moet de tekst die je gaat printen, worden gedefinieerd. Ga naar Prolog/Methods; klik hierop met je rechtermuisknop en kies New Method. Open de nieuwe methode en typ het volgende in: display description prologDescription() { return strfmt("Start of report: %1", element.design().lookupCaption()); }
Deze methode zal een “Start of report” string opleveren dat de waarde van de titel van het rapportontwerp bevat. Deze methode moet dan aangeroepen worden in het proloogontwerp. Sluit de editor en sleep de methode naar de Prolog vertakking. Axapta zal een string control maken, die de waarde afdrukt die door de display methode wordt teruggegeven. 4. Klik met je rechtermuisknop op de naam van de rapportsjabloon, kies New en selecteer de rapportsectie Epilog. Creëer nu de volgende methode en sleep de methode naar de Epilog vertakking. display description epilogDescription() { return strfmt("End of report: %1", element.design().lookupCaption()); }
5. Als je de proloog- en epiloogsecties wil printen op nieuwe pagina’s, moet je een nieuw paginabegin toevoegen. Ga naar Prolog/Methods; klik met je rechtermuisknop en kies Override Method en selecteer executeSection(). Merk op dat de oproep van de newPage methode geplaatst is na de oproep van super(). Hierdoor zal een nieuwe pagina beginnen nadat de proloogsectie afgedrukt is.
© 2007 Steen Andreasen
18 of 60
MORPHX IT
Rapporten
public void executeSection() { super(); element.newPage();
Samples from MORPHX IT -- steenandreasen.com
}
© 2007 Steen Andreasen
19 of 60
MORPHX IT
Rapporten
Samples from MORPHX IT -- steenandreasen.com
6. Voeg een nieuw paginabegin toe aan de epiloogsectie. Het nieuw paginabegin moet uitgevoerd worden voor de super() methode in de epiloogsectie, omdat de epiloog moet geprint worden op een nieuwe pagina. Je moet nu een rapportsjabloon hebben zoals afgebeeld in Figuur 4 : rapportsjabloon.
Figuur 4 : rapportsjabloon
7. De volgende stap is de nieuwe rapportsjabloon gebruiken in MyReport_MyInternalList. Ga naar de vertakking Designs/ReportDesign1; open het eigenschappenblad en selecteer MyInternalTemplate als de rapportsjabloon. 8. Creëer een nieuwe menuoptie voor het rapport. Wanneer het rapport wordt uitgevoerd, zal er een pagina voor de proloog voor het rapport en een pagina voor de epiloog na het rapport worden afgedrukt. De MyInternalList sjabloon gebruikt displaymethodes om de waarden voor de controls terug te geven. Net zoals in het geval van formulieren, gebruik je regelmatig displaymethodes als je een rapport maakt of aanpast. Dit is één van de manieren om gegevens te printen die je niet gemakkelijk kan ophalen met een query. In dit voorbeeld gebruik je de displaymethode om een string terug te geven, in andere gevallen kan het een resultaat van een berekening zijn. Je maakt gewoon de displaymethode en sleept de methode naar het ontwerp. Je moet je geen zorgen maken over het controltype om de juiste waarde weer te geven. MorphX doet dit voor jou door het return type van de methode na te kijken. Je moet overwegen of je één of twee rapportsjablonen gaat gebruiken voor de meeste van je rapporten. Het voordeel van het gebruiken van één rapportsjabloon is dat het je toelaat om de basisopmaak van je rapporten te standaardiseren. Als je later besluit om een rapportsjabloon aan te passen, zullen alle rapporten met auto-ontwerp die dit sjabloon gebruiken, automatisch mee veranderen.
© 2007 Steen Andreasen
20 of 60
MORPHX IT
Rapporten
Samples from MORPHX IT -- steenandreasen.com
Opmerking: Het is vaak nodig om zowel de paginanummer af te drukken als het totaal aantal pagina’s. Het sjabloon InternalList gebruikt element.page() om de huidige paginanummer af te drukken. De methode element.pagesTotal() geeft het totaal aantal af te drukken pagina’s weer. Element.pagesTotal() kan alleen gebruikt worden als return value voor een displaymethode met return type integer. Het totaal aantal pagina’s wordt berekend tijdens het uitvoeren van het rapport dus kan je de methode niet gebruiken voor validaties. Om <page> of <page total> af te drukken, zal je gebruik moeten maken van 3 report controls.
Sectiesjabloon De sectiesjablonen zijn geïntroduceerd in versie 3.0. Dit kan de reden zijn waarom ze zelden gebruikt worden en je geen voorbeelden van hun gebruik zal terug vinden in het standaardpakket. Een sectiesjabloon moet gebaseerd zijn op een tabelmap. Tabelmappen worden uitgelegd in het hoofdstuk Data Dictionary. Velden van de map kunnen toegevoegd worden als controls. In het geval dat je rapporten met gelijkaardige sectieblokken hebt, kan je dankzij een sectiesjabloon hetzelfde stuk code herbruiken in plaats van dezelfde sectieblok telkens weer op te bouwen in verschillende rapporten. Niettemin kan het in praktijk gemakkelijker zijn om één rapport te maken en X++ te gebruiken om de output aan te passen in plaats van twee rapporten te gebruiken met een sectiesjabloon. Het SalesInvoice rapport is hiervan een uitstekend voorbeeld.
1.5
Ontwerpen
Het plaatsen van velden en controls in je ontwerp wordt gedaan door MorphX. Alle controls zullen automatisch naar de standaard worden aangepast zoals gevraagd. Dit betekent dat de controls gezet worden op automatisch positioneren. Het lettertype en de lettergrootte worden bepaald door de gebruikersopties in de werkbalkmenu Tools/Options in het tabblad Fonts. Wanneer je de volgorde van de rijen kiest, zal MorphX de controls positioneren, gebaseerd op de uitgebreide datatypes. Dit kan zeer handig zijn : als je ooit een control moet toevoegen in het midden van een rij of je wil een control verbergen, dan worden de volgende controls geherpositioneerd. Voor de meeste rapporten moet je Morphx toelaten om de controls zelf te plaatsen. In situaties waar je controls altijd een vaste positie moeten hebben, kan je de standaard instellingen overschrijven. Dit heeft wel één nadeel : als je één enkele control op een vaste positie in een rij zet, dan moet je vaste posities definiëren voor alle controls. Dit is meestal niet aan te raden, tenzij je controls in een voorgedrukt formulier moeten passen of beantwoorden aan specificaties van klanten, verkopers of de overheid. Als je controls moet afdrukken die onder elkaar zijn gepositioneerd in dezelfde kolom, kan je de eigenschap ModelFieldname gebruiken (alle report controls hebben
© 2007 Steen Andreasen
21 of 60
MORPHX IT
Rapporten
deze eigenschap). De positie van de huidige control zal zich aanpassen aan de positie van control bepaald in ModelFieldName, als de positionering van de huidige control op automatisch worden gezet.
Samples from MORPHX IT -- steenandreasen.com
Het ontwerp maken Een rapport kan meer dan één ontwerp hebben. Onder de ontwerp vertakking (Design node) kan je zoveel ontwerpen maken als je nodig hebt. Dit kan zeer nuttig zijn als je een formulier hebt dat je wil afdrukken met een verschillende opmaak voor elke taal of voor elke klantengroep. Verschillende ontwerpen in één rapport worden niet vaak gebruikt in het standaardpakket. In plaats van te werken met verschillende ontwerpen, kan je de nood aan verschillende layout oplossen met X++, een voorbeeld hiervan is het Sales Invoice rapport. In het SalesInvoice rapport zal de methode element.changeDesign() ervoor zorgen dat er wel of niet een control zal geprint worden. Het vraagt dikwijls meer tijd om verschillen in meerdere ontwerpen na te kijken dan één ontwerp te manipuleren met X++. Het onderhoud van de hoofdingsecties over verschillende ontwerpen is vervelend werk, omdat het tijd vraagt om na te gaan of je veranderingen hetzelfde zijn in alle ontwerpen. Opmerking : Als je een rapport maakt zoals een formulier dat moet passen in een voorgedrukte layout, kan het nodig zijn om de laatste aanpassing te doen met gebruik van de specifieke printer driver die gebruikt zal worden om voor de productieoutput te zorgen. Variaties in printers kan ervoor zorgen dat velden op een andere plaats worden afgedrukt. Vaak zal de opmaak of layout aangepast worden naar gelang de gebruikte printer driver.
Ontwerpen kunnen gemaakt worden als auto-ontwerp of gegenereerd ontwerp. Een ontwerp kan ook zowel een auto-ontwerp als een gegenereerd ontwerp bevatten. In dit geval wordt alleen het gegenereerd ontwerp gebruikt. Het grote verschil tussen de twee is dat auto-ontwerpen alle mogelijkheden van MorphX gebruiken : ze laten dynamische sjablonen toe, auto-hoofdingen en auto-sommen gebaseerd op de criteria toe die je in de query hebt vastgelegd. Gegenereerde ontwerpen zijn statisch en zullen zich niet automatisch aanpassen aan de veranderingen die je maakt in de query of de rapportsjabloon. Het wordt aangeraden om auto-ontwerpen te gebruiken. Je kan overwegen gebruik te maken van gegenereerde ontwerpen maar dan enkel in speciale gevallen waar een vaste layout vereist is. Gegenereerde ontwerpen zijn doorgaans enkel nodig wanneer de opmaak vastgelegd is door een contract of statuut , of wanneer je gebruik moet maken van voorgedrukte formulieren zoals cheques en aankooporders. Gegenereerde ontwerpen hebben extra secties om paginahoofdingen en –voetregels of footers toe te voegen aan de middensectie. Voor de rest gebruiken auto-ontwerp en gegenereerd ontwerp dezelfde soort secties. Zie figuur 5 Rapportontwerpsecties voor een overzicht van de secties in rapportontwikkeling Type Proloog
Omschrijving Dit is de eerste sectie die afgedrukt wordt. De
© 2007 Steen Andreasen
22 of 60
MORPHX IT
Rapporten
Samples from MORPHX IT -- steenandreasen.com
proloog wordt meestal gebruikt om een logo of een titel op de eerste pagina af te drukken. Paginahoofding
De paginahoofding wordt bovenaan op elke pagina afgedrukt. Een rapport kan meer dan één paginahoofding hebben.
Midden
De middensectie wordt afgedrukt na de paginahoofding. Dit is de gegevenssectie. Het rapport zal normaal gezien een middensectie bevatten voor elke gegevensbron (data source).
Paginavoetregel
De voetregel wordt onderaan elke pagina afgedrukt. Een rapport kan meer dan één paginavoetregel hebben.
Epiloog
Dit is de laatste pagina die afgedrukt wordt.
Programmeerbare sectie
Programmeerbare secties worden uitgevoerd op basis van code. Dit type van secties kan gebruikt worden in gevallen , waar je gegevens moet printen die geen deel zijn van de query.
Sectiesjabloon
Sectiesjablonen worden gebruikt om veelvuldig gebruikte gegevens te definiëren; het wordt meestal gebruikt in middensecties. Een sectie is gebaseerd op een Map.
Hoofding
Hoofding wordt gebruikt in gegenereerde ontwerpen als hoofding van de middensectie.
Sectiegroep
In gegenereerde ontwerpen wordt de middensectie toegevoegd aan een sectiegroep.
Voetregel
Voetregel wordt gebruikt in gegenereerde ontwerpen als voetregel voor een middensectie.
Figuur 5 : Rapportontwerpsecties
Je kan bij benadering een beeld van het rapport zien als je view selecteert. De view optie kan bijna hetzelfde zijn als het geprint resultaat. Maar als een rapport een complex ontwerp heeft zoals het SalesInvoice rapport, kan het moeilijk zijn om uit te puzzelen hoe het resultaat eruit zal zien als het geprint is. Je hebt twee opties om controls toe te voegen aan je ontwerp, ofwel door het gebruik van de vertakkingen van de rapportboom, die je hebt gezien in voorgaande voorbeelden, ofwel door de visuele editor te gebruiken. De visuele editor geeft de optie om de controls in je ontwerp te zien of aan te passen. Om een rapport te editeren met de rapportboom, moet je dubbelklikken op de ontwerpvertakking; als je de visuele editor wil gebruiken, klik je met je rechtermuisknop op de ontwerpvertakking en kies edit. Zoals de view optie in het rapport kan de visuele
© 2007 Steen Andreasen
23 of 60
MORPHX IT
Rapporten
Samples from MORPHX IT -- steenandreasen.com
editor moeilijk zijn om te gebruiken in complexe rapporten, maar het kan gebruikt worden wanneer je rapporten maakt met een relatief eenvoudige opmaak. Om een ontwerp te maken, biedt de visuele editor dezelfde hoofdkenmerken als de AOT. Via de visuele editor kan je de eigenschappen van een element in een rapport veranderen en controls toevoegen en verwijderen. Om een rapport aan te passen via de visuele editor, positioneer de cursor en klik met je rechtermuisknop op de menu om een element aan te passen, te verwijderen of toe te voegen. Om de eenheid van de liniaal te veranderen, klik je erop met je rechtermuisknop en kies tussen centimeters, inches en chars.
Figuur 6 : de visuele editor
In de praktijk is de visuele editor het best om een overzicht te krijgen van je ontwerp of om de eigenschappen van een specifieke control op te vragen en te veranderen. De visuele editor is relatief traag en de meeste dingen kunnen sneller gedaan worden wanneer je werkt met een rapportboom.
Auto-ontwerp De meest gebruikelijke weg om de opmaak voor je rapporten te maken is door het gebruiken van auto-ontwerp. Wanneer je auto-ontwerp gebruikt, moet je alleen een rapportsjabloon kiezen en kiezen welke velden van de query moeten afgedrukt worden. MorphX zal voor de formattering van je opmaak zorgen. Als je rapport gehele of reële getallen bevat, zal de gebruiker de optie hebben om een optelling tijdens de uitvoering te kiezen. Voor een snelle start met auto-ontwerp klik je met je rechtermuisknop op de vertakking van auto design en kies Generate Specs From Query, een middensectie zal dan gemaakt worden voor elke gegevensbron in de query en de sorteervelden zullen toegevoegd worden als controls aan het ontwerp. Om het visueel voor te stellen, klik met je rechtermuisknop op de auto design vertakking en selecteer view. Probeer MyReport te openen in de visuele editor. Merk
© 2007 Steen Andreasen
24 of 60
MORPHX IT
Rapporten
Samples from MORPHX IT -- steenandreasen.com
op dat de visuele editor de secties toont van de rapportsjabloon, ook al zijn de sjabloonsecties geen deel van de rapportvertakkingen. Dit geeft een nuttig overzicht van het rapport. Om het rapport aan te passen, klik je met je rechtermuisknop en kies edit. In het aanpasscherm zullen alleen de vertakkingen die deel zijn van het rapport, toegankelijk zijn. Autosommen zijn een nuttig kenmerk van auto-ontwerpen; het staat de gebruiker toe, bij het uitvoeren van het rapport, om aan te geven waar er subtotalen moeten berekend worden. In de rapportdialoog kan je zowel afbreekniveaus voor subtotalen instellen voor elk veld of middensectie als het totaal vragen voor het gehele rapport. Vanuit het standpunt van de applicatiegebruiker kan het de belangrijkste reden zijn om auto-ontwerp te gebruiken. Het maakt je rapport meer flexibel en elimineert de meeste inspanningen van het programmeren die anders noodzakelijk zijn om deze sommen te coderen. Voorbeeld 4: Autosom
Elementen gebruikt van het MORPHXIT_Reports project Report, MyReport_Sums Menu item output, MyReport_Sums Breid MyReport uit met totalen voor transactiebedragen. Een subtotaal voor elke klant en een totaal voor alle klanten zal toegevoegd worden. 1. Start met het kopiëren van MyReport en geef het nieuwe rapport de naam “MyReport_Sums”. 2. Omdat een index geen optie heeft om afbreekpunten als de waarde van een indexveld wijzigt, zal de AccountIdx verwijderd worden van de sorteervertakking van de CustTable gegevensbron, en in plaats daarvan zal het AccountNum veld gespecifiëerd worden. Zet de eigenschap Autosum op Yes voor het veld AccountNum. Je hebt nu bepaald dat een subtotaal zal geprint worden elke keer de waarde van een klantenrekening verandert. 3. De velden om op te tellen moeten bepaald worden. In dit voorbeeld zullen alleen de velden AmountMST van de tabel CustTrans gebruikt worden. Zoek de control die AmountMST afdrukt in de CustTrans middensectie; open het eigenschappenblad en zet SumAll op Yes. 4. Maak een nieuw menuoptie voor het rapport en laat het rapport lopen. Voor elke klant zal een subtotaal geprint worden. 5. In dit geval was er alleen een subtotaal afgedrukt. Om een totaal voor het hele rapport toe te voegen, sluit het rapport en ga terug naar de AOT. Ga naar de middensectie van de CustTable en zet de eigenschap GrandTotal op Yes . De
© 2007 Steen Andreasen
25 of 60
MORPHX IT
Rapporten
middensectie CustTrans heeft deze eigenschap niet, alleen de CustTable wel omdat deze de primaire gegevensbron is.
Samples from MORPHX IT -- steenandreasen.com
Stap 2 specifieerde de control die de subtotalen van het rapport bepaalt, maar niet welke velden worden opgeteld. Het ontwerp specifieert welke velden moeten opgeteld worden, hier is dat AmountMST. Dit zijn de enige vereiste instellingen. De gebruiker zal de rest kunnen doen tijdens de uitvoering. Het sorteerveld, gebruikt om af te breken op het subtotaal, en de instellingen voor het algemeen totaal bepalen alleen de standaardinstellingen van het rapport en kunnen veranderd worden tijdens de uitvoering van het rapport. De vertakking AutoDesignSpecs heeft een eigenschap GrandTotal. Deze eigenschap zal een totaal afdrukken voor het rapport met als standaardetiket “SuperGrandTotal”, als de eigenschap op Yes wordt gezet. SuperGrandTotal en het algemeen totaal, ingesteld via de rapportdialoog of de middensectie zullen alitjd hetzelfde resultaat geven. Beiden zullen een totaal voor het hele rapport afdrukken. Dus als de gebruiker de optie heeft om het volledige totaal in stellen via de rapportdialoog moet je de super grand total niet gebruiken. De waarde van een automsom kan beheerd worden via de element.sumControl(). Om de autosom control voor CustTrans.AmounMST in het voorgaande voorbeeld te beheren, moet je code er als volgt uitzien : element.sumControl(identifierstr(CustTrans_AmountMST), element.indent());
Element.sumControl geeft de gesommeerde waarde terug. De eerste parameter is de controlnaam van het gesommeerde veld. De systeemfunctie identifierstr() wordt gebruikt om te verhinderen dat de “best practice check” een waarschuwing geeft. Gebruik steeds element.indent() als tweede parameter om het juiste indentatieniveau te bepalen. Zoals je misschien hebt opgemerkt is er een eigenschap auto-hoofding. Dit wordt op dezelfde manier gebruikt als auto-som. In plaats van totalen te printen, zal een hoofding worden afgedrukt elke keer als een sorteerveld van waarde verspringt. De gebruiker kan de auto-hoofding controleren tijdens de uitvoering , maar als het nodig is, kan je instellen dat de standaard autohoofdingen zichtbaar moeten zijn. Autosommen en autohoofdingen zijn kenmerken die alleen beschikbaar zijn in autoontwerpen. Alle secties die tot nu toe vermeld zijn, starten ofwel door het rapportraamwerk ofwel door de rapportquery. Je zal situaties hebben waar je een rapportsectie manueel zal moeten starten. In die situatie zullen programmeerbare secties die in X++ gemaakt zijn, gebruikt worden. Voorbeeld 5: Programmeerbare sectie
© 2007 Steen Andreasen
26 of 60
MORPHX IT
Rapporten
Elementen gebruikt van MORPHXIT_Reports project Report, MyReport_ProgSec Menu item output, MyReport_ProgSec Je gaat een programmeerbare sectie toevoegen aan MyReport. Voor de eenvoud zal het rapport alleen een tekstcontrol afdrukken.
Samples from MORPHX IT -- steenandreasen.com
1. Start met het kopiëren van MyReport en hernoem het nieuwe rapport “MyReport_ProgSec”. Ga naar de vertakking AutoDesignSpecs, klik met je rechtermuisknop op de vertakking en kies nieuwe ProgrammableSection. 2. Open het eigenschappenblad voor de nieuwe programmeerbare sectie en zoek de eigenschap ControlNumber. Het ControlNumber wordt gebruikt als referentie voor de sectie van X++. Stel het ControlNumber in op 10. 3. Voeg nu een controle toe aan de programmeerbare sectie. Klik met je rechtermuisknop op de programmeerbare sectie en kies New Control om een text control toe te voegen. Ga naar de nieuwe text control, zoek de eigenschap Text en typ “Hoofding voor klanten” in. 4. Definieer nu de uitvoering van de programmeerbare sectie. Ga naar MyReport_ProgSec/Methods, klik met je rechtermuisknop en kies Override Method en selecteer init(). De init() methode moet er als volgt uitzien: Public void init() { super(); element.execute(10); }
5. Maak een menupunt voor het rapport MyReport_ProgSec. Wanneer MyReport_ProgSec wordt uitgevoerd, zal de tekst “Hoofding voor klanten” afgedrukt worden vooraleer de query start. In het voorbeeld heb je de nummer van de programmeerbare sectie in 10 gewijzigd. Het is aangewezen dat je openingen laat in de volgorde van de nummers die je toekent aan de programmeerbare secties. Op deze manier kan je later de logische volgorde bewaren als je een nieuwe programmeerbare sectie moet toevoegen. De uitvoering van een programmeerbare sectie kan opgeroepen worden vanuit X++ waar nodig. Maar als je het gebruikt in combinatie met autosommen, zijn er dingen waarvoor je moet opletten: stel dat je een programmeerbare sectie wil afdrukken voor de middensectie wordt geprint, dan is de logische plaats om je code toe te voegen in de executeSection() methode juist voor super() in de middensectie. Dit zal je programmeerbare sectie afdrukken voor de middensectie wordt afgedrukt, maar de programmeerbare sectie zal ook uitgevoerd worden voor elke autosom. Tijdens de
© 2007 Steen Andreasen
27 of 60
MORPHX IT
Rapporten
uitvoering zal MorphX een autosom als een voetregel behandelen en dit zorgt ervoor dat de middensectie opnieuw zal uitgevoerd worden. De oplossing is om in dit geval de rapportmethodes header() of footer() te gebruiken. Vanaf hier kan je controleren welke middensectie zal worden uitgevoerd. Wanneer een middensectie wordt uitgevoerd, zullen de parameters _tableId en _fieldId een waarde bevatten.
Samples from MORPHX IT -- steenandreasen.com
public void header(ReportSection _headerSection, tableId _tableId, fieldId _fieldId) { if (_tableId == tableNum(custTable) && _fieldId) element.execute(10); super(_headerSection, _tableId, _fieldId); }
Hier wordt de header() methode gebruikt. Er wordt nagekeken of het de middensectie is van de klantentabel die afgedrukt wordt. Is dit het geval, dan wordt de programmeerbare sectie uitgevoerd. Een andere manier om de header() en footer() methode te gebruiken is het toevoegen van een nieuwe pagina na de som als je een batch van verkopers- of klantentransacties wil afdrukken. Opmerking : Programmeerbare secties worden vaak gebruikt om scheidingen in te voegen zoals blanco rijen of lijnen. Dit kan je doen door de eigenschappen van de programmeerbare sectie in te stellen. Je zal een “dummy” of lege control moeten toevoegen aan je programmeerbare sectie, omdat de sectie niet zal afgedrukt worden als je programmeerbare sectie geen controls heeft.
gegenereerd ontwerp Het gebruik van gegenereerde ontwerpen kan op het eerste zicht eenvoudiger lijken dan auto-ontwerpen: je hebt immers meer secties die je kan gebruiken om je rapport te maken en alle secties zijn zichtbaar. Maar gegenereerde ontwerpen zijn meer statisch, het ontwerp is gebaseerd op de instellingen van de query en de eigenschapinstellingen van de ontwerpvertakking. Het nadeel hiervan is het volgende : als je een rapportsjabloon hebt gekozen voor je rapport en later beslis je het rapportsjabloon te wijzigen of een ander sjabloon te kiezen, dan zal je ontwerp niet automatisch aangepast worden. Bovendien heeft de gebruiker niet de mogelijkheid om te kiezen voor samenvatting (summarization) bij het uitvoeren van het rapport. Om het gegenereerd ontwerp van naderbij te bekijken, gebruiken we MyReport voor het aanmaken van een gegenereerd ontwerp. Klik met de rechtermuisknop op de Designs/AutoDesign1 vertakking in MyReport en kies Generate Design. Een nieuwe vertakking met de naam Generated Design is nu aangemaakt onder Designs/AutoDesign1. Als je het gegenereerde ontwerp openvouwt, zal je zien dat een ontwerp gelijkaardig aan het auto-ontwerp is aangemaakt. Het verschil is dat de secties van het rapportsjabloon en de secties voor het berekenen van totalen, zijn toegevoegd.
© 2007 Steen Andreasen
28 of 60
MORPHX IT
Rapporten
Als je een overzicht wil van je rapport bij het gebruik van auto-ontwerpen, kan je handig gebruik maken van de optie voor de creatie van een gegenereerd ontwerp gebaseerd op je auto-ontwerp. Alle secties gebaseerd op je sjablonen en de autosommen worden immers ingevuld.
Samples from MORPHX IT -- steenandreasen.com
Controls in het ontwerp De meest eenvoudige manier om controls toe te voegen aan je ontwerp, is het verslepen van velden of displaymethodes vanaf een gegevensbron of rechtstreeks van een tabel. Als je een basistype veld of displaymethode versleept zoals string, enum, integer, real date & time, zal MorphX automatisch een control van hetzelfde type aanmaken. Controls zoals prompt, shape, sum en field group worden gebruikt voor meer speciale doeleinden en moeten manueel worden toegevoegd. Je kan natuurlijk alle types van control manueel toevoegen, maar het werkt sneller door de controls te verslepen omdat MorphX de control automatisch positioneert en de eigenschappen invult met een referentie naar het betreffende veld of displaymethode.
© 2007 Steen Andreasen
29 of 60
MORPHX IT
Rapporten
Samples from MORPHX IT -- steenandreasen.com
Auto-ontwerpen en gegenereerde ontwerpen hebben dezelfde controls. Voor een overzicht van de beschikbare controles verwijzen we naar Figuur 7 : rapportcontrols. Naam String
Omschrijving Gebruikt voor tekenwaardes (string values). Bij het afdrukken van memovelden, zal de eigenschap DynamicHeight de hoogte van de control aanpassen aan het aantal lijnen dat wordt afgedrukt.
Enum
Gebruikt voor het afdrukken van base enums.
Integer
Gebruikt voor gehele getallen.
Real Date
Gebruikt voor reële getallen. Gebruikt voor het afdrukken van datums. Datums worden geformatteerd op basis van de Windows regional settings.
Time
Gebruikt voor het afdrukken van Tijd. Tijd wordt geformatteerd op basis van de Windows regional settings.
Text
Gebruikt voor het afdrukken van vaste tekstwaarden. Als de tekst een dynamische waarde moet bevatten, worden displaymethodes die een string teruggeven, gebruikt.
Prompt
Prompt voegt tekst toe gevolgd door puntjes en een dubbele punt.
Shape
Tekent een doos. Grootte en positie worden bepaald door de eigenschappen. Kan gebruikt worden voor het opbouwen van de opmaak van een formule.
Bitmap
Gebruikt voor grafische gegevens. Geef het pad op van de bitmap, verwijs naar een container of gebruik resources. Een voorbeeld van het gebruik van een resource als bitmap vind je in het rapport HRMApplicantStatus.
Sum
Gebruikt voor het afdrukken van sommen in gegenereerde ontwerpen. Met auto-ontwerpen kunnen sommen gebruikt worden voor het afdrukken van een som in een programmeerbare sectie. Een voorbeeld van het gebruik in auto-ontwerp vind je in het rapport SalesLinesExtended.
Field group
Gebruikt voor het toevoegen van een field group van de data dictionary. De field group of veldengroep op het rapport wordt automatisch aangepast als de field group in de data dictionary wordt gewijzigd.
Figuur 7 : Rapportcontrols
Bitmap controls zijn een beetje lastig in het gebruik. Er zijn verschillende manieren om een bitmap te configureren. Je kan iconen gebruiken uit de Axapta resources. Ofwel geef je de resource id in het eigenschappenblad in of je maakt een
© 2007 Steen Andreasen
30 of 60
MORPHX IT
Rapporten
displaymethode die de resource id teruggeeft. Voor een overzicht van de resources kan je gebruik maken van het rapport tutorial_Resources. Dit rapport drukt de resource id af en de bijbehorende icon. Je kan ook het pad van de bitmap opgeven of verwijzen naar een bitmap die is opgeslagen in een container. Als je het pad opgeeft, moet je een dubbele backslash gebruiken.
Samples from MORPHX IT -- steenandreasen.com
De somcontrol in gegenereerde ontwerpen wordt gebruikt in voetregelsecties. Bij gebruik in auto-ontwerpen moet de somcontrol in een programmeerbare sectie geplaatst worden. Opmerking: Bij het afdrukken van een rapport kan de infolog melden dat de schaal van het rapport is gewijzigd is om op één pagina te passen. Dit wordt veroorzaakt door teveel kolommen in je ontwerp. Wijzig de eigenschap FitToPage in No op de design vertakking om schaling te voorkomen.
Bij het toevoegen van controls aan je ontwerp, moet je erop toezien dat de controls die verwijzen naar een gegevensbron, opgehaald worden op het moment dat de sectie wordt afgedrukt. In het MyReport voorbeeld kan je geen control van de middensecties CustTable en CustTrans in een paginahoofdingsectie afdrukken : bij het verwerken van de paginahoofding, heeft MorphX immers de informatie geassocieerd met de middensecties, nog niet opgehaald. Hetzelfde geldt voor het toevoegen van een control aan de middensectie CustTable met verwijzing naar een veld van CustTrans. Dit zal eveneens een foutmelding geven omdat CustTable wordt opgehaald voor CustTrans.
1.6
Methodes in een Rapport
Je kan eenvoudige rapporten maken, zoals een lijst van voorraadartikels, zonder dat je X++ code moet schrijven. Hiervoor moet je enkel gebruik maken van de mogelijkheden van de rapportgenerator. Voor moeilijker rapporten die gegevens filteren gebaseerd op een parameter van een oproepend programma of die een bepaalde sortering voorzien, moet je de rapportmethodes overschrijven met je eigen X++ code. Een overzicht van de methodes in een rapport vind je terug in Figuur 8: Rapportmethodes. De querymethodes worden beschreven in het query hoofdstuk, zie verder onder Queries. De rapportsysteemklassen worden vaak gebruikt voor het wijzigen van rapporten bij runtime. Deze klassen zijn de basisrapportcomponenten en zij staan de programmeur toe om alle aspecten van een rapport tijdens de uitvoering te herdefiniëren. Je kan een rapport van nul af opbouwen met behulp van de systeemklassen. Meer informatie over deze systeemklassen vind je terug in het hoofdstuk Klassen.
Naam CallMenuFunction
Parameters MenuFunction _menuFunction
© 2007 Steen Andreasen
Omschrijving Webmethode.
31 of 60
MORPHX IT
Caption
Rapporten
str _reportSpelling, str _reportName, str _designCaption, str _designName
Samples from MORPHX IT -- steenandreasen.com
CreateProgressForm
Dialog
Overschrijft het standaard voortgangsformulier dat getoond wordt als de rapportpagina’s worden aangemaakt. De methode voorziet in de mogelijkheid om je eigen voortgangsformulier te maken. Object _dialog
Fetch
Footer
Dialog() wordt gebruikt als je velden toevoegt aan het rapportdialoogvenster. Het report runbase raamwerk zal het dialoogvenster oproepen als het rapport wordt uitgevoerd. Zie ook bij report KMAction. Deze methode is de motor van het rapport. Fetch() opent de dialoog met de gebruiker, selecteert de records van de databank door het verwerken van de query en stuurt de records naar de printer. Deze methode wordt meestal overschreven als een expressie niet in de query kan worden gespecifieerd. Een voorbeeld hiervan vind je terug in het rapport HRMCourseSkills bij het afdrukken van de detailinformatie.
ReportSection _footerSection, tableId _tableId, fielded _fieldId
GetTarget Header
Gebruikt voor het bepalen van de titel van het rapport. De parameters _reportSpelling en _designCaption bepalen de titels in het Print to Screen venster.
ReportSection _headerSection, tableId _tableId, fieldId _fieldId
Init
Deze methode wordt afgevuurd telkens als een sectie in het ontwerp wordt uitgevoerd. Gezien auto-som geen deel is van het ontwerp, geeft dit de mogelijkheid om code uit te voeren voor of na het afdrukken van de auto-som.
Geeft het geselecteerde printmedium terug. Deze methode wordt afgevuurd telkens als een sectie in het ontwerp wordt uitgevoerd. Gezien auto-som geen deel is van het ontwerp, geeft dit de mogelijkheid om code uit te voeren voor of na het afdrukken van de aut-som. Deze methode wordt als eerste
© 2007 Steen Andreasen
32 of 60
MORPHX IT
Rapporten
opgeroepen om het rapport te initializeren. Entiteiten die in het rapport worden gebruikt, worden hier geïnitializeerd. Een voorbeeld daarvan vind je terug in het rapport salesFreightSlip.
Samples from MORPHX IT -- steenandreasen.com
New
anytype _argsOrReportOrContainer, str _designName, boolean _isWebReport=FALSE
Gebruikt om een reportRun object te initializeren. Dit wordt normaal niet gedaan door de rapportgenerator. Meestal gebruik je deze methode als een rapport wordt geïnitialiseerd vanuit X++.
Pack
Deze methode wordt gebruikt voor het opslaan van de laatste waardes. Ze wordt gebruikt in samenhang met unpack(), die de laatst opgeslagen waarde ophaalt. Maar unpack() is geen basismethode. Als een nieuw dialoogveld wordt toegevoegd, wordt pack() overschreven om de waardes van het dialoogvenster te bewaren. Een voorbeeld vind je terug in het rapport KMAction.
PageFormatting
Deze methode wordt niet meer gebruikt. Vanaf versie 3.0 wordt de method PrintJobSetttings.PageFormatting() in plaats daarvan gebruikt.
Print
Print() geeft het aantal af te drukken bladzijden weer. Deze method kan gebruikt worden om na te gaan of er bladzijden afgedrukt moeten worden. Zie in het rapport projTimeSheetEmpl.
PrinterSettings
int _showWhat=-1
Gebruikt om de verschillende delen van de printerdialoog te activeren. Deze methode wordt alleen opgeroepen als het report runbase raamwerk niet actief is, maar in plaats daarvan opgeroepen wordt vanuit prompt() methode.
ProgressInfo
int _pageNo, int _lineNo boolean _enableCopy=TRUE, boolean _enablePages=TRUE, boolean _enableDevice=TRUE, boolean _enableProperties=TRUE, boolean _enablePrintTo=TRUE
ProgressInfo wordt opgeroepen voor iedere lijn die afgedrukt wordt. Voor versie 3.0 handelde prompt() de rapportdialoog af. Voortaan wordt de dialog() methode gebruikt. De methode kan niet gebruikt worden in combinatie met het report runbase raamwerk aangezien het raamwerk alle
Prompt
© 2007 Steen Andreasen
33 of 60
MORPHX IT
Rapporten
Samples from MORPHX IT -- steenandreasen.com
instellingen zal overschrijven. In plaats daarvan moet je de klasse PrintJobSettings gebruiken.
Run
Run() wordt opgeroepen als OK knop wordt aangeklikt in het dialoogvenster. Run() voert de volgende stappen uit : • Als er geen gegenereerd ontwerp bestaat, wordt er een ontwerp aangemaakt op basis van auto design. • Call fetch() • Call print() De methode kan gebruikt worden voor het toevoegen van bereiken (ranges) aan de query gebaseerd op Based On settings in de dialoog. Zie verder in het rapport ReqPO.
Send
Send() is aanverwant aan fetch(). Fetch() gaat door de query records, and send() stuurt de records naar het ontwerp. De methode kan overschreven worden om te bepalen of een record al dan niet afgedrukt moet worden. Een voorbeeld vind je terug in het rapport CustTransList.
SetTarget
PrintMedium _target
Stelt het doelmedium van het rapport in.
ShowMenuFunction
MenuFunction _menuFunction
Webmethode.
ShowMenuReference
WebMenu _menuReference
Webmethode.
Title
str _title=""
Wordt niet vaak meer gebruikt. Het kan de titelbalk van een schermafdruk overschrijven als het wordt uitgevoerd door fetch().
ExecuteSection
Iedere sectie in het ontwerp heeft de executeSection methode, die gebruikt wordt om de sectie af te drukken. De methode kan gebruikt worden om te bepalen of de sectie al dan niet moet afgedrukt worden. Een voorbeeld vind je terug in het rapport CustCollectionJour.
© 2007 Steen Andreasen
34 of 60
MORPHX IT
Rapporten
Figuur 7 : Rapportmethodes
Samples from MORPHX IT -- steenandreasen.com
De vorige onderdelen van dit hoofdstuk legden de nadruk op de individuele elementen die een rapport uitmaken. Het wordt nu tijd om na te kijken hoe je X++ kan gebruiken om je rapporten te wijzigen.
© 2007 Steen Andreasen
35 of 60
MORPHX IT
Rapporten
Report Runbase Raamwerk
Samples from MORPHX IT -- steenandreasen.com
Je hebt je misschien afgevraagd waarom je soms verschillende dialoogvensters krijgt bij het uitvoeren van rapporten binnen Axapta. Als een rapport wordt uitgevoerd vanuit de AOT, krijg je eerst de querydialoog en daarna de printerdialoog. Als een rapport wordt uitgevoerd vanaf een menuoptie, krijg je maar één dialoogvenster te zien. In versie 3.0 van Axapta is de nieuwe runbase class runbaseReportStd ingevoerd. Als een rapport wordt opgeroepen vanaf een menuoptie, dan wordt RunbaseReportStd opgeroepen vanaf de klasse SysReportRun. Dit Report Runbase Raamwerk is vaak een bron van verwarring bij nieuwe Axaptaprogrammeurs. Het is belangrijk te begrijpen dat een rapport kan opgeroepen worden op vier manieren : o direct vanuit de rapportvertakking (reports node) in de AOT; o via een menuoptie hetzij op een gebruikersmenu hetzij in de AOT; o opgeroepen door een klasse die erft van runBaseReport; o opgeroepen vanuit X++.
De klasse RunbaseReportStd wordt opgeroepen door het Report Runbase Raamwerk alleen als je rapport niet wordt opgeroepen door een klasse die erft van de RunBaseReport klasse. Maar als een rapport wordt uitgevoerd vanuit de Reports vertakking, wordt het Runbase Report Raamwerk niet uitgevoerd, en worden de twee dialoogvensters getoond. Opmerking: Rapporten worden vaak gebruikt om de gegevensintegriteit van het systeem te controleren. Hoewel het nuttig kan zijn om rapporten de gegevens te laten aanpassen, is het toch aangewezen om rapporten niet naar de databank te laten schrijven. Als je rapport records moet wijzigen of toevoegen, kan je dit best doen door een klasse te schrijven die de gegevensmanipulatie uitvoert. Deze klasse moet dan opgeroepen worden door een klasse die erft van RunBaseReport .
Het is aangewezen om altijd een menuoptie te maken dat je rapport uitvoert; zo krijg je hetzelfde dialoogvenster te zien dat getoond wordt aan de gebruikers als zij een rapport lanceren vanuit één van hun menu’s. Onthoud dat een rapport uitgevoerd door een klasse, altijd moet erven van de klasse RunBaseReport. De klasse RunbaseReportStd wordt enkel gebruikt door het runbase raamwerk. Meer informatie over de runbase klassen vind je terug in het Klassen hoofdstuk.
Figuur 8 : Runbase rapportklassen
© 2007 Steen Andreasen
36 of 60
MORPHX IT
Rapporten
Samples from MORPHX IT -- steenandreasen.com
Bij de creatie van een rapport in vorige versies van Axapta, was het de gewoonte dat een rapport moest opgeroepen worden vanuit een geërfde RunBaseReport klasse. Dit werd gedaan om de twee dialoogvensters, die hierboven vermeld werden, op te vangen. Zodoende was het mogelijk om het rapport in stapelverwerking (batch) uit te voeren. Dit zorgde ook voor een betere performantie omdat de klasse uitgevoerd kon worden op de server. Met de invoering van de RunBaseReportStd klasse, zouden enkel rappporten met een zware databankbelasting mogen erven van de RunBaseReport klasse.
Voorbeeld 6: Report runbase
Elementen gebruikt van het MORPHXIT_Reports project Class, SalesReport_DailyEntries Report, SalesDailyEntries Menu item output, SalesReport_DailyEntries Om het Report Runbase raamwerk te verkennen, navigeer je naar de Classes vertakking en zoek de klasse SalesReport_DailyEntries op. Deze klasse erft van de RunBaseReport klasse en wordt daarom gebruikt om een rapport op te roepen. Dit is een gebruikelijke rapportklasse met in de naam een prefix die verwijst naar de module. Je zal veel gelijkaardige rapportklassen zien wanneer je de toepassingsklassen doorloopt. SalesReport_DailyEntries roept het rapport SalesDailyEntries op. In feite is deze klasse niet nodig sinds de introductie van Axapta 3.0, aangezien de logica van de klasse afgehandeld kan worden door de klasse RunBaseReportStd. Niettemin is de klasse SalesReport_DailyEntries een goed voorbeeld van hoe je een rapportklasse moet bouwen. De klasse heeft de volgende methodes: public identifiername lastValueElementName() { return reportstr(SalesDailyEntries); }
Hier wordt de naam van het rapport gespecifieerd zodat de method overschreven (overridden) moet worden. De functie reportstr() garandeert dat de rapportnaam die je ingeeft een geldige rapportnaam is. client server public static ClassDescription description() { return "@SYS77491"; }
Deze optionele method definieert de titelnaam van de rapportdialoog. static void main(Args args) { SalesReport_DailyEntries
salesReport_DailyEntries;
© 2007 Steen Andreasen
37 of 60
MORPHX IT
Rapporten
; salesReport_DailyEntries = new salesReport_DailyEntries(); if (salesReport_DailyEntries.prompt()) { salesReport_DailyEntries.run(); }
Samples from MORPHX IT -- steenandreasen.com
}
De main() methode is een statische methode die de klasse initialiseert. Hierdoor kan je de klasse oproepen via een menuoptie. Het systeem kijkt na of het dialoogvenster wordt opgeroepen. Als OK wordt aangeklikt in het dialoogvenster, wordt het rapport uitgevoerd. Om de klasse in het rapport te kunnen gebruiken, moet een variabele van de SalesReport_DailyEntries klasse gedeclareerd worden in de klassedeclaratie voor het SalesDailyEntries rapport. public class ReportRun extends ObjectRun { SalesReport_DailyEntries salesReport_DailyEntries; }
public void init() { super(); salesReport_DailyEntries = element.args().caller(); if (!salesReport_DailyEntries) { throw error(Error::missingRecord(funcName())); } }
Een object van de SalesReport_DailyEntries klasse wordt doorgegeven via args().caller() aan het rapport. Het systeem kijkt na of het rapport wordt aangeroepen door een klasse. Dit wordt gedaan om te voorkomen dat het rapport rechtstreeks wordt uitgevoerd vanuit X++ of de AOT. In dit voorbeeld zou het niet uitmaken op welke manier het rapport wordt aangeroepen, maar in sommige gevallen kan de klasse de af te drukken data filteren. Het rechtstreeks aanroepen van dit rapport leidt dan tot onverwachte resultaten. Zoals eerder vermeld, is de klasse SalesReport_DailyEntries niet nodig gezien de interne klasse RunBaseReportStd de logica zal afhandelen die nodig is om de query/print dialoog weer te geven en automatisch de stapelverwerking of batch te vergemakkelijken. Om het rapport te veranderen zodat het niet de SalesReport_DailyEntries klasse gebruikt, moet je de init() methode van het rapport aanpassen. In dit geval kan je eenvoudig init() verwijderen. De menuoptie verwijst nog altijd naar de klasse, dus moet je naar de output menuoptie
© 2007 Steen Andreasen
38 of 60
MORPHX IT
Rapporten
SalesReport_DailyEntries gaan en de eigenschappen veranderen voor de menuoptie zodat het niet meer de klasse maar het rapport oproept. Wanneer het rapport rechtsstreeks wordt uitgevoerd vanuit de AOT, zal je hetzelfde resultaat krijgen alsof je de klasse SalesReport_DailyEntries gebruikt. Als je het rapport uitvoert via een menu , zal je het geconsolideerd dialoogscherm zien.
Samples from MORPHX IT -- steenandreasen.com
Voorbeeld 7: Rapportdialoog
Elements used from MorphxIt_Report project Report, SalesDailyEntries Menu item output, SalesDailyEntries_Without_Class Nu is het tijd om meer kenmerken toe te voegen aan het SalesDailyEntries rapport. We beginnen met een dialoogveld dat aangeeft of de details moeten afgedrukt worden. De waarde van het nieuwe veld wordt opgeslagen zodat de laatste waarde wordt opgeladen wanneer het rapport wordt uitgevoerd. Het volgende moet toegevoegd worden voor de klassedeclaratie (Class Declaration) van het rapport: public class ReportRun extends ObjectRun { DialogField dialogPrintDetails; Boolean
printDetails;
#DEFINE.CurrentVersion(1) #LOCALMACRO.CurrentList printDetails #ENDMACRO }
DialogPrintDetails is een variabele van de klasse DialogField. Dit wordt gebruikt voor het nieuw dialoogveld dat de gebruiker ziet wanneer het rapport wordt uitgevoerd. De variabele printDetails bewaart de waarde van het dialoogveld. De macro CurrentList is een lijst van variabelen die bewaard worden. De lijst zal doorgaans een variabele voor elk veld in het dialoogscherm bevatten. Om er meer toe te voegen, moet je de variabelen scheiden door een komma. CurrentVersion houdt een spoor bij van de opgeslagen versie van CurrentList. Axapta laat toe dat je de parameters van batchjobs en rapporten bewaart van elke uitvoering. Het systeem zal de parameters vooraf opladen die de gebruiker het laatst gebruikt heeft om deze job te laten lopen. Als er veranderingen worden gemaakt aan de CurrentList, dan moet CurrentVersion met één stijgen. Je kan ook de gebruiksgegevens of usage data resetten. Hierdoor worden de waarden van vorige jobuitvoeringen terug opgehaald samen met de selectiebereiken die door de gebruiker werden opgegeven.
public Object dialog(DialogRunbase _dialog = null) {
© 2007 Steen Andreasen
39 of 60
MORPHX IT
Rapporten
DialogRunBase dialog; ; dialog = super(_dialog); dialogPrintDetails = dialog.addFieldValue(typeId(NoYesId), printDetails, "Print details", "Print additional information for the transactions."); return dialog;
Samples from MORPHX IT -- steenandreasen.com
}
De dialoog wordt geïnitieerd door super() en bevat de standaarddialoog voor het rapport. Het enige wat je moet doen, is een nieuw veld toevoegen voor de afdrukdetails. Het nieuwe veld zal automatisch in een standaardveldengroep met de naam Parameters gezet worden.
public boolean getFromDialog() { boolean ret; printDetails ret
= dialogPrintDetails.value(); = true;
return ret; }
Wanneer je OK klikt in het dialoogvenster, roept het systeem de getFromDialog methode op. De waarde van het nieuwe dialoogveld wordt bewaard in de printDetails variabele. public container pack() { return [#CurrentVersion, #CurrentList]; }
Zoals hier getoond, wordt de laatste waarde van het nieuwe dialoogveld bewaard. Pack() bewaart de huidige waarde van CurrentVersion en CurrentList gespecifieerd in de ClassDeclaration. public boolean unpack(container packedClass) { boolean ret; Integer version = conPeek(packedClass,1); switch (version) { case #CurrentVersion: [version, #CurrentList] = packedClass; ret = true; break; default: ret = false; }
© 2007 Steen Andreasen
40 of 60
MORPHX IT
Rapporten
return ret; }
Samples from MORPHX IT -- steenandreasen.com
Deze method haalt de laatst bewaarde waarde van CurrentVersion en CurrentList op. public void run() { if (printDetails) { SalesLine_Name.visible(true); } else { SalesLine_Name.visible(false); } super(); }
Tot slot moeten we nakijken of details al dan niet afgedrukt moeten worden. In dit voorbeeld bepaal je zo of de naam SalesLine afgedrukt wordt of niet. Alle rapportcontrols moeten gedeclareerd worden voor ze gebruikt kunnen worden in X++. Je kan de eigenschappen veranderen tijdens de uitvoering. Een rapportcontrol wordt gedeclareerd door de eigenschap AutoDeclaration op Yes te zetten. In bovenstaand voorbeeld moet je eerst de AutoDeclaration eigenschap van de SalesLine_Name control op Yes zetten. In het rapportdialoog voorbeeld hebben we de methodes pack() en unpack() gebruikt. Deze methodes worden gebruikt om de laatste waarde van een dialoogvenster te bewaren en om de gebruikersparameters, opgegeven in de dialoog, over te brengen van client naar server, wanneer het rapport wordt uitgevoerd in batch mode. Als je nood hebt aan deze functionaliteit voor je dialoog, moet je de twee methodes van een bestaande klasse kopiëren en CurrentVersion en CurrentList toevoegen aan de ClassDeclaration.
Dynamische Rapporten De mogelijkheid om veranderingen te maken tijdens de uitvoering is erg nuttig, omdat het de optie voorziet om eigenschappen te veranderen of nieuwe elementen toe te voegen als je het rapport uitvoert. Hierdoor kan je één rapport maken in plaats van verschillende rapporten met gelijkaardige ontwerpen. Het SalesInvoice rapport is hiervan een voorbeeld. Afhankelijk van de verkoopsparameters wordt SalesInvoice afgedrukt met verschillende controls. Omdat Axapta een meertalig system is, moet het mogelijk zijn om rapporten in verschillende talen af te drukken. In de meeste gevallen zal Axapta dit correct behandelen zonder de noodzaak voor extra programmatie. Standaard zal het rapport afgedrukt worden in de taal van de Axaptagebruiker. Hoewel uitzonderingen kunnen voorkomen in bepaalde omstandigheden. Stel je voor dat een verkoopsfacturenrapport moet afgedrukt worden in de voorkeurstaal van de klant. Dit
© 2007 Steen Andreasen
41 of 60
MORPHX IT
Rapporten
doe je door de Language eigenschap op de ReportDesign vertakking in te stellen. Je kan de eigenschap een vaste waarde geven, maar de beste manier is de taal instellen vanuit X++. Hier wordt myTable.languageId gebruikt om de taal in te stellen voor het ontwerp: public void init() { super();
Samples from MORPHX IT -- steenandreasen.com
element.design().laguageId(myTable.languageId); }
Het sleutelwoord element wordt gebruikt in het rapport als referentie voor alle rapportobjecten. Hier verwijst het element naar de method languageId() in het objectontwerp. Op deze manier krijg je greep op elk element van het rapport. Als je element gebruikt als verwijzing naar een rapportobject, kan het resultaat een lang pad opleveren, zoals je hieronder ziet : element.design().sectionGroup(tablenum(CustInterestTrans)).section(ReportBlockType::BODY).contr olName('custInterestTrans_custInterestJourInterestAmount');
De bovenstaande lijn komt uit de init() methode in het rapport CustInterestNote. Een betere manier om dit soort problemen af te handelen is de eigenschap AutoDeclaration te gebruiken. Wanneer je de eigenschap AutoDeclaration gebruikt, declareer je eigenlijk een instantie van een systeemklasse. SalesLine_Name in het rapportdialoogvoorbeeld is een instantie van de systeemklasse ReportStringControl. Noot: Wanneer je door de standaardrapporten in de AOT bladert, kan je rapporten zien waar systeemklassen voor secties en controls in de code gedeclareerd zijn, en niet via de eigenschap AutoDeclaration. Dit is omdat de AutoDeclaration eigenschap voor rapportcontrols pas is toegevoegd in v3.0. van Axapta.
De systeemklassen zijn bedoeld om gebruikt te worden wanneer je nood hebt aan elementen zoals secties en controls in een rapport tijdens de uitvoering. Zo kan je bijvoorbeeld beslissen om bijkomend gedetailleerde informatie af te drukken of zelfs een extra sectie van een andere tabel af te drukken, afhankelijk van waar je rapport wordt opgeroepen, In plaats van systeemklassen te gebruiken om controls tijdens de uitvoering te creëren, kan je ook alle secties en controls toevoegen die nodig zijn voor de verschillende combinaties en dan de Visible eigenschap gebruiken om te bepalen of de control al dan niet moet getoond worden. In sommige gevallen krijgt het gebruik van de systeemklassen de voorkeur. Als je de systeemklassen gebruikt voor het maken van controls, kan je wachten tot de uitvoering om te beslissen welk type control nodig is. Dit is zeker handig als de controls die je moet toevoegen, afhankelijk zijn van de gebruikersinstellingen of parameters. Voorbeeld 8: Rapportsysteemklassen
© 2007 Steen Andreasen
42 of 60
MORPHX IT
Rapporten
Samples from MORPHX IT -- steenandreasen.com
Elements used from MorphxIt_Report project Report, MyReport_SystemClasses Menu item output, MyReport_SystemClasses Om de rapport systeemklasses uit te proberen, maak je een nieuw rapport zoals getoond wordt in figuur 10: test van de rapport systeemklasses. Tijdens de looptijd zal het rapport een midden sectie maken voor de CustTable. De midden sectie zal 10 controles hebben, die de waarde van de eerste 10 velden van de CustTable zullen printen. De table CustTable wordt toegevoegd als databron en de vertakking voor het auto ontwerp is al gemaakt.
Figure 9: Test of report system classes
Wijzig de init() methode van het rapport via overloading zoals hieronder getoond. Andere code is niet nodig.
public void init() { ReportSection DictTable DictField Counter
reportSection; dictTable; dictField; fieldCounter;
super(); reportSection = element.design().autoDesignSpecs().addSection(ReportBlockType::Body); reportSection.table(tableNum(custTable)); dictTable = new DictTable(tableNum(custTable)); while (fieldCounter < 10) { fieldCounter++; dictField = new DictField(dictTable.id(), dictTable.fieldCnt2Id(fieldCounter)); reportSection.addControl(dictTable.id(), dictTable.fieldCnt2Id(fieldCounter)); } }
© 2007 Steen Andreasen
43 of 60
MORPHX IT
Rapporten
Samples from MORPHX IT -- steenandreasen.com
De instantie van de systeemklassen reportSection en reportControl wordt gebruikt om de middensectie of body section en zijn geassocieerde elementen aan te maken. Een nieuwe rapportsectie van het type Body Section wordt toegevoegd aan de AutoDesignSpecs vertakking en gespecificeerd om de tabel CustTable te gebruiken. DictTable is ook een instantie van een systeemklasse. DictTable gebruikt men vaak wanneer men een verwijzing nodig heeft naar een tabel of veldeigenschappen. Zo is ook DictField een systeemklasse die een verwijzing voorziet naar een specifiek veld voor een specifieke tabel. In dit voorbeeld gebruiken we dictField en DictTable om de eerste 10 velden van de tabel CustTable te overlopen. Voor ieder veld zal een control aan de middensectie toegevoegd worden. MorphX zorgt ervoor dat de correcte controltypes toegevoegd worden en past deze automatisch aan, zodat bij het openen van het rapport, de eerste 10 velden van de CustTable op één lijn afgedrukt worden. Wanneer je een module schrijft waarbij de gebruiker de optie heeft om zijn/haar eigen rapportopmaak te bepalen, dan bieden systeemklassen hier een antwoord op.
Gemeenschappelijke rapportmethoden Bij het wijzigen van een rapport, overschrijf je bestaande methodes, of voeg je nieuwe methodes toe die opgeroepen worden vanuit de overschreven methodes. De volgende methodes worden in onderstaande volgorde uitgevoerd wanneer een rapport geladen wordt: init() ► dialog() ► run() ► fetch() ► send() ► print() Init() en dialog() worden opgeroepen bij het laden van het rapport. Run() wordt opgeroepen bij het klikken op de OK knop van het dialoogvenster. Fetch() doorloopt het resultaat van de query en voor ieder gevonden record wordt de send() methode uitgevoerd. Uiteindelijk wordt de print() methode opgeroepen. Deze methodes zijn de belangrijkste van een rapport en zijn diegene die je het meest zal overschrijven. Typische aanpassingen zijn het toevoegen van controls aan het dialoogvenster, het manipuleren van de query output alvorens deze af te drukken, of het aanpassen van de output bestemd voor de middensectie van het rapport door een programmeerbare sectie uit te voeren. De bovenvermelde volgorde van uitvoering, wordt gebruikt wanneer het report runbase raamwerk actief is. Wanneer je het rapport rechtstreeks vanuit de AOT oproept, zonder gebruik te maken van een menuoptie , dan wordt een enigszins andere volgorde van uitvoering gehanteerd, zoals hieronder afgebeeld: init() ► run() ► prompt() ► fetch() ► send() ► print()
© 2007 Steen Andreasen
44 of 60
MORPHX IT
Rapporten
Merk op dat dialog() niet zal opgeroepen worden. RunBaseReportStd beheert de dialoogvensters van het rapport en wanneer het “runbase raamwerk niet actief is” wordt prompt()gebruikt. Voorbeeld 9: fetch() overschrijven
Samples from MORPHX IT -- steenandreasen.com
Elementen gebruikt van het MORPHXIT_Reports project Rapport, MyReport_Fetch Menu item output, MyReport_Fetch Een nieuw rapport wordt aangemaakt voor het afdrukken van transacties voor iedere klant, gefilterd van n-dagen geleden tot de huidige systeemdatum. Het rapport heeft een dialoogvenster waarop het aantal dagen door de gebruiker kan opgegeven worden. Start met het voorbeeld MyReport te dupliceren. Het resultaat zal eruit zien als in Figuur 11: Rapport om fetch() te overschrijven. Het voorbeeld legt de nadruk op het overschrijven van methodes.
Figuur 10,: Rapport om fetch() te overschrijven
© 2007 Steen Andreasen
45 of 60
MORPHX IT
Rapporten
Nu je de query en het ontwerp van het rapport hebt aangemaakt, kun je starten met het creëren van methodes voor het rapport. public class ReportRun extends ObjectRun { DialogField dialogDaysBack; NumberOf daysBack; }
Samples from MORPHX IT -- steenandreasen.com
De variabele dialogDaysBack is nodig voor het dialoogvenster. De waarde zal toegekend worden aan de variabele daysBack. public Object dialog(Object _dialog) { DialogRunBase dialog; ; dialog dialogDaysBack days",
= super(_dialog); = dialog.addFieldValue(typeId(NumberOf), daysBack, "Number of "Number of days back to be printed.");
return dialog; }
Een veld wordt toegevoegd aan het dialoogvenster om het aantal n-1 dagen in te geven. public boolean getFromDialog() { boolean ret; daysBack = dialogDaysBack.value(); ret = true; return ret; }
De variabele daysBack wordt gebruikt om de waarde van het dialoogvenster te bewaren. public boolean fetch() { QueryRun qr; QueryBuildRange Boolean ret;
rangeTransDate;
qr = new QueryRun(element); rangeTransDate = element.query().dataSourceTable(tablenum(CustTrans)).addRange(fieldnum(CustTrans, transDate)); rangeTransDate.value(queryRange(systemdateGet()-daysBack, systemDateGet())); rangeTransDate.status(RangeStatus::LOCKED); element.design().caption(strFmt("%1, %2", element.design().caption(), rangeTransDate.value()));
© 2007 Steen Andreasen
46 of 60
MORPHX IT
Rapporten
Samples from MORPHX IT -- steenandreasen.com
if (qr.prompt() && element.prompt()) { while (qr.next()) { custTable = qr.get(tableNum(CustTable)); custTrans = qr.get(tableNum(CustTrans)); if (!custTable) { ret = false; break; } if (qr.changed(tableNum(custTable))) element.send(custTable, 1); if (qr.changed(tableNum(custTrans))) element.send(custTrans, 2); } ret = true; } else ret = false; return ret; }
De variabele daysBack bevat de waarde die door de gebruiker werd ingegeven. Je moet een bereik toevoegen aan de query om te filteren op de transactiedatums tussen n-1 dagen en de systeemdatum. Een QueryRun object, qr genoemd, wordt geïnitialiseerd met de actieve query van het rapport, waarna een bereik word toegevoegd aan de qr voor de transactiedatums. Het bereik is geblokkeerd, waardoor de gebruiker deze niet kan wijzigen. Het bereik van de transactiedatums wordt toegevoegd aan de titel van het rapport. Op dit punt wordt de query doorlopen. De standaardlus van de query en de afdruk van het record wordt afgehandeld door de oproep van de super() methode in de fetch() methode. Vooraleer de query te doorlopen, wordt gecontroleerd of de dialoogvensters van de query en het rapport werden opgeroepen. Dit zijn de twee dialoogvensters die verpakt zitten in de RunBaseReportStd. Binnen iedere lus worden de tabellen CustTable en CustTrans geïnitialiseerd. Wanneer geen records gevonden worden, stopt de lus en wordt het rapport beëindigd. Wanneer een gegevensbron werd gewijzigd, en een record is gevonden, zal het rapport worden afgedrukt via de send() methode. Bemerk de tweede parameter in de send() methode. De tweede parameter definieert het niveau van het record. CustTable is op het eerste niveau van de query en CustTrans is op het tweede niveau. Dit is belangrijk, omdat autosommen niet afgedrukt worden, indien de niveau’s niet correct worden ingesteld, In het fetch voorbeeld werd de query van het rapport doorlopen. Dit kon ook via het WHILE commando, SELECT commando, of een combinatie van beide. Voor ieder
© 2007 Steen Andreasen
47 of 60
MORPHX IT
Rapporten
record doorlopen in de query, wil je misschien een bijbehorend record selecteren van een tabel die niet in de query zit, of een tijdelijke tabel opbouwen om af te drukken. Voor iedere record dat moet afgedrukt worden, moet je enkel de send() methode oproepen.
Samples from MORPHX IT -- steenandreasen.com
Wanneer je de af te drukken records wil valideren, dien je de send() methode te overschrijven in plaats van de fetch() methode: public boolean send(Common _cursor, int _level=1, boolean _triggerOffBody=TRUE, boolean _newPageBeforeBody=FALSE) { boolean ret; CustTrans custTrans; if (_cursor.tableId == custTrans.tableId) { custTrans = _cursor; } if (custTrans.transDate == systemDateGet()) { ret = super(_cursor, _level, _triggerOffBody, _newPageBeforeBody); } return ret; }
De send() methode krijgt het af te drukken record door als een parameter. Het enige wat je moet doen, is de betreffende tabel initialiseren. In dit geval is de tabel CustTrans geinitialiseerd als de cursor een CustTrans record is. Enkel klanttransacties waarvoor de transactiedatum gelijk is aan de systeemdatum, zullen afgedrukt worden. Het toevoegen van querywaarden kan vaak door simpelweg de init() methode te overschrijven, wat stukken gemakkelijker is gezien slechts enkel een aantal lijnen code nodig zijn. Het bereik toegevoegd aan de query in het fetch voorbeeld was afhankelijk van de gebruikerinteractie. De wijziging was nodig nadat het dialoogvenster werd gesloten, dus moest de code genoteerd worden in de fetch() methode. Alvorens een bereik aan de query toe te voegen, moet je nakijken of de query niet al een bereik voor het veld heeft, door gebruik te maken van de QueryBuildRange.findRange() methode. Indien twee bereiken voor hetzelfde veld werden gecreërd, zullen de bereiken samengesmolten worden (ge-“AND-ed”) wat onverwachte resultaten kan opleveren. De gebruiker heeft de mogelijkheid in het rapportdialoogvenster om het printbereik voor de query in te geven wanneer die naar de printer gestuurd worden. Zowel bereiken toegevoegd aan de query voor de gegevensbron, als bereiken toegevoegd met X++ code zullen afgedrukt worden. Maar als de fetch() methode is overschreven, zal deze optie uitgeschakeld zijn.
© 2007 Steen Andreasen
48 of 60
MORPHX IT
1.7
Rapporten
Speciale Rapporten
Tot nog toe richtte dit hoofdstuk zich op de basisstappen voor het creeëren van rapporten. Om een idee te krijgen van de mogelijkheden binnen de MorphX taal, zal dit gedeelte via een aantal voorbeelden aantonen hoe je kan omgaan met speciale rapporten en hoe je die rapporten gebruiksvriendelijker kan maken.
Samples from MORPHX IT -- steenandreasen.com
Een rapport uitvoeren vanuit X++ Rapporten worden normaal opgestart vanuit een menuoptie, opgeroepen via het hoofdmenu of via een formulier. Soms is het nodig om een rapport direct uit X++ code op te roepen, omdat de gebruiker het rapport niet rechtstreeks via een menuoptie mag oproepen. Elementen gebruikt van MORPHXIT_Reports project Job, Reports_ExecuteReport Job, Reports_ExecuteReportSilent static void Reports_ExecuteReport(Args _args) { Args args; SysReportRun reportRun; ; args = new Args(); reportRun = new menuFunction(menuItemOutputStr(MyReport), MenuItemType::Output).create(args); reportRun.run(); }
De job toont hoe MyReport opgeroepen wordt vanuit X++. Merk op dat de applicatieklasse SysReportRun gebruikt wordt. SysReportRun erft over van de systeemklasse ReportRun. Het voordeel van het gebruik van de applicatieklasse is de mogelijkheid om de code in de SysReportRun klasse te overschrijven. Je kan ook je eigen afgeleide klasse maken die overerft van de SysReportRun klasse. Dit is handig als je voor een bepaalde reeks rapporten een aantal controles moet uitvoeren bij het afdrukken, in plaats van die voor ieder rapport apart te voorzien. MyReport wordt opgeroepen door gebruik te maken van een menuoptie, die het runbase rapportraamwerk oproept en het correcte dialoogvenster laadt voor het rapport. Indien je geen gebruik wil maken van het runbase raamwerk of je wil het rapport afdrukken zonder gebruikersinteractie, dien je het rapport op te roepen zonder gebruik te maken van het runbase rapport raamwerk. static void ExecuteReportSilent(Args _args) { Args args; SysReportRun reportRun; ;
© 2007 Steen Andreasen
49 of 60
MORPHX IT
Rapporten
args = new Args(); args.name(reportstr(MyReport)); reportRun = classFactory.reportRunClass(args); reportRun.query().interactive(false); reportRun.report().interactive(false); reportRun.setTarget(PrintMedium::Printer); reportRun.run();
Samples from MORPHX IT -- steenandreasen.com
}
In deze job voeren we het rapport uit, zonder gebruik te maken van de menuoptie en dus wordt het runbase rapportraamwerk niet gebruikt. Het voorbeeld drukt het rapport onmiddelijk af op de standaardprinter zonder interactie van de gebruiker, omdat zowel de query als het rapportdialoogvenster op inactief geplaatst zijn. Wanneer de methode dialog() in je rapport overschreven wordt, moet je er zeker van zijn dat dit geen problemen met zich meebrengt, omdat dialog()niet uitgevoerd zal worden. Indien je rapport uit meer dan één ontwerp bestaat, moet je aanduiden welk ontwerp je wenst te gebruiken. Indien deze niet werd aangeduid, of indien een foutieve waarde werd ingesteld, zal het eerste ontwerp op het rapport toegepast worden. reportRun.design("MyDesign"); reportRun.run();
© 2007 Steen Andreasen
50 of 60
MORPHX IT
Rapporten
Samples from MORPHX IT -- steenandreasen.com
Gebruik van tijdelijke tabellen Indien een speciale sorteermethode nodig is, of je wenst data vanuit meerdere tabellen te selecteren die niet met elkaar gekoppeld kunnen worden, dan kan het gebruik van tijdelijke tabellen hier een oplossing voor bieden. Het gebruik van tijdelijke tabellen is vrij simpel. De tijdelijke tabel moet opgevuld en doorgegeven worden naar het rapport. Er kunnen performantieproblemen optreden bij het gebruik van tijdelijke tabellen, gezien het rapport 2 maal zal uitgevoerd worden. De eerste maal zal de tijdelijke tabel opgebouwd worden. Vervolgens zal deze overlopen worden in het rapport. Het gebruik van tijdelijke tabellen zou niet je eerste keuze mogen zijn. Het is beter om het ontwerp van je rapport opnieuw te analyseren. Voor meer informatie over tijdelijke tabellen, zie het hoofdstuk : Data Dictionary. Elementen gebruikt van MORPHXIT_Reports project Klasse, Reports_TempTable Rapport, Reports_TempTable Bij het gebruik van tijdelijke tabellen, dient het rapport opgeroepen te worden vanaf een klasse. Dit biedt de mogelijkheid om de tijdelijke tabel te bouwen op de server. Het volgende voorbeeld toont hoe je een rapport kunt maken met gebruik van een tijdelijke tabel. Voor de eenvoud voegt het voorbeeld 10 records toe aan de tijdelijke tabel en drukt het resultaat af. class Reports_TempTable extends runBaseReport { }
De klasse erft over van runBaseReport. public identifiername lastValueElementName() { return reportstr(Reports_TempTable); }
De naam voor het rapport wordt gespecificeerd. tmpAccountSum tempTable() { CustTrans custTrans; TmpAccountSum tmpAccountSum; Counter counter; ; while select custTrans { counter++; if (counter == 10) { break; }
© 2007 Steen Andreasen
51 of 60
MORPHX IT
Rapporten
tmpAccountSum.accountNum = custTrans.accountNum; tmpAccountSum.currencyCode = custTrans.currencyCode; tmpAccountSum.balance01 = custTrans.amountMST; tmpAccountSum.insert(); } return tmpAccountSum;
Samples from MORPHX IT -- steenandreasen.com
}
De tijdelijke tabel tmpAccountSum wordt gebruikt. De eerste tien records van de CustTrans tabel worden aan de tabel tmpAccountSum toegevoegd. Het rapport gebruikt deze methode om de buffer van de tijdelijke tabel door te geven naar het rapport. static void main(Args args) { Reports_TempTable reports_TempTable = new reports_TempTable(); if (reports_TempTable.prompt()) { reports_TempTable.run(); } }
De klasse wordt geïnitialiseerd en het rapport wordt uitgevoerd.
De laatste stap is het creeëren van het rapport. Een rapport met de tijdelijke tabel, TmpAccountSum als gegevensbron, moet aangemaakt worden. De drie velden opgevuld met de waarden van CustTrans zullen afgedrukt worden. Je rapport moet eruitzien als Figuur 12: Rapport met tijdelijke tabel.
Figuur 11: Rapport met tijdelijke tabel
© 2007 Steen Andreasen
52 of 60
MORPHX IT
Rapporten
Init() moet overschreven worden. De runbase klasse wordt geïnitialiseerd en de query wordt opgevuld met een buffer naar de tijdelijke tabel. Merk op dat je een referentie dient te maken naar de buffer. De query zal hierdoor het volledige bereik hebben van de tijdelijke tabel en alle records van de tijdelijke tabel overlopen.
Samples from MORPHX IT -- steenandreasen.com
public void init() { Reports_TempTable ; super();
reports_tempTable;
reports_TempTable = element.args().caller(); if (!reports_TempTable) { throw error(Error::missingRecord(funcName())); } reports_TempTable.queryRun().setRecord(reports_TempTable.tempTable()); }
Gekleurde rijen Kleuren zijn zeldzaam in standaard verpakte rapporten. Je zal een beetje moeten spelen met het rapport om het gewenste resultaat te krijgen. Nochtans kan het gebruik van kleuren de kers op de taart zijn voor je rapport en de afdruk gemakkelijker maken om te lezen. Elementen gebruikt van het MORPHXIT_Reports project Rapport, MyReport_Color Menu item output, MyReport_Color Dit voorbeeld toont hoe één enkele kolom een bepaalde kleur kan krijgen volgens een bepaalde conditie. Het rapport zal de achtergrondkleur wijzigen van het veld CustTrans.amountMST. Om code te vereenvoudigen, gebeurt de conditiecontrole vanuit X++. In een echte applicatie zullen de voorwaarden opgegeven worden via een dialoogvenster of gebaseerd zijn op de data in een formulier. Het resultaat zal eruit zien zoals te zien is op Figuur 13: Rapport gekleurde rijen.
© 2007 Steen Andreasen
53 of 60
Samples from MORPHX IT -- steenandreasen.com
MORPHX IT
Rapporten
Figuur 12,: Rapport gekleurde rijen
1. Start met het dupliceren van het rapport MyReport en geef het de naam “MyReport_Color”. 2. Het doel is om het element CustTrans_AmountMST een bepaalde kleur te geven. Door gebruik te maken van het ongewijzigde MyReport voorbeeld, zal de label van de paginahoofding ook van kleur wijzigen. In plaats van de standaard paginahoofding voor de middensectie CustTrans_Body, moet je een nieuwe hoofding aanmaken. Om de standaard paginahoofding over te slaan, geef je de eigenschap NoOfHeadingLines de waarde “0” in de middensectie CustTrans_Body. 3. Maak een nieuwe paginahoofding door een programmeerbare sectie toe te voegen en een prompt control voor elk van de drie velden in de middensectie. De eigenschap ModelFieldName op iedere prompt control moet geïnitialiseerd worden naar de overeenkomstige middensectie controlnaam. Voeg een label toe voor iedere prompt control. 4. Declareer een variabele om bij te houden wanneer de programmeerbare sectie, gebruikt om de paginahoofding af te drukken, moet uitgevoerd worden. public class ReportRun extends ObjectRun { Boolean printCustTransHeader; }
© 2007 Steen Andreasen
54 of 60
MORPHX IT
Rapporten
5. Overschrijf de methode send(). Als het huidige record een CustTrans record is, dan zal de paginahoofding afgedrukt worden voor de eerste CustTrans in een rij. Er werd een conditie toegevoegd voor het veld CustTrans.AmountMST. Indien een bedrag hoger dan 500 wordt afgedrukt, zal de achtergrondkleur wijzigen in het geel. Zoniet, zal de achtergrondkleur ongewijzigd blijven in een neutrale kleur.
Samples from MORPHX IT -- steenandreasen.com
public boolean send(Common _cursor, int _level=1, boolean _triggerOffBody=TRUE, boolean _newPageBeforeBody=FALSE) { boolean ret; ; if (_cursor.tableId == tableNum(custTable)) printCustTransHeader = true; if (_cursor.tableId == tableNum(custTrans)) { if (printCustTransHeader) { element.execute(10); printCustTransHeader = false; } if (custTrans.amountMST > 500) { CustTrans_AmountMST.backgroundColor(Winapi::RGB2int(255, 255, 0)); } else { CustTrans_AmountMST.backgroundColor(Winapi::RGB2int(255, 255, 255)); } } ret = super(_cursor, _level, _triggerOffBody, _newPageBeforeBody);
return ret; }
Afdrukken met Microsoft Word Rapporten aanmaken in Axapta met een complex ontwerp zoals formules, tabellen en figuren kan een hele uitdaging zijn. Door gebruik te maken van de COM interface kun je connecteren naar externe applicaties zoals Microsoft Word. Om Microsoft Word te gebruiken om data af te drukken, moet je eerst een Microsoft Word sjabloon aanmaken met de nodige markeringen of bookmarks te maken. De markeringen worden gebruikt om de data uit Axapta te positioneren. Let wel, je moet een licentiecode hebben voor minstens één COM client om de COM interface te kunnen gebruiken.
© 2007 Steen Andreasen
55 of 60
MORPHX IT
Rapporten
Opmerking: De documentafhandeling in het standaardpakket gebruikt de COM interface om Microsoft Excel en Microsoft Word bestanden te koppelen. De klassen gebruikt door Document handling hebben als prefix DocuActionCOM.
Samples from MORPHX IT -- steenandreasen.com
Elementen gebruikt van het MORPHXIT_Reports project Klasse, PrintUsingWord Job, Reports_PrintUsingWord Bijhorend Wordsjabloon , Reports_WordTemplate.dot Dit voorbeeld zal tonen hoe je een connectie kan maken met Microsoft Word en een nieuw document kan maken dat data van de InventTable tabel zal afdrukken. De eerste 10 rijen van de InventTable zullen afgedrukt worden. Er zullen labels worden afgedrukt voor de rapport- en kolomhoofdingen. Je zal een Microsoft Word sjabloon moeten aanmaken met de volgende markeringen : label_header, label_itemid, label_itemname en label_itemdesc. Label_header zal een teksthoofding afdrukken voor de kolommen. Creeër een tabel en voeg de 3 resterende markeringen toe als hoofdingen voor de tabel. De volgende stap is het creeëren van de volgende klasse: void run() { COM ;
COMAppl, COMDocuments, COMDocument;
COMAppl = new COM('Word.Application'); COMDocuments = COMAppl.documents(); // enter path to the template Reports_wordtemplate.dot COMDocument = COMdocuments.add('d:\\Reports_WordTemplate.dot'); if (COMDocument) { this.setLabels(COMDocument); this.sendInventTable(COMDocument); this.showDocument(COMAppl); } }
Run() zal de COM connectie initialiseren, en een nieuw Microsoft Word document openen, gebaseerd op de sjabloon Reports_WordTemplate.dot. Vergeet niet te controleren of het pad naar de sjabloon wel degelijk correct is. Bij de creatie van het document zullen de labels en data toegevoegd worden. Uiteindelijk zal het document getoond worden. Onthou dat het getoonde document niet bewaard wordt. Indien je het document wenst te bewaren, moet je de volgende instructie toevoegen : COMdocument.saveAs(
,0,false,'',false); void setLabels(COM _COMDocument)
© 2007 Steen Andreasen
56 of 60
MORPHX IT
Rapporten
{ COM DictField Label
COMBookmarks, COMBookmark, COMrange; dictField; label;
;
Samples from MORPHX IT -- steenandreasen.com
COMBookmarks
= _COMDocument.bookmarks();
if (COMbookmarks.exists('label_header')) { COMbookmark = COMbookmarks.item('label_header'); COMrange = COMbookmark.range(); COMRange.InsertAfter("Inventory list"); } if (COMbookmarks.exists('label_itemId')) { COMbookmark = COMbookmarks.item('label_itemId'); COMrange = COMbookmark.range(); DictField = new dictField(tableNum(inventTable), fieldNum(inventTable, itemId)); COMRange.InsertAfter(dictField.label()); } if (COMbookmarks.exists('label_itemName')) { COMbookmark = COMbookmarks.item('label_itemName'); COMrange = COMbookmark.range(); DictField = new dictField(tableNum(inventTable), fieldNum(inventTable, itemName)); COMRange.insertAfter(dictField.label()); } if (COMbookmarks.exists('label_itemDesc')) { COMbookmark = COMbookmarks.item('label_itemDesc'); COMrange = COMbookmark.range(); label = new Label(CompanyInfo::languageId()); COMRange.InsertAfter(label.extractString(literalstr("@SYS58702"))); } }
Er wordt gekeken of de markering gevonden kan worden. Indien deze gevonden wordt, worden de labels opgevuld. De label voor de hoofding krijgt de statische tekst “Inventory list”. De labels voor de markeringen label_itemId en label_itemName krijgen de waarde van het label van de overeenkomstige tabelvelden. De label voor de markering label_itemDesc krijgt een waarde via de methode label.extractString() die de label ophaalt voor de standaardbedrijfstaal. void sendInventTable(COM _COMDocument) { COM COMTable, COMRows, COMRow; COM COMCells, COMCell, COMRange; InventTable inventTable; Counter counter;
© 2007 Steen Andreasen
57 of 60
MORPHX IT
Rapporten
; //init tabel COMTable COMTable COMRows
= COMDocument.Tables(); = COMTable.Item(1); = COMTable.Rows();
Samples from MORPHX IT -- steenandreasen.com
while select inventTable { counter++; if (counter == 10) { break; } // add new row COMRow = COMRows.Add(); COMCells = COMRow.Cells(); // item id COMCell = COMCells.Item(1); COMRange = COMCell.Range(); COMRange.InsertAfter(inventTable.itemId); // item name COMCell = COMCells.Item(2); COMRange = COMCell.Range(); COMRange.InsertAfter(inventTable.itemName); // item description COMCell = COMCells.Item(3); COMRange = COMCell.Range(); COMRange.InsertAfter(inventTable.itemDescription()); } }
De code doorloopt de inventTable. De tabel zal eerst in Microsoft Word geïnitialiseerd worden. Voor ieder record wordt een rij toegevoegd aan de tabel in Microsoft Word. De velden itemId, itemName en de displaymethode itemDescription() van de InvenTable worden toegevoegd aan de drie rijen in de Microsoft Word tabel. Merk op dat er geen markeringen nodig zijn. void showDocument(COM _COMAppl) { _COMAppl.visible(TRUE); }
Het aangemaakte Microsoft Word document wordt getoond. static void main(Args _args) { PrintUsingWord printUsingWord = new PrintUsingWord(); ; PrintUsingWord.run();
© 2007 Steen Andreasen
58 of 60
MORPHX IT
Rapporten
}
Deze code initialiseert en voert deze klasse uit.
Samples from MORPHX IT -- steenandreasen.com
1.8
Samenvatting
Dit hoofdstuk gaf je een inleiding op rapporten in Axapta. Het omvat de basis voor het creeëren van rapporten. Nu zou je reed vertrouwd moeten zijn met de verschillende rapportelementen, zoals gegevensbronnen, ontwerpen, secties en controls in ontwerpen en gemeenschappelijke methoden gebruikt bij het aanmaken van een rapport. Je zou ook kennis moeten verworven hebben omtrent het het aanmaken van rapporten met de rapportgenerator en hopelijk verkreeg je inzicht in de kracht van Axaptarapporten en de MorphX ontwikkelingsomgeving.
© 2007 Steen Andreasen
59 of 60
Samples from MORPHX IT -- steenandreasen.com