Foxite.COM Community Weblog

Foxite.COM Community Weblog - free weblog service for the Visual FoxPro Community.
Welcome to Foxite.COM Community Weblog Sign in | Join | Help
in
Home Blogs Forum Photos Forum Archives

ReportSculptor



  • Report Sculptor 1-2-3 Series. Getting started / OOP Reporting

     

    So you have visited Report Sculptor website,  then finally found some time to download files. And now what ?  SculptorSchema

    As you are probably still confused with all that stuff that you saw on website (and I don't blame you!), 
    perhaps it is time to finally offer some guidlines and explanations to those of you who might  be interested
    in all this. 

    In this blog series I will try to break the ice little bit, and show you that no matter how
    complex it all might seem  to you at this point (What a heck is on that picture ?!?),
    Report Sculptor is actually all about simplicity and  pretty much down to earth when it comes
    to class of reporting problems it is trying to solve.  And as you will later see, it is all very very easy
    to understand and get on with it ! 

    This time around I will not get you tired with long pages explaining theory and complex OOP buildup
    behind these features,  but try to make it more like jumpstart manual, explaining how to get advantage
    of this whole thing, in shortest possible time!   
    Trust me, I did not go through all this, to make things more difficult, quiet opposite :)
    You will be versatile in RS reporting before you even know it!  (You Already know it! )


    But enough talk, let's get down to business :)
    We will start first with things that naturally come first;

    Download and initial setup
    There are two files you have to download in new version 0.90 Beta
    (First and second download link respectively);

    1) RsDev.Zip 
    2) RsServer.zip


    I will start explaining in reversible order starting with file #2  first, simply because there is really nothing to explain there. This file (RsServer.zip) 
    is just conveniently packed server deployment, which will be simply dumped (unzipped) somewhere along with your application when
    the right time comes. As simple as that; Unzip and dump whole thing right next to your own app.   (be that server or client machine) 

    So let's forget about it all together and proceed with setting up your own RS Reporting - 'Laboratory' 

    We will take rsDev.zip and unzip it in directly on your ( presumably c:\ ) drive.
    So, after you agree to (annoying) WinZip license and finally create C:\RsDev   folder with all subfolders underneath, you will open your FoxPro9
    and consecutively look for ReportScuptorDemo.pjx   located in root folder. When project opens up, go to project tab 'Code'  and run myRS.prg.
    After that you can run second program marked here, to verify that everything is working.  You will get VFP9 preview of HelloWorld  prg sample.    

     RsDemoPic01
    Picture 1  Report Sculptor Demo Project

    We will take closer look inside myRS.prg later, because there are few important things there regarding later deployment, but we will come back to it
    once we actually need it.  You don't have RS Report to deliver (at this point)  so why bother. Instead I will just say that every time you open this
    demo 'RS LAB' you always run this program first, in order to set up development environment.  This program essentially calls compiled
    ReportSculptor.app which in turn, automatically sets up RS Global Object, initializes GdiPlusX and then sets procedure to itself, so you are set
    to run all form samples.

    While running demo forms is nice, and you see many nice RS samples, perhaps you don't get to understand much out of it. So we will not go this way.
    This is jumpstart crush-course not site-seeing (you probably managed to do that by now already) so instead, we are going straight to the
    core of the matter. Develop Report! Believe it or not, by the end of this blog post alone you will be able to develop your very first;
    (or first in a long time) ; 

    Free Report  
    (Fully OOP at that!)

    Before we do that, let's try doing something like a little hypnotherapy, where you try put all troubling thoughts and fears some place else, and
    free your mind  to learn something only relatively new. Therefore try to erase from your brain all those complex listener constructions
    with GDI+ custom rendering, successors,  decorators etc. You will much easier understand all this - if you forget all that and have 'clean start'  :)       

    So as clock is ticking. We are sliding back in time.  
    Now, as your memory takes you couple of decades back in time when (FRX) designers were not even invented yet (let alone listeners) laser jet cost
    in a 4000$ range, you can almost hear an awful noise coming from next door...  So what was happening there making that much of a noise ?
     Account's department is printing payrolls! 
    But wait minute!  All this is happening some 20 years back, they did not have modern report designers back then!  So how the heck
    they were doing it ??   Well it was hard but obviously not impossible. And more or less everybody did some of that.  
      
    Let see now, how do we write one very ordinary report without comfort of having Report Designer at hand.
    That is not to keep you permanently in stone age of reporting, but simply to remember basics, which will help you greatly 
    understand how Report Sculptor Engine works!   

    Write As You Go  / Line By Line    
    So let now run this little program within your \rsDev\rsDev.pjx   'Report Laboratory'
    In order for this to work you have to execute  myRS.prg  first and set up RS development environment. Then create new prg
    and add below code;

    ******* Open & Relate tables
    Close Tables All
    use (Addbs(_oRSGO.RS_root) + 'data\categories' ) In 0 Shared order categoryid
    use (Addbs(_oRSGO.RS_root) + 'data\products' ) In 0 Shared  order categoryid
    select products
    set relation to categoryid into categories
    go top

    *set device to printer prompt &&If you want to send it to printer
    *set Printer on              

    ****** And then produce raw output on screen using ?/?? commands 


    ? '          RS Example of Raw Printing '
    ? Replicate('-',80)
    scan
       ? 
       ?? Str(Products.categoryid,5,0) at 10
       ?? Products.productname at 20
       ?? Transform(Products.unitprice,'$$$,$$$.00') at 60
       ?  
    endscan
    ? Replicate('-',80)
    ? 'End of report'

    *set device to screen

    When you run this prg, you shall see raw report lines scrolling on your screen. When I have sent this to 
    MDI format (via MS Office Document Image Writer) I got 3 pages of raw, character based report.
    I amended picture a bit to illustrate flow of lines as if this was to be sent to physical printer. So here it is; 

    Picture 2  Raw Report
     RsDemoPic02 

    So what do we got here ; 
    Not much I agree, but enough to understand order of events in physical terms, when this report is to be printed out on matrix or even laser printer
    in character mode.   Red lines illustrate Page By Page flow of report, while blue lines illustrate Line by Line flow happening within those pages.

    Essentially, page is drawn from top to bottom, line by line (only way line printers were able to print them)
    up to certain Page Break Point where printer would simply eject it, and start writing new one. This motion would continue until entire report is written.
    Paper space below that page break point would be  'Non Printable Area'  and would vary from printer to printer. 

    Note that we did not define any page headers or footers, report groups or anything like that. This is very very basic report level. You can see that
    data records are ordered by category and you can see the point where CategoryId  (group) changes, but since we did not make any provisions
    for this event , then nothing is actually happening except our eye noticing it. Report lines simply flow one after the other as we scan through
    'Products' table.

    Main reason I took you back to this basic level is that;
    If you understood what you have seen above, then you already have in dept understanding of RS Engine.
    RS Paging Engine down under, acts pretty much the same way! 

    You saw that along this code I issued 'set device
    to printer.'  and then redirected output to a printer (MDI you saw) therefore for the sake
    of easy understanding Consider it simply a new device. 
    'Only' difference between your Printer as device, and RS Engine as device is that RS Engine is actually an Object  rich in functionalities.
    Now since it is an object, instead of doing 'set device to . '   You get to hold object reference of rsEngine object in a variable. 

    local oRS as rsEngine
    oRS=getRsObject(thisform)
    oRS.OpenSession()
    With oRS

    And RSEngine 'device' is now ON
    Having done so, I could now continue and recode above shown raw report 1:1, by calling short named RsEngine methods matching
    to  ?/??  output commands;  

    .lf()
    .lw(25, '          RS Example of Raw Printing ')
    .
    Endwith

    And so for.  It would eventually appear almost the same as shown on picture above.  

    Now there IS big difference between just having printer open with 'set device to printer' and  having rsEngine Object instantiated and held as
    object reference. RS Engine is fully blown FoxPro object rich with methods and functionalities which give you
    Full Power and almost complete control  over every aspect of page rendering, and consecutively Report creation.  Next to flashing out records
    line by line, and flipping pages one after the other, RS Engine is capable of doing many more things!  

    However, Let's focus on ONE particular feature;  RS Engine can render native FoxPro controls on RS Report surface
    Note that idea and method here is NOT to make a snapshot of Form controls (which is doable as well) but to reproduce them
    in a practical reporting context
    This feature alone brings up entirely new reporting paradigm when it comes to VFP reporting;

    Visual OOP Report as VFP9 Form 
    (In steps 1-2-3 )  


    Step 1  
    Create an empty Form, Open & Relate Data via Form.DE


    So we  add native VFP form to our RS Demo Project.  Note that all controls used here will be native VFP controls. This is not some firm requirement
    or anything like that;  RS can ran from almost any kind of Forms and use your own (framework) controls.  I hereby use native controls simply to
    demonstrate how RS in fact gives whole new Role to our aging VFP Form Designer & all it's 'dwellers'. As you will later see, Form Designer
    becomes not exactly 'Inspector Gadget' , but workable Report Designer at least. 

    Then we open Form Data environment where we Open & Relate Products -> Categories  via common  categoryId field and index tag
    These tables can be found under data folder of RS Demo Project structure and belong to our old friend TasTrade.Dbc
    Product table is parent, and it is ordered by index Tag categoryID. Just like we had it in that raw text report earlier.    

    Picture 3 Open & Relate Data
    RsDemoPic03


    Step 2 
    Building Report Sctructure 
     
    We add (in this case 3) borderless empty containers painted white, according to reporting structure we want to build. 
    We also add couple of buttons, one to run it and one to release form while in development mode. That is not really necessary, as all this can
    run from invisible form without user interaction. I just added buttons here so we can play with it easier.  I also set form back color to little
    bit darker gray, for better visibility. 

    Then we name containers intuitively into  'Detail_Header' ,  'Detail' , 'Detail_Footer'  respectively  
     
    Picture 4  Building Report Structure  
     RsDemoPic04  
     

    Then we reopen Form.DE window and simply start dragging and dropping fields directly on form surface.
    Now there is little bit of 'grunt work'  involved here. Next to above structuring of report we also have to do resizing, aligning,
    setting textbox format/input masks moving objects around etc. 
    (Bear in mind that this is all built from scratch right here&now, whereas you can have for instance template form having all necessary objects ready
    to be filled up. Not to even mention, that since we use real objects we can do much better then just have templates.  (Class libraries later)

    Picture 5  Grunt Work 
    RsDemoPic05 


    When we groomed and aligned our textboxes and labels properly, we distribute them (cut&paste) to respective container bands.
    All labels will go to header container and all textboxes will go to detail container preserving alignment all along. 

    Then finally we put all this together into  actual report via code;  

    Step 3   Stage Data Flow

    We will now stage simple Scan/EndScan data flow which will flash  form containers we just built as report bands , and then we run
    our report (form).

    What do I mean by flashing containers as bands ?   
    Just as ?/??  commands can output some strings and increment some internal line counter, RS Engine have method called
    .FlashContainer() which does similar thing, but renders entire containers from our active form to our RS report.
    After container and all contained objects are transported to our report surface, RS engine will simply increase current vertical
    page position maintained in a property called .nTop  (just like VFP increases _plineno ) and writing will continue with next band
    (container in this case) .   

    So report writing principle is again the same as we saw before on raw text example;  Write As You Go  but with one major difference!
    It is no longer Line By Line!  Now instead of going line by line, advances are made vertically Band By Band,  where 'Band' is actual
    (.Flash)Container and it's height in pixels. 
    And just like in that raw report example; When RS Engine reach some Page Break Point  it adds new page and report continues.

    Now since RS Engine is fully blown object, this running 'motion' rises various  events  such are;
    Page Footer any time page break point is reached
    Page Header any time new page is appended
    There are of course more events happening along, but let's keep it simple for better understanding.  

    Back to our example;
    For simplicity purposes, I will not draw directly Page Headers/Footers but rather let RS Engine render default ones.  
    (Hence  these default PH/PF are customizable, and can be actually your own class objects, so you already get first glimpse of OOP kicking
    inn to help productivity.) 

    So, since RS Engine will handle Headers and Footers, we are left with very simple task / code to write.  See right side of the picture, and
    watch markings/comments carefully ;  

    Picture 6   Putting it all together
      RsDemoPic06  

    What you can see on the right side (in green) is something that vaguely resembles FRX detail band with header and footer, but is this
    time situated right here in our code to illustrate that you in fact fully control report flow and order of events. 
    This very simple record loop on products table will be actually driving our report.
    As you can see above I added one more label and textbox to footer band to show product count ( as simple reccount() ) and Voila! 

    Our report is ready! 
    When you run this form and click run button, you get fully blown report ready to be printed exported etc. 
    I will expose it via VFP9 native Preview/Print in this case.

    Picture 7 Our first OOP Report
    RsDemoPic07 

    RS Engine Behavior
    Now let see how did engine behave in this case. As you will see, pretty similar as that raw report flow presented earlier;
    Page Break point is followed by Page footer band rather then nonprintable area in this case, but other then that principle is almost the same.
    Very simple and intuitive! So have look at picture below to easily understand basic order of events when executing OOP Data Report
    with containers as report bands;

    Picture 8 Print As Yu Go / Band By Band
    RsDemoPic08 


    However, this order of events is not something carved in stone. Since RS Engine is an object, it is all driven by properties. So here are some of them
    that control way page sections are unfolding;

    .lAutoFirstPage=.t.   &&   Decides if .OpenSession()  method automatically adds first page or you want to do it.

    ************************************** Page/Report Format and orientation  
    .
    rsPageFormat ='A4'  &&or 'LETTER','A3' (and the rest to follow soon)   
    .rsPageOrientation='PORTRAIT'  &&Orientation
    ************************************** Default Page Header Footers
    .lAutoPageHeader=.t.  && Decides if engine will flash Page Header (or maybe want to do it yourself)
    .lAutoPageFooter =.t.  && The same as with Page Header  
    .oPageHeader = oPageHeaderContainerRef  && directly 'pin' some container reference as Page Header
    .oPageFooter = oPageFooterContainerRef   && As for header 

    ****************************************Default Font (true types only)
    .rsFontName      = "Arial"
    .rsFontSize      = 8
    .rsFnStyleNo     = 1  &&Bold, 0 Regular, 2 Italic, 4 Underlined, 128 Strikethrough , and composites

    ****************************************relative on the fly / default positioning  
    .pgRemainder          &&  How many pixels remain before page break point is reached.
    .nTop                 &&  Current Vertical Position on page
    .nColumnLeft=25       &&  Default Left 
    ************************************* ***See sample form #10 for more properties and methods ***

    Love being in control ?  I thought so ;) 

    Where does this lead us ? 
    This was by all means very simple report. It was meant to be this way, so you can understand basic RS Engine motions easily. 
    As they say; 'You got to learn to walk first before you try flying.'   so this example was greatly simplified (or downplayed if you wish)
    showcase of power  and flexibility this approach gives you, so you can get on your own two feet by understanding very basics.   

    I understand that by now you are probably bored to death with 'Product By Category' type of report samples, so let see some
    real life examples of how you can assert and exercise this power to much greater extend. 

    Therefore, take look at following report example published in RS Report & Code Gallery. 
    It is quiet good example of power brought to you by above presented paradigm of code driven report with containers as report bands
    So please have look at it   http://www.report-sculptor.com/community/gallerymenu#GroupingOnMultipleInnerBands 
    Those of you who follow this blog post with an open RS Demo Project in front of you, can open and run form sample #15. 

    Some of you might say or think  'Big deal, I can do such thing with FRX' .
    I am sure you can :)  It has been done already many times despite some FRX limitations in this respect, but report itself is not the point here! 
    What I have presented you in this blog post was actually about something else.  If you look inside code there (#15) then that form itself,
    you will realize one major difference compared to 'common solutions' to this I would say common reporting requirement
    (multiple bands with grouping on each);  
    If you remember how much of your time and energy you have spent by now on smartly preprocessing cursors, creating dummy indexes and
    relations,  'overheating'  PrintWhen clauses, adding report variables, UDFs (and what not.)  on various reporting problems like this in the
    past, You just might like the fact that with RS;

    It is no longer you trying to 'trick' predefined FRX paradigm & order of events so you get result report you wish,
    It is you who create  your own paradigm - So you simply do as you wish.  
    RS Engine is there to provide services so you can accomplish that task, but you are the one who set the rules to the game :) 

    Having spelled out this little 'rant' about FRX,  I have to clarify once more that RS is not something trying to replace or compete
    with FRX/RD.  Report Sculptor is designed to compliment FRX based reporting in cases like like those published under gallery/samples;
    When FRX have to be 'pushed beyond limits'  in order to achieve certain results, or report is impossible to build with FRX/RD. 
    I wrote RS for this kind of reasons.  However, when ordinary report comes which have no any special requirements; 
    Then I would myself use FRX/RD!  I might pass it through RS to get PDF  or TIF version, but I would still write it with FRX/RD.  
    At this point building standard stereotype reports with FRX is still much easier. However do not underestimate (yourself and)
    power of OOP concept.  Things might change in the future :)

    Talking about OOP;

    Little game at the end 
    'Bonus Question' 

    If you take that simple form we just created together (picture #7 ) and then consecutive result that comes out of it (picture #8) 
    it might look to you like 'case closed' What else is there to say ?  However, let's not overlook few details ( 'Devil lies in details'    )

    1) It is 100% OOP report in terms of elements used
    2) Despite being very primitive, it is already  (90% ) reusable reporting structure   

    If you take form we just have put together, and clean up all containers bands, leaving them empty and then also remove all 
    cursor objects object from DE, what do we get ? Your 'bonus question' to win this game is;   

    Discover 'offending' line of code, preventing you to save this form as  Reusable reporting class?

    Picture 9  OOP Bonus Question
     RsDemoPic09   

    You guessed it right. It is line #1 :)

    select products

    If you erase this line and save this form with emptied containers into your own class library, 
    you just made your first  report designer class!  Although primitive, you could even use it, to do produce simple record listings .

    All you would have to do next time, is add cursors to Form.DE and then drag & drop some fields from there onto form surface
    align & groom  textboxes/labels and distribute them to those empty band containers. There would be no code required any more. 
    Very primitive OOP buildup in this case was sufficient to reach 'no code required' situation, and turned this very primitive demonstration form
    into simple reporting class. 

    Ultimate prize on this bonus question you just won - is your own Reporting Freedom. So go out there and cash it :)

    And that would be all for now,  
    In the next blog;
    We will further expand on this brand new reporting concept, and show how to do nested report groups, organize totaling etc. 
    '1-2-3' part of the blog, will be on how to compile and deploy your application with RS reporting enabled.

    Stay tuned & Enjoy using Report Sculptor :)

  • Report Sculptor - New Version 0.90

    Report Sculptor is Free Reporting Framework, complement and extension to standard VFP9 reporting, which focuses on providing alternative ways of designing reports with VFP9. Major goal of this project is Fully OOP Reporting, Cross Format, Open, Extensible and Free of all known constrains. Next to providing many new and significant ready to use functionalities, it is also intended to become solid foundation for building Your personal OOP reporting solutions.


    *** Time to re-download!
    http://www.report-sculptor.com/downloads

    This version bring significant changes in terms of easy integration, and also many new features.
    Demo Project now have 14 samples. See samples from #6 and up in particular.
    If first version was 'Pilot Beta' this version is actually more like 'production grade' beta.
    See / Try  report samples yourself.  

    In this version;

    - Greatly simplified Deployment and customization of Rs Engine
    (See Readme.TXT for set of instructions for easy RS integration)
    - Simple Excel Replication added   (See Form samples #09 and  #11/PageTab5  )
    - Added Frx Wrapper for codeless (visual) chaining of FRX reports via pageframe. (Form #12)
    - Improved grid rendering for fitting headerless grids into preprinted forms (#14)
    - Improved RS SmartText
    (Venture into text programming if necessary - See Form Sample #11 / PageTab3)
    - Added FlashContainer() method which turns your form containers into actual
    report bands (Form Sample #15)
    - Engine now supports A4, LETTER, A3  (With most of standard page formats to follow)

    And few more 'goodies' here and there :)
    ---------------------------------------------------------------------------------------------------------
    Note:
    For Previewing/Printing hard copies) in real life apps,
    at this point in time I still recommend using standard VFP9 standard Preview&Print facility.
    Via oRS.Output( 2 , [.t.] )  method.  

    FYI  RS Native Preview/Print facility is still under development.
    ------------------------------------------------------------------------------------------------------------

    ReportSculptor Highlights;

    * * *

    - Independent Reporting Engine (Pure VFP object)

    - Report Scripting (Low to high level)
    Report from Arrays, Collections, Database Structures, Project files etc.
    Loop through and (Script) Write-as-You-Go.

    - WYSIWYG Design of Free Reporting pages
    Visual Report Composition (Page By Page)
    Using native form objects, ActiveX snapshots etc.

    - FRX Interpreter
    Allowing you to process any FRX report in order to combine resulting pages with other report contents.

    - Report from Text files (RS SmartText)
    Merge Plain Text with your data and then additionally decorate it with nice fonts, using simple html formatting tags and scripting embeded within text.

    -Report From Excel files (Included now)
    Simple Excel replication alowing You to
    use Excel Contents directly as part of your reports.

    And Finally;
    - Introducing Fully OOP Reporting to VFP9
    Enter into exciting new world of totally free and Fully OOP Reporting. Use your own Grids, Listboxes, Checkboxes, Textboxes, Labels, Shapes, Containers etc. and build your own OOP Reporting functionalities.

    When do I need Report Sculptor ?
    For Extremes; Very Simple and Very Complex Reports.
    To produce simple record listing, all that is needed is a single function call, pointing to any grid on a form. (Combined with run time grid creation can cut quiet a bit number of Frx-es shipped with your App.)

    When you need tricky, non-standard and/or Complex Multi Part Reports then these are perfect matches for Report Sculptor. These were one of main reasons for building this framework.

    On Output Side.

    Anything you do with ReportSculptor can be;

    Previewed and Printed via
    - Report Sculptor Modeless Preview/Print Form
    - VFP9 Native Preview/Print
    - XFRX Preview/Print.

    Or Exported to files
    - Ultrafast PDF Export (via DorinV wrapper for HaruPdf OpenSource library)
    - Multipage TIF
    - XFF intermediate format, which can be directly converted to many other formats supported by XFRX.

    * * *

    This is Free & Open Project! - Contributing Authors Welcome.

    Also, bear in mind that this still work in progress, which requires lot of your support and feedback to get better over period of time. Please try features and send me your feedback.
    It will be of great value to me to improve and robust this tool. 

    Thank You for all constructive feedback I received so far &

    Enjoy using ReportSculptor :)

    Djordjevic Srdjan
    Limassol, Cyprus

This Blog

Post Calendar

<January 2009>
SuMoTuWeThFrSa
28293031123
45678910
11121314151617
18192021222324
25262728293031
1234567

Archives

Syndication