Page 2 of 3

Re: Reports designers comparison

Posted: Tue Jul 09, 2013 4:18 pm
by Antonio Linares
This is just a very early draft, I appreciate if you comment about something really missing that may be uncompatible with this design:

I think MDI is the way to go as we can work with x reports simultaneously.

Image

The header and footer are RichEdit controls so we can do there what we want related to fonts, colors, pictures, etc.

In the center a xbrowse to define the report columns.

How to show the groups and subgroups ? (I think inside the xbrowse somehow)

Here you have full source code in case you want to try it :-)

FiveReps.prg

Code: Select all | Expand

#include "FiveWin.ch"
#include "RichEdit.ch"
#include "xbrowse.ch"
#include "splitter.ch"

static oWndMain

function Main()
 
   local oBmpTiled , oBar
   local hDLL := LoadLibrary( "Riched20.dll" )
 
   SetDlgGradient( { { 1, RGB( 199, 216, 237 ), RGB( 237, 242, 248 ) } } )

   DEFINE BITMAP oBmpTiled RESOURCE "background"  
 
   DEFINE WINDOW oWndMain TITLE "Reports Builder" MDI ;
      MENU BuildMenu()

   DEFINE BUTTONBAR oBar OF oWndMain 2010 SIZE 70, 70

   DEFINE BUTTON OF oBar PROMPT "New" RESOURCE "new" ACTION ReportNew()

   DEFINE BUTTON OF oBar PROMPT "Open" RESOURCE "open" ACTION ReportOpen()

   DEFINE BUTTON OF oBar PROMPT "Exit" RESOURCE "exit" ;
      ACTION oWndMain:End() GROUP

   ReportNew()

   ACTIVATE WINDOW oWndMain MAXIMIZED ;
      VALID MsgYesNo( "Want to end ?" ) ;
      ON PAINT DrawTiled( hDC, oWndMain, oBmpTiled )  

   oBmpTiled:End()
   
   FreeLibrary( hDLL )
   
return nil

function BuildMenu()

   local oMenu
   
   MENU oMenu
      MENUITEM "Reports"
      MENU
         MENUITEM "New" ACTION ReportNew()
      ENDMENU
   ENDMENU
   
return oMenu

function ReportNew()

   local oWndChild, cHeader := "Header", oHeader, oSplit1, oBrw
   local cFooter := "Footer", oFooter, oSplit2
   
   DEFINE WINDOW oWndChild TITLE "New report" MDICHILD
   
   @ 0, 0 RICHEDIT oHeader VAR cHeader SIZE oWndChild:nWidth, 70 OF oWndChild
   
   @ 5.3, 0 XBROWSE oBrw OF oWndChild SIZE oWndChild:nWidth, 150
               
   oBrw:CreateFromCode()

   @ 15.2, 0 RICHEDIT oFooter VAR cFooter SIZE oWndChild:nWidth, 130 OF oWndChild

   @ 70,0  SPLITTER oSplit1 ;
            HORIZONTAL ;
            PREVIOUS CONTROLS oHeader ;
            HINDS CONTROLS oBrw ;
            TOP MARGIN 30 ;
            BOTTOM MARGIN oSplit2:nLast + 50 ;
            SIZE 500, 4  PIXEL ;
            OF oWndChild ;
            STYLE

   @ 225,0  SPLITTER oSplit2 ;
            HORIZONTAL ;
            PREVIOUS CONTROLS oBrw NOADJUST ;
            HINDS CONTROLS oFooter ;
            TOP MARGIN oSplit1:nFirst + 50 ;
            BOTTOM MARGIN 80 ;
            SIZE 500, 4  PIXEL ;
            OF oWndChild ;
            STYLE
   
   ACTIVATE WINDOW oWndChild ;
      ON RESIZE ( oSplit1:Adjust( .T., .F., .T., .T. ), oSplit2:Adjust( .F., .T., .T., .T. ) )
       
return nil  

function ReportOpen()

return nil

Re: Reports designers comparison

Posted: Tue Jul 09, 2013 4:48 pm
by Antonio Linares
As it is just a GUI to FWH Class TReport, see how easily we can make it work already :-)

FiveReps.prg

Code: Select all | Expand

#include "FiveWin.ch"
#include "RichEdit.ch"
#include "xbrowse.ch"
#include "splitter.ch"
#include "report.ch"

static oWndMain

function Main()
 
   local oBmpTiled , oBar
   local hDLL := LoadLibrary( "Riched20.dll" )
 
   SetDlgGradient( { { 1, RGB( 199, 216, 237 ), RGB( 237, 242, 248 ) } } )

   DEFINE BITMAP oBmpTiled RESOURCE "background"  
 
   DEFINE WINDOW oWndMain TITLE "Reports Builder" MDI ;
      MENU BuildMenu()

   DEFINE BUTTONBAR oBar OF oWndMain 2010 SIZE 70, 70

   DEFINE BUTTON OF oBar PROMPT "New" RESOURCE "new" ACTION ReportNew()

   DEFINE BUTTON OF oBar PROMPT "Open" RESOURCE "open" ACTION ReportOpen()

   DEFINE BUTTON OF oBar PROMPT "Run" RESOURCE "run" GROUP ;
      ACTION ReportRun()
     
   DEFINE BUTTON OF oBar PROMPT "Exit" RESOURCE "exit" ;
      ACTION oWndMain:End() GROUP

   ReportNew()

   ACTIVATE WINDOW oWndMain MAXIMIZED ;
      VALID MsgYesNo( "Want to end ?" ) ;
      ON PAINT DrawTiled( hDC, oWndMain, oBmpTiled )  

   oBmpTiled:End()
   
   FreeLibrary( hDLL )
   
return nil

function BuildMenu()

   local oMenu
   
   MENU oMenu
      MENUITEM "Reports"
      MENU
         MENUITEM "New" ACTION ReportNew()
      ENDMENU
   ENDMENU
   
return oMenu

function ReportNew()

   local oWndChild, cHeader := "Header", oHeader, oSplit1, oBrw
   local cFooter := "Footer", oFooter, oSplit2
   
   DEFINE WINDOW oWndChild TITLE "New report" MDICHILD
   
   @ 0, 0 RICHEDIT oHeader VAR cHeader SIZE oWndChild:nWidth, 70 OF oWndChild
   
   @ 5.3, 0 XBROWSE oBrw OF oWndChild SIZE oWndChild:nWidth, 150
               
   oBrw:CreateFromCode()

   @ 15.2, 0 RICHEDIT oFooter VAR cFooter SIZE oWndChild:nWidth, 130 OF oWndChild

   @ 70,0  SPLITTER oSplit1 ;
            HORIZONTAL ;
            PREVIOUS CONTROLS oHeader ;
            HINDS CONTROLS oBrw ;
            TOP MARGIN 30 ;
            BOTTOM MARGIN oSplit2:nLast + 50 ;
            SIZE 500, 4  PIXEL ;
            OF oWndChild ;
            STYLE

   @ 225,0  SPLITTER oSplit2 ;
            HORIZONTAL ;
            PREVIOUS CONTROLS oBrw NOADJUST ;
            HINDS CONTROLS oFooter ;
            TOP MARGIN oSplit1:nFirst + 50 ;
            BOTTOM MARGIN 80 ;
            SIZE 500, 4  PIXEL ;
            OF oWndChild ;
            STYLE
   
   ACTIVATE WINDOW oWndChild ;
      ON RESIZE ( oSplit1:Adjust( .T., .F., .T., .T. ), oSplit2:Adjust( .F., .T., .T., .T. ) )
       
return nil  

function ReportOpen()

return nil

function ReportRun()

   local oRpt, aControls
   local oHeader, oFooter

   if oWndMain:oWndActive != nil

      aControls = oWndMain:oWndActive:aControls    
      oHeader   = aControls[ 1 ]
      oFooter   = aControls[ Len( aControls ) - 2 ]
   
      REPORT oRpt PREVIEW ;
         HEADER oHeader:GetText() ;
         FOOTER oFooter:GetText()

      COLUMN TITLE "" DATA ""

      END REPORT
     
      ACTIVATE REPORT oRpt
   endif

return nil


Image

Re: Reports designers comparison

Posted: Tue Jul 09, 2013 5:33 pm
by Antonio Linares
We can even dynamically add some dummy cols and see how it behave already :-)

Image

FiveReps.prg

Code: Select all | Expand

#include "FiveWin.ch"
#include "RichEdit.ch"
#include "xbrowse.ch"
#include "splitter.ch"
#include "report.ch"

static oWndMain

function Main()
 
   local oBmpTiled , oBar
   local hDLL := LoadLibrary( "Riched20.dll" )
 
   SetDlgGradient( { { 1, RGB( 199, 216, 237 ), RGB( 237, 242, 248 ) } } )

   DEFINE BITMAP oBmpTiled RESOURCE "background"  
 
   DEFINE WINDOW oWndMain TITLE "Reports Builder" MDI ;
      MENU BuildMenu()

   DEFINE BUTTONBAR oBar OF oWndMain 2010 SIZE 70, 70

   DEFINE BUTTON OF oBar PROMPT "New" RESOURCE "new" ACTION ReportNew()

   DEFINE BUTTON OF oBar PROMPT "Open" RESOURCE "open" ACTION ReportOpen()

   DEFINE BUTTON OF oBar PROMPT "Add" RESOURCE "add" ACTION ReportAddColumn() GROUP

   DEFINE BUTTON OF oBar PROMPT "Del" RESOURCE "del" ACTION ReportDelColumn()

   DEFINE BUTTON OF oBar PROMPT "Run" RESOURCE "run" GROUP ;
      ACTION ReportRun()
     
   DEFINE BUTTON OF oBar PROMPT "Exit" RESOURCE "exit" ;
      ACTION oWndMain:End() GROUP

   ReportNew()

   ACTIVATE WINDOW oWndMain MAXIMIZED ;
      VALID MsgYesNo( "Want to end ?" ) ;
      ON PAINT DrawTiled( hDC, oWndMain, oBmpTiled )  

   oBmpTiled:End()
   
   FreeLibrary( hDLL )
   
return nil

function BuildMenu()

   local oMenu
   
   MENU oMenu
      MENUITEM "Reports"
      MENU
         MENUITEM "New" ACTION ReportNew()
      ENDMENU
   ENDMENU
   
return oMenu

function ReportNew()

   local oWndChild, cHeader := "Header", oHeader, oSplit1, oBrw
   local cFooter := "Footer", oFooter, oSplit2
   
   DEFINE WINDOW oWndChild TITLE "New report" MDICHILD
   
   @ 0, 0 RICHEDIT oHeader VAR cHeader SIZE oWndChild:nWidth, 70 OF oWndChild
   
   @ 5.3, 0 XBROWSE oBrw ARRAY { Space( 20 ) } OF oWndChild SIZE oWndChild:nWidth, 150
               
   oBrw:CreateFromCode()
   
   oBrw:aCols[ 1 ]:cHeader = "Empty"

   @ 15.2, 0 RICHEDIT oFooter VAR cFooter SIZE oWndChild:nWidth, 130 OF oWndChild

   @ 70,0  SPLITTER oSplit1 ;
            HORIZONTAL ;
            PREVIOUS CONTROLS oHeader ;
            HINDS CONTROLS oBrw ;
            TOP MARGIN 30 ;
            BOTTOM MARGIN oSplit2:nLast + 50 ;
            SIZE 500, 4  PIXEL ;
            OF oWndChild ;
            STYLE

   @ 225,0  SPLITTER oSplit2 ;
            HORIZONTAL ;
            PREVIOUS CONTROLS oBrw ;
            HINDS CONTROLS oFooter ;
            TOP MARGIN oSplit1:nFirst + 50 ;
            BOTTOM MARGIN 80 ;
            SIZE 500, 4  PIXEL ;
            OF oWndChild ;
            STYLE
   
   ACTIVATE WINDOW oWndChild ;
      ON RESIZE ( oSplit1:Adjust( .T., .F., .T., .T. ), oSplit2:Adjust( .F., .T., .T., .T. ) )
       
return nil  

function ReportOpen()

return nil

function ReportAddColumn()

   local oBrw
   
   if ! Empty( oWndMain:oWndActive )
      oBrw = oWndMain:oWndActive:aControls[ 2 ]
      ADD COLUMN TO oBrw TITLE "Test" DATA Time() SIZE 150
      if oBrw:aCols[ 1 ]:cHeader == "Empty"
         oBrw:DelCol( 1 )
      endif  
      oBrw:Refresh()
   endif  

return nil

function ReportDelColumn()

return nil

function ReportRun()

   local oRpt, aControls, oBrw
   local oHeader, oFooter, n, cHeader, cValue

   if oWndMain:oWndActive != nil

      aControls = oWndMain:oWndActive:aControls    
      oHeader   = aControls[ 1 ]
      oBrw      = aControls[ 2 ]
      oFooter   = aControls[ Len( aControls ) - 2 ]
   
      REPORT oRpt PREVIEW ;
         HEADER oHeader:GetText() ;
         FOOTER oFooter:GetText()

      for n = 1 to Len( oBrw:aCols )
         cHeader = GetHeader( oBrw, n )
         cValue  = GetValue( oBrw, n )
         COLUMN TITLE cHeader DATA cValue
      next  

      END REPORT
     
      ACTIVATE REPORT oRpt
   endif

return nil

static function GetHeader( oBrw, n )

return oBrw:aCols[ n ]:cHeader

static function GetValue( oBrw, n )

return Eval( oBrw:aCols[ n ]:bStrData )

Re: Reports designers comparison

Posted: Tue Jul 09, 2013 7:12 pm
by Antonio Linares
Defining the databases to use for the report:

Image

FiveReps.prg

Code: Select all | Expand

#include "FiveWin.ch"
#include "RichEdit.ch"
#include "xbrowse.ch"
#include "splitter.ch"
#include "report.ch"

static oWndMain, oWndDbfs

function Main()
 
   local oBmpTiled , oBar
   local hDLL := LoadLibrary( "Riched20.dll" )
 
   SetDlgGradient( { { 1, RGB( 199, 216, 237 ), RGB( 237, 242, 248 ) } } )

   DEFINE BITMAP oBmpTiled RESOURCE "background"  
 
   DEFINE WINDOW oWndMain TITLE "Reports Builder" MDI ;
      MENU BuildMenu()

   DEFINE BUTTONBAR oBar OF oWndMain 2010 SIZE 70, 70

   DEFINE BUTTON OF oBar PROMPT "New" RESOURCE "new" ACTION ReportNew()

   DEFINE BUTTON OF oBar PROMPT "Open" RESOURCE "open" ACTION ReportOpen()

   DEFINE BUTTON OF oBar PROMPT "DataBases" RESOURCE "database" ACTION Databases() GROUP

   DEFINE BUTTON OF oBar PROMPT "Add" RESOURCE "add" ACTION ReportAddColumn() GROUP

   DEFINE BUTTON OF oBar PROMPT "Del" RESOURCE "del" ACTION ReportDelColumn()

   DEFINE BUTTON OF oBar PROMPT "Run" RESOURCE "run" GROUP ;
      ACTION ReportRun()
     
   DEFINE BUTTON OF oBar PROMPT "Exit" RESOURCE "exit" ;
      ACTION oWndMain:End() GROUP

   ReportNew()

   ACTIVATE WINDOW oWndMain MAXIMIZED ;
      VALID MsgYesNo( "Want to end ?" ) ;
      ON PAINT DrawTiled( hDC, oWndMain, oBmpTiled )  

   oBmpTiled:End()
   
   FreeLibrary( hDLL )
   
return nil

function BuildMenu()

   local oMenu
   
   MENU oMenu
      MENUITEM "Reports"
      MENU
         MENUITEM "New" ACTION ReportNew()
      ENDMENU
   ENDMENU
   
return oMenu

function DataBases( cFileName )

   local oBar, oBrw, aWorkAreas := GetWorkAreas(), cClrBack

   DEFINE WINDOW oWndDbfs TITLE "DataBases management" MDICHILD

   DEFINE BUTTONBAR oBar OF oWndDbfs 2010 SIZE 70, 70

   DEFINE BUTTON OF oBar PROMPT "Add" RESOURCE "add" ;
      ACTION ( OpenDataBase(), oBrw:SetArray( GetWorkAreas() ), oBrw:SetFocus() )

   DEFINE BUTTON OF oBar PROMPT "Exit" RESOURCE "exit" ;
      ACTION oWndDbfs:End() GROUP
   
   @ 0, 0 XBROWSE oBrw OF oWndDbfs LINES ;
      ARRAY aWorkAreas AUTOCOLS
   
   oBrw:nMarqueeStyle := MARQSTYLE_HIGHLROW
   oBrw:bClrStd = { || If( oBrw:nArrayAt % 2 == 0, ;
                         { CLR_BLACK, RGB( 198, 255, 198 ) }, ;
                         { CLR_BLACK, RGB( 232, 255, 232 ) } ) }
   oBrw:bClrSel = { || { CLR_WHITE, RGB( 0x33, 0x66, 0xCC ) } }
   cClrBack = Eval( oBrw:bClrSelFocus )[ 2 ]
   oBrw:bClrSelFocus = { || { CLR_WHITE, cClrBack } }
   oBrw:SetColor( CLR_BLACK, RGB( 232, 255, 232 ) )

   oBrw:CreateFromCode()
     
   oBrw:aCols[ 1 ]:cHeader  = "Area"
   oBrw:aCols[ 1 ]:nWidth   = 100
   oBrw:aCols[ 1 ]:bStrData = { || If( Len( oBrw:aArrayData ) > 0, oBrw:nArrayAt, "" ) }
   
   ADD COLUMN TO oBrw HEADER "Alias" DATA oBrw:nArrayAt WIDTH 100
   oBrw:aCols[ 2 ]:bStrData = { || If( Len( oBrw:aArrayData ) > 0, oBrw:aArrayData[ oBrw:nArrayAt, 1 ], "" ) }
   
   oWndDbfs:oClient = oBrw
   
   ACTIVATE WINDOW oWndDbfs

return nil

function OpenDataBase( cFileName )

   DEFAULT cFileName := cGetFile( "*.dbf", "Please select a DBF" )

   if File( cFileName )
      USE ( cFileName ) NEW
   endif

return nil

function GetWorkAreas()

   local aWorkAreas := {}, n := 1

   while ! Empty( Alias( n ) )
      AAdd( aWorkAreas, { Alias( n ), RddName( n++ ) } )
   end  

return aWorkAreas

function ReportNew()

   local oWndChild, cHeader := "Header", oHeader, oSplit1, oBrw
   local cFooter := "Footer", oFooter, oSplit2
   
   DEFINE WINDOW oWndChild TITLE "New report" MDICHILD
   
   @ 0, 0 RICHEDIT oHeader VAR cHeader SIZE oWndChild:nWidth, 70 OF oWndChild
   
   @ 5.3, 0 XBROWSE oBrw ARRAY { Space( 20 ) } OF oWndChild SIZE oWndChild:nWidth, 150
               
   oBrw:CreateFromCode()
   
   oBrw:aCols[ 1 ]:cHeader = "Empty"

   @ 15.2, 0 RICHEDIT oFooter VAR cFooter SIZE oWndChild:nWidth, 130 OF oWndChild

   @ 70,0  SPLITTER oSplit1 ;
            HORIZONTAL ;
            PREVIOUS CONTROLS oHeader ;
            HINDS CONTROLS oBrw ;
            TOP MARGIN 30 ;
            BOTTOM MARGIN oSplit2:nLast + 50 ;
            SIZE 500, 4  PIXEL ;
            OF oWndChild ;
            STYLE

   @ 225,0  SPLITTER oSplit2 ;
            HORIZONTAL ;
            PREVIOUS CONTROLS oBrw ;
            HINDS CONTROLS oFooter ;
            TOP MARGIN oSplit1:nFirst + 50 ;
            BOTTOM MARGIN 80 ;
            SIZE 500, 4  PIXEL ;
            OF oWndChild ;
            STYLE
   
   ACTIVATE WINDOW oWndChild ;
      ON RESIZE ( oSplit1:Adjust( .T., .F., .T., .T. ), oSplit2:Adjust( .F., .T., .T., .T. ) )
       
return nil  

function ReportOpen()

return nil

function ReportAddColumn()

   local oBrw
   
   if ! Empty( oWndMain:oWndActive )
      oBrw = oWndMain:oWndActive:aControls[ 2 ]
      ADD COLUMN TO oBrw TITLE "Test" DATA Time() SIZE 150
      if oBrw:aCols[ 1 ]:cHeader == "Empty"
         oBrw:DelCol( 1 )
      endif  
      oBrw:Refresh()
   endif  

return nil

function ReportDelColumn()

return nil

function ReportRun()

   local oRpt, aControls, oBrw
   local oHeader, oFooter, n, cHeader, cValue

   if oWndMain:oWndActive != nil

      aControls = oWndMain:oWndActive:aControls    
      oHeader   = aControls[ 1 ]
      oBrw      = aControls[ 2 ]
      oFooter   = aControls[ Len( aControls ) - 2 ]
   
      REPORT oRpt PREVIEW ;
         HEADER oHeader:GetText() ;
         FOOTER oFooter:GetText()

      for n = 1 to Len( oBrw:aCols )
         cHeader = GetHeader( oBrw, n )
         cValue  = GetValue( oBrw, n )
         COLUMN TITLE cHeader DATA cValue
      next  

      END REPORT
     
      ACTIVATE REPORT oRpt
   endif

return nil

static function GetHeader( oBrw, n )

return oBrw:aCols[ n ]:cHeader

static function GetValue( oBrw, n )

return Eval( oBrw:aCols[ n ]:bStrData )

Re: Reports designers comparison

Posted: Tue Jul 09, 2013 7:17 pm
by lucasdebeltran
Antonio,

Thank you.

Please, do not forget to include and set margins (top. left, right, bottom).

Also, I was wondering how you could move the ítems visually:
Image

Best regards

Re: Reports designers comparison

Posted: Tue Jul 09, 2013 7:34 pm
by Antonio Linares
Inspecting the fields to use:

Image

FiveReps.prg

Code: Select all | Expand

#include "FiveWin.ch"
#include "RichEdit.ch"
#include "xbrowse.ch"
#include "splitter.ch"
#include "report.ch"

static oWndMain, oWndDbfs

function Main()
 
   local oBmpTiled , oBar
   local hDLL := LoadLibrary( "Riched20.dll" )
 
   SetDlgGradient( { { 1, RGB( 199, 216, 237 ), RGB( 237, 242, 248 ) } } )

   DEFINE BITMAP oBmpTiled RESOURCE "background"  
 
   DEFINE WINDOW oWndMain TITLE "Reports Builder" MDI ;
      MENU BuildMenu()

   DEFINE BUTTONBAR oBar OF oWndMain 2010 SIZE 70, 70

   DEFINE BUTTON OF oBar PROMPT "New" RESOURCE "new" ACTION ReportNew()

   DEFINE BUTTON OF oBar PROMPT "Open" RESOURCE "open" ACTION ReportOpen()

   DEFINE BUTTON OF oBar PROMPT "DataBases" RESOURCE "database" ACTION Databases() GROUP

   DEFINE BUTTON OF oBar PROMPT "Add" RESOURCE "add" ACTION ReportAddColumn() GROUP

   DEFINE BUTTON OF oBar PROMPT "Del" RESOURCE "del" ACTION ReportDelColumn()

   DEFINE BUTTON OF oBar PROMPT "Run" RESOURCE "run" GROUP ;
      ACTION ReportRun()
     
   DEFINE BUTTON OF oBar PROMPT "Exit" RESOURCE "exit" ;
      ACTION oWndMain:End() GROUP

   ReportNew()

   ACTIVATE WINDOW oWndMain MAXIMIZED ;
      VALID MsgYesNo( "Want to end ?" ) ;
      ON PAINT DrawTiled( hDC, oWndMain, oBmpTiled )  

   oBmpTiled:End()
   
   FreeLibrary( hDLL )
   
return nil

function BuildMenu()

   local oMenu
   
   MENU oMenu
      MENUITEM "Reports"
      MENU
         MENUITEM "New" ACTION ReportNew()
      ENDMENU
   ENDMENU
   
return oMenu

function DataBases( cFileName )

   local oBar, oBrw, aWorkAreas := GetWorkAreas(), cClrBack

   if ! Empty( oWndDbfs )
      oWndDbfs:SetFocus()
      return nil
   endif  

   DEFINE WINDOW oWndDbfs TITLE "DataBases management" MDICHILD

   DEFINE BUTTONBAR oBar OF oWndDbfs 2010 SIZE 70, 70

   DEFINE BUTTON OF oBar PROMPT "Add" RESOURCE "add" ;
      ACTION ( OpenDataBase(), oBrw:SetArray( GetWorkAreas() ), oBrw:SetFocus() )

   DEFINE BUTTON OF oBar PROMPT "Struct" RESOURCE "struct" ;
      ACTION ( Alias( oBrw:nArrayAt ) )->( Struct( cFileName, oBrw ) ) GROUP

   DEFINE BUTTON OF oBar PROMPT "Exit" RESOURCE "exit" ;
      ACTION oWndDbfs:End() GROUP
   
   @ 0, 0 XBROWSE oBrw OF oWndDbfs LINES ;
      ARRAY aWorkAreas AUTOCOLS
   
   oBrw:nMarqueeStyle := MARQSTYLE_HIGHLROW
   oBrw:bClrStd = { || If( oBrw:nArrayAt % 2 == 0, ;
                         { CLR_BLACK, RGB( 198, 255, 198 ) }, ;
                         { CLR_BLACK, RGB( 232, 255, 232 ) } ) }
   oBrw:bClrSel = { || { CLR_WHITE, RGB( 0x33, 0x66, 0xCC ) } }
   cClrBack = Eval( oBrw:bClrSelFocus )[ 2 ]
   oBrw:bClrSelFocus = { || { CLR_WHITE, cClrBack } }
   oBrw:SetColor( CLR_BLACK, RGB( 232, 255, 232 ) )

   oBrw:CreateFromCode()
     
   oBrw:aCols[ 1 ]:cHeader  = "Area"
   oBrw:aCols[ 1 ]:nWidth   = 100
   oBrw:aCols[ 1 ]:bStrData = { || If( Len( oBrw:aArrayData ) > 0, oBrw:nArrayAt, "" ) }
   
   if Empty( aWorkAreas )
      ADD COLUMN TO oBrw HEADER "Alias" DATA oBrw:nArrayAt WIDTH 150
      oBrw:aCols[ 2 ]:bStrData = { || If( Len( oBrw:aArrayData ) > 0, oBrw:aArrayData[ oBrw:nArrayAt, 1 ], "" ) }

      ADD COLUMN TO oBrw HEADER "Rdd" DATA oBrw:nArrayAt WIDTH 100
      oBrw:aCols[ 3 ]:bStrData = { || If( Len( oBrw:aArrayData ) > 0, oBrw:aArrayData[ oBrw:nArrayAt, 3 ], "" ) }
   endif
   
   oWndDbfs:oClient = oBrw
   
   ACTIVATE WINDOW oWndDbfs ;
      VALID ( oWndDbfs := nil, .T. )

return nil

function OpenDataBase( cFileName )

   DEFAULT cFileName := cGetFile( "*.dbf", "Please select a DBF" )

   if File( cFileName )
      USE ( cFileName ) NEW
   endif

return nil

function GetWorkAreas()

   local aWorkAreas := {}, n := 1

   while ! Empty( Alias( n ) )
      AAdd( aWorkAreas, { Alias( n ), Alias( n ), RddName( n++ ) } )
   end  
   
return aWorkAreas

function ReportNew()

   local oWndChild, cHeader := "Header", oHeader, oSplit1, oBrw
   local cFooter := "Footer", oFooter, oSplit2
   
   DEFINE WINDOW oWndChild TITLE "New report" MDICHILD
   
   @ 0, 0 RICHEDIT oHeader VAR cHeader SIZE oWndChild:nWidth, 70 OF oWndChild
   
   @ 5.3, 0 XBROWSE oBrw ARRAY { Space( 20 ) } OF oWndChild SIZE oWndChild:nWidth, 150
               
   oBrw:CreateFromCode()
   
   oBrw:aCols[ 1 ]:cHeader = "Empty"

   @ 15.2, 0 RICHEDIT oFooter VAR cFooter SIZE oWndChild:nWidth, 130 OF oWndChild

   @ 70,0  SPLITTER oSplit1 ;
            HORIZONTAL ;
            PREVIOUS CONTROLS oHeader ;
            HINDS CONTROLS oBrw ;
            TOP MARGIN 30 ;
            BOTTOM MARGIN oSplit2:nLast + 50 ;
            SIZE 500, 4  PIXEL ;
            OF oWndChild ;
            STYLE

   @ 225,0  SPLITTER oSplit2 ;
            HORIZONTAL ;
            PREVIOUS CONTROLS oBrw ;
            HINDS CONTROLS oFooter ;
            TOP MARGIN oSplit1:nFirst + 50 ;
            BOTTOM MARGIN 80 ;
            SIZE 500, 4  PIXEL ;
            OF oWndChild ;
            STYLE
   
   ACTIVATE WINDOW oWndChild ;
      ON RESIZE ( oSplit1:Adjust( .T., .F., .T., .T. ), oSplit2:Adjust( .F., .T., .T., .T. ) )
       
return nil  

function ReportOpen()

return nil

function ReportAddColumn()

   local oBrw
   
   if ! Empty( oWndMain:oWndActive )
      oBrw = oWndMain:oWndActive:aControls[ 2 ]
      ADD COLUMN TO oBrw TITLE "Test" DATA Time() SIZE 150
      if oBrw:aCols[ 1 ]:cHeader == "Empty"
         oBrw:DelCol( 1 )
      endif  
      oBrw:Refresh()
   endif  

return nil

function ReportDelColumn()

return nil

function ReportRun()

   local oRpt, aControls, oBrw
   local oHeader, oFooter, n, cHeader, cValue

   if oWndMain:oWndActive != nil

      aControls = oWndMain:oWndActive:aControls    
      oHeader   = aControls[ 1 ]
      oBrw      = aControls[ 2 ]
      oFooter   = aControls[ Len( aControls ) - 2 ]
   
      REPORT oRpt PREVIEW ;
         HEADER oHeader:GetText() ;
         FOOTER oFooter:GetText()

      for n = 1 to Len( oBrw:aCols )
         cHeader = GetHeader( oBrw, n )
         cValue  = GetValue( oBrw, n )
         COLUMN TITLE cHeader DATA cValue
      next  

      END REPORT
     
      ACTIVATE REPORT oRpt
   endif

return nil

static function GetHeader( oBrw, n )

return oBrw:aCols[ n ]:cHeader

static function GetValue( oBrw, n )

return Eval( oBrw:aCols[ n ]:bStrData )


function Struct( cFileName, oBrwParent )

   local oDlg, oBrw, aFields := DbStruct(), n

   if Empty( aFields ) .and. ! Empty( oBrwParent:oRS )
      for n = 0 to oBrwParent:oRS:Fields:Count - 1
         AAdd( aFields, { oBrwParent:oRS:Fields[ n ]:Name,;
                          oBrwParent:oRS:Fields[ n ]:Type,;
                          oBrwParent:oRS:Fields[ n ]:DefinedSize,;
                          oBrwParent:oRS:Fields[ n ]:NumericScale } )
      next
   endif

   DEFINE DIALOG oDlg TITLE Alias() + " fields" SIZE 400, 400

   @ 0, 0 XBROWSE oBrw ARRAY aFields AUTOCOLS LINES ;
      HEADERS "Name", "Type", "Len", "Dec" ;
      COLSIZES 150, 50, 80, 80

   oBrw:nMarqueeStyle := MARQSTYLE_HIGHLROW
   oBrw:bClrStd = { || If( oBrw:KeyNo() % 2 == 0, ;
                         { CLR_BLACK, RGB( 198, 255, 198 ) }, ;
                         { CLR_BLACK, RGB( 232, 255, 232 ) } ) }
   oBrw:bClrSel = { || { CLR_WHITE, RGB( 0x33, 0x66, 0xCC ) } }
   oBrw:SetColor( CLR_BLACK, RGB( 232, 255, 232 ) )

   oBrw:CreateFromCode()

   oDlg:oClient = oBrw

   ACTIVATE DIALOG oDlg CENTERED ;
      ON INIT ( BuildStructBar( oDlg, oBrw, cFileName ), oDlg:Resize(), oBrw:SetFocus() )

return nil

//----------------------------------------------------------------------------//

function BuildStructBar( oDlg, oBrw, cFileName )

   local oBar

   DEFINE BUTTONBAR oBar OF oDlg 2010 SIZE 70, 70

   DEFINE BUTTON OF oBar PROMPT "Code" RESOURCE "code" ;
      ACTION ( TxtStruct(), oBrw:SetFocus() )

   DEFINE BUTTON OF oBar PROMPT "Exit" RESOURCE "exit" ;
      ACTION oDlg:End() GROUP

return nil

//----------------------------------------------------------------------------//

function TxtStruct()

   local cCode := "local aFields := { ", n

   for n = 1 to FCount()
      if n > 1
         cCode += Space( 27 )
      endif
      cCode += '{ "' + FieldName( n ) + '", "' + ;
               FieldType( n ) + '", ' + ;
               AllTrim( Str( FieldLen( n ) ) ) + ", " + ;
               AllTrim( Str( FieldDec( n ) ) ) + " },;" + CRLF
   next

   cCode = SubStr( cCode, 1, Len( cCode ) - 4 ) + " }" + CRLF + CRLF

   cCode += 'DbCreate( "myfile.dbf", aFields, "' + RddName() + '" )'

   MemoEdit( cCode, "Code" )

return nil

//----------------------------------------------------------------------------//

 

Re: Reports designers comparison

Posted: Tue Jul 09, 2013 8:19 pm
by Antonio Linares
Starting the editing of the report columns:

Image

FiveReps.prg

Code: Select all | Expand

#include "FiveWin.ch"
#include "RichEdit.ch"
#include "xbrowse.ch"
#include "splitter.ch"
#include "report.ch"

static oWndMain, oWndDbfs

//----------------------------------------------------------------------------//

function Main()
 
   local oBmpTiled , oBar
   local hDLL := LoadLibrary( "Riched20.dll" )
 
   SetDlgGradient( { { 1, RGB( 199, 216, 237 ), RGB( 237, 242, 248 ) } } )

   DEFINE BITMAP oBmpTiled RESOURCE "background"  
 
   DEFINE WINDOW oWndMain TITLE "Reports Builder" MDI ;
      MENU BuildMenu()

   DEFINE BUTTONBAR oBar OF oWndMain 2010 SIZE 70, 70

   DEFINE BUTTON OF oBar PROMPT "New" RESOURCE "new" ACTION ReportNew()

   DEFINE BUTTON OF oBar PROMPT "Open" RESOURCE "open" ACTION ReportOpen()

   DEFINE BUTTON OF oBar PROMPT "DataBases" RESOURCE "database" ACTION Databases() GROUP

   DEFINE BUTTON OF oBar PROMPT "Add" RESOURCE "add" ACTION ReportAddColumn() GROUP

   DEFINE BUTTON OF oBar PROMPT "Edit" RESOURCE "edit" ACTION ReportEditColumn()

   DEFINE BUTTON OF oBar PROMPT "Del" RESOURCE "del" ACTION ReportDelColumn()

   DEFINE BUTTON OF oBar PROMPT "Run" RESOURCE "run" GROUP ;
      ACTION ReportRun()
     
   DEFINE BUTTON OF oBar PROMPT "Exit" RESOURCE "exit" ;
      ACTION oWndMain:End() GROUP

   ReportNew()

   ACTIVATE WINDOW oWndMain MAXIMIZED ;
      VALID MsgYesNo( "Want to end ?" ) ;
      ON PAINT DrawTiled( hDC, oWndMain, oBmpTiled )  

   oBmpTiled:End()
   
   FreeLibrary( hDLL )
   
return nil

//----------------------------------------------------------------------------//

function BuildMenu()

   local oMenu
   
   MENU oMenu
      MENUITEM "Reports"
      MENU
         MENUITEM "New" ACTION ReportNew()
      ENDMENU
   ENDMENU
   
return oMenu

//----------------------------------------------------------------------------//

function DataBases( cFileName )

   local oBar, oBrw, aWorkAreas := GetWorkAreas(), cClrBack

   if ! Empty( oWndDbfs )
      oWndDbfs:SetFocus()
      return nil
   endif  

   DEFINE WINDOW oWndDbfs TITLE "DataBases management" MDICHILD

   DEFINE BUTTONBAR oBar OF oWndDbfs 2010 SIZE 70, 70

   DEFINE BUTTON OF oBar PROMPT "Add" RESOURCE "add" ;
      ACTION ( OpenDataBase(), oBrw:SetArray( GetWorkAreas() ), oBrw:SetFocus() )

   DEFINE BUTTON OF oBar PROMPT "Struct" RESOURCE "struct" ;
      ACTION ( Alias( oBrw:nArrayAt ) )->( Struct( cFileName, oBrw ) ) GROUP

   DEFINE BUTTON OF oBar PROMPT "Exit" RESOURCE "exit" ;
      ACTION oWndDbfs:End() GROUP
   
   @ 0, 0 XBROWSE oBrw OF oWndDbfs LINES ;
      ARRAY aWorkAreas AUTOCOLS
   
   oBrw:nMarqueeStyle := MARQSTYLE_HIGHLROW
   oBrw:bClrStd = { || If( oBrw:nArrayAt % 2 == 0, ;
                         { CLR_BLACK, RGB( 198, 255, 198 ) }, ;
                         { CLR_BLACK, RGB( 232, 255, 232 ) } ) }
   oBrw:bClrSel = { || { CLR_WHITE, RGB( 0x33, 0x66, 0xCC ) } }
   cClrBack = Eval( oBrw:bClrSelFocus )[ 2 ]
   oBrw:bClrSelFocus = { || { CLR_WHITE, cClrBack } }
   oBrw:SetColor( CLR_BLACK, RGB( 232, 255, 232 ) )

   oBrw:CreateFromCode()
     
   oBrw:aCols[ 1 ]:cHeader  = "Area"
   oBrw:aCols[ 1 ]:nWidth   = 100
   oBrw:aCols[ 1 ]:bStrData = { || If( Len( oBrw:aArrayData ) > 0, oBrw:nArrayAt, "" ) }
   
   if Empty( aWorkAreas )
      ADD COLUMN TO oBrw HEADER "Alias" DATA oBrw:nArrayAt WIDTH 150
      oBrw:aCols[ 2 ]:bStrData = { || If( Len( oBrw:aArrayData ) > 0, oBrw:aArrayData[ oBrw:nArrayAt, 1 ], "" ) }

      ADD COLUMN TO oBrw HEADER "Rdd" DATA oBrw:nArrayAt WIDTH 100
      oBrw:aCols[ 3 ]:bStrData = { || If( Len( oBrw:aArrayData ) > 0, oBrw:aArrayData[ oBrw:nArrayAt, 3 ], "" ) }
   endif
   
   oWndDbfs:oClient = oBrw
   
   ACTIVATE WINDOW oWndDbfs ;
      VALID ( oWndDbfs := nil, .T. )

return nil

//----------------------------------------------------------------------------//

function OpenDataBase( cFileName )

   DEFAULT cFileName := cGetFile( "*.dbf", "Please select a DBF" )

   if File( cFileName )
      USE ( cFileName ) NEW
   endif

return nil

//----------------------------------------------------------------------------//

function GetWorkAreas()

   local aWorkAreas := {}, n := 1

   while ! Empty( Alias( n ) )
      AAdd( aWorkAreas, { Alias( n ), Alias( n ), RddName( n++ ) } )
   end  
   
return aWorkAreas

//----------------------------------------------------------------------------//

function ReportEditColumn()

   local oDlg, oBrw := oWndMain:oWndActive:aControls[ 2 ]
   local oCol := oBrw:aCols[ oBrw:nColSel ]
   local cHeader := PadR( oCol:cHeader, 100 )
   
   DEFINE DIALOG oDlg TITLE "Column properties" SIZE 400, 300
   
   @ 0.5, 1 SAY "Header:"

   @ 0.6, 3.9 GET cHeader SIZE 150, 11
   
   @ 1.5, 1 SAY "Data:"

   @ 1.7, 3.9 GET oCol:cExpr SIZE 150, 11 ;
      ACTION MsgInfo( "expression builder" )

   @ 2.5, 1 SAY "Width:"

   @ 2.7, 3.9 GET oBrw:aCols[ oBrw:nColSel ]:nWidth SIZE 70, 4 SPINNER

   @ 7, 7 BUTTON "&Ok" OF oDlg SIZE 45, 13 ;
      ACTION ( oCol:cHeader := RTrim( cHeader ), oBrw:Refresh(), oDlg:End() )

   @ 7, 18 BUTTON "&Cancel" OF oDlg SIZE 45, 13 ACTION oDlg:End()
   
   ACTIVATE DIALOG oDlg CENTERED

return nil

//----------------------------------------------------------------------------//

function ReportNew()

   local oWndChild, cHeader := "Header", oHeader, oSplit1, oBrw
   local cFooter := "Footer", oFooter, oSplit2
   
   DEFINE WINDOW oWndChild TITLE "New report" MDICHILD
   
   @ 0, 0 RICHEDIT oHeader VAR cHeader SIZE oWndChild:nWidth, 70 OF oWndChild
   
   @ 5.3, 0 XBROWSE oBrw ARRAY { Space( 20 ) } OF oWndChild SIZE oWndChild:nWidth, 150
               
   oBrw:CreateFromCode()
   
   oBrw:aCols[ 1 ]:cHeader = "Empty"
   oBrw:aCols[ 1 ]:cExpr   = "nil"

   @ 15.2, 0 RICHEDIT oFooter VAR cFooter SIZE oWndChild:nWidth, 130 OF oWndChild

   @ 70,0  SPLITTER oSplit1 ;
            HORIZONTAL ;
            PREVIOUS CONTROLS oHeader ;
            HINDS CONTROLS oBrw ;
            TOP MARGIN 30 ;
            BOTTOM MARGIN oSplit2:nLast + 50 ;
            SIZE 500, 4  PIXEL ;
            OF oWndChild ;
            STYLE

   @ 225,0  SPLITTER oSplit2 ;
            HORIZONTAL ;
            PREVIOUS CONTROLS oBrw ;
            HINDS CONTROLS oFooter ;
            TOP MARGIN oSplit1:nFirst + 50 ;
            BOTTOM MARGIN 80 ;
            SIZE 500, 4  PIXEL ;
            OF oWndChild ;
            STYLE
   
   ACTIVATE WINDOW oWndChild ;
      ON RESIZE ( oSplit1:Adjust( .T., .F., .T., .T. ), oSplit2:Adjust( .F., .T., .T., .T. ) )
       
return nil  

//----------------------------------------------------------------------------//

function ReportOpen()

return nil

//----------------------------------------------------------------------------//

function ReportAddColumn()

   local oBrw
   
   if ! Empty( oWndMain:oWndActive )
      oBrw = oWndMain:oWndActive:aControls[ 2 ]
      ADD COLUMN TO oBrw TITLE "Test" DATA Time() SIZE 150
      ATail( oBrw:aCols ):cExpr = "Time()"
      if oBrw:aCols[ 1 ]:cHeader == "Empty"
         oBrw:DelCol( 1 )
      endif  
      oBrw:Refresh()
   endif  

return nil

//----------------------------------------------------------------------------//

function ReportDelColumn()

return nil

//----------------------------------------------------------------------------//

function ReportRun()

   local oRpt, aControls, oBrw
   local oHeader, oFooter, n

   if oWndMain:oWndActive != nil

      aControls = oWndMain:oWndActive:aControls    
      oHeader   = aControls[ 1 ]
      oBrw      = aControls[ 2 ]
      oFooter   = aControls[ Len( aControls ) - 2 ]
   
      REPORT oRpt PREVIEW ;
         HEADER oHeader:GetText() ;
         FOOTER oFooter:GetText()

      for n = 1 to Len( oBrw:aCols )
         RptAddColumn( { GetHeader( oBrw, n ) },, { GetValue( oBrw, n ) } )
      next  

      END REPORT
     
      ACTIVATE REPORT oRpt
   endif

return nil

//----------------------------------------------------------------------------//

static function GetHeader( oBrw, n )

return { || oBrw:aCols[ n ]:cHeader }

//----------------------------------------------------------------------------//

static function GetValue( oBrw, n )

return { || oBrw:aCols[ n ]:bStrData }

//----------------------------------------------------------------------------//


function Struct( cFileName, oBrwParent )

   local oDlg, oBrw, aFields := DbStruct(), n

   if Empty( aFields ) .and. ! Empty( oBrwParent:oRS )
      for n = 0 to oBrwParent:oRS:Fields:Count - 1
         AAdd( aFields, { oBrwParent:oRS:Fields[ n ]:Name,;
                          oBrwParent:oRS:Fields[ n ]:Type,;
                          oBrwParent:oRS:Fields[ n ]:DefinedSize,;
                          oBrwParent:oRS:Fields[ n ]:NumericScale } )
      next
   endif

   DEFINE DIALOG oDlg TITLE Alias() + " fields" SIZE 400, 400

   @ 0, 0 XBROWSE oBrw ARRAY aFields AUTOCOLS LINES ;
      HEADERS "Name", "Type", "Len", "Dec" ;
      COLSIZES 150, 50, 80, 80

   oBrw:nMarqueeStyle := MARQSTYLE_HIGHLROW
   oBrw:bClrStd = { || If( oBrw:KeyNo() % 2 == 0, ;
                         { CLR_BLACK, RGB( 198, 255, 198 ) }, ;
                         { CLR_BLACK, RGB( 232, 255, 232 ) } ) }
   oBrw:bClrSel = { || { CLR_WHITE, RGB( 0x33, 0x66, 0xCC ) } }
   oBrw:SetColor( CLR_BLACK, RGB( 232, 255, 232 ) )

   oBrw:CreateFromCode()

   oDlg:oClient = oBrw

   ACTIVATE DIALOG oDlg CENTERED ;
      ON INIT ( BuildStructBar( oDlg, oBrw, cFileName ), oDlg:Resize(), oBrw:SetFocus() )

return nil

//----------------------------------------------------------------------------//

function BuildStructBar( oDlg, oBrw, cFileName )

   local oBar

   DEFINE BUTTONBAR oBar OF oDlg 2010 SIZE 70, 70

   DEFINE BUTTON OF oBar PROMPT "Code" RESOURCE "code" ;
      ACTION ( TxtStruct(), oBrw:SetFocus() )

   DEFINE BUTTON OF oBar PROMPT "Exit" RESOURCE "exit" ;
      ACTION oDlg:End() GROUP

return nil

//----------------------------------------------------------------------------//

function TxtStruct()

   local cCode := "local aFields := { ", n

   for n = 1 to FCount()
      if n > 1
         cCode += Space( 27 )
      endif
      cCode += '{ "' + FieldName( n ) + '", "' + ;
               FieldType( n ) + '", ' + ;
               AllTrim( Str( FieldLen( n ) ) ) + ", " + ;
               AllTrim( Str( FieldDec( n ) ) ) + " },;" + CRLF
   next

   cCode = SubStr( cCode, 1, Len( cCode ) - 4 ) + " }" + CRLF + CRLF

   cCode += 'DbCreate( "myfile.dbf", aFields, "' + RddName() + '" )'

   MemoEdit( cCode, "Code" )

return nil

//----------------------------------------------------------------------------//

 

Re: Reports designers comparison

Posted: Tue Jul 09, 2013 9:16 pm
by Marco Turco
Hi Antonio,
I personally think the best report is FastReport and in my opinion you should take over the job Spirin already did.
It is a non sense you lost further time to develop tReport, it can't compete with specialized report products like FastReport or Crystal Report and we need professional solutions, not solutions for programmers or beta testers.

Re: Reports designers comparison

Posted: Wed Jul 10, 2013 6:50 am
by Antonio Linares
Marco,

It is just a GUI for FWH Class TReport to see how far we can go :-)

I have to create many reports soon, so I want to use our own designer :-)

Re: Reports designers comparison

Posted: Thu Jul 11, 2013 5:48 am
by HunterEC
Antonio:

First of all, your work in progress looks great ! Very welcomed !
Some suggestions:
1. A way to include graphics within the report (pie, line, bar, stacked bar, etc.)
2. Data and headers in different orientation than the rest of the report

We value a lot your continued effort in pushing FW's boundaries !

Re: Reports designers comparison

Posted: Thu Jul 11, 2013 12:49 pm
by ADutheil
Antonio,

Something I miss a lot in treport is group headers.

Re: Reports designers comparison

Posted: Fri Jul 12, 2013 11:53 am
by Silvio.Falconi
Antonio,
How make graphics dot document ad factura or order ?

Re: Reports designers comparison

Posted: Fri Jul 12, 2013 2:20 pm
by arthursilvestre
I am new to this forum and talk of Brazil.

I think the best class is FastReport. There's a whole world to enjoy and do not need external files to generate the report, everything can be done in the code base. For mair than the standard method is the use of the *. Fr3, he has the possibility to use it only alert by code. I have a routine Termination of Employees made ​​alert by code. What better way to work the groups headers, footer and master data. Having also a good criterion would be the 'Script', where it is proposed to use a setting of three programming languages ​​suggested to change the display of the report. I support FastReport and with a little effort all be able to use for longer than initially appears to be a bit tricky.

Hug.

Re: Reports designers comparison

Posted: Mon Jul 15, 2013 2:01 pm
by James Bott
André,

Something I miss a lot in treport is group headers.


We have always had group headers. Example:

Code: Select all | Expand

  GROUP on invno;
      HEADER invno;
      FOOTER "Total"
 


Regards,
James

Re: Reports designers comparison

Posted: Mon Jul 15, 2013 4:59 pm
by ADutheil
James,

I know this one. I meant a common header for multiple colums just like SetGroupHeader method in xbrowse. This kind of header is lost when using the report function from xbrowse.