Page 1 of 1

Xbrowse totals

Posted: Sat Mar 28, 2015 6:31 pm
by hag
I would like a user to a number of records (as they select) in an xbrowse and insert a subtotal of the records.
for example
records:
1
2
3
4
Insert a sub total hear of records 1-4
5
6
7
8
Insert a sub total hear of records 5-8
9
10
total here 1-10

I hope you understand my example :D

Re: Xbrowse totals

Posted: Mon Apr 06, 2015 1:37 am
by nageswaragunupudi
You may test this sample.
You can use your own data too. Instructions for using your own data are contained in the code.

Code: Select all

/*
* Inserting Subtotals
* Automatically recalculated
* When individual items are edited
*
*/

#include "fivewin.ch"

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

function Main()

   local aData, n
   local aHead

   FWNumFormat( 'A', .t. )

   /*
      This works only with Arrays. We are using test data aData
      Instead it can be any Array of real Data. Conditions are that
      a) First column should be serial number
      b) second column should be some description
      Other columns can be of any datatype
   */

   aData    := {}
   for n := 1 to 10
      AAdd( aData, { n, "Item-" + StrZero( n, 2 ), ;
         HB_RandomInt( 1, 999 ), HB_RandomInt( 1, 9999 ), ;
         Space( 5 ), ;
         HB_RandomInt( 1, 9999 ) } )
   next

   /*
      Call function BrowseWithSubTotals( aData, [aHead], [aSumCols] )
      Optionally we can provide an array of column headers in the 2nd param
      Optionally we can specify which columns are to be sub-totalled and totalled.
      If ommitted all numeric columns are totalled.
   */

   BrowseWithSubTotals( aData, aHead, { 3, 4, 6 } )

return nil

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

function BrowseWithSubTotals( aData, aHead, aSumCols )

   local oDlg, oBrw, oFont
   local nCol

   if Empty( aSumCols )
      aSumCols := {}
      AEval( aData[ 1 ], { |u,i| If( ValType( u ) == 'N', AAdd( aSumCols, i ), nil ) }, 3 )
   endif

   DEFAULT aHead := { "SlNo", "Item" }

   DEFINE FONT oFont NAME "TAHOMA" SIZE 0,-14
   DEFINE DIALOG oDlg SIZE 700,500 PIXEL FONT oFont

   @ 30,10 XBROWSE oBrw SIZE -10,-10 PIXEL OF oDlg ;
      DATASOURCE aData ;
      AUTOCOLS HEADERS aHead ;
      COLSIZES 40 ;
      CELL LINES FOOTERS NOBORDER FASTEDIT

   for Each nCol in aSumCols
      if ValType( aData[ 1, nCol ] ) == 'N'
         WITH OBJECT oBrw:aCols[ nCol ]
            :bEditValue    := { |x,o| If( x == nil .or. ValType( oBrw:aRow[ o:nArrayCol ] ) == 'B', ;
                                     XEval( oBrw:aRow[ o:nArrayCol ] ), ;
                                     oBrw:aRow[ o:nArrayCol ] := x ) }

            :nEditType     := EDIT_GET
            :cEditPicture  := NumPict( 10, 2 )
            :bEditWhen     := { || ! IsTotalRow(  oBrw:aRow )  }
            :bOnChange     := { || oBrw:Refresh() }
            :nFooterType   := AGGR_SUM
            :bSumCondition := { |n,o| ! IsTotalRow( o:oBrw:aRow ) }
         END
      endif
   next

   WITH OBJECT oBrw
      :nStretchCol   := STRETCHCOL_WIDEST
      :bClrStd       := { || { CLR_BLACK, If( IsTotalRow( oBrw:aRow ), CLR_YELLOW, CLR_WHITE ) } }
      :bChange       := { || oDlg:AEvalWhen() }
      :MakeTotals()
      //
      :CreateFromCode()
   END

   @ 10, 10 BUTTON "Insert SubTotal" SIZE 70,14 PIXEL OF oDlg ;
      ACTION InsertSubTotal( oBrw ) ;
      WHEN ! IsTotalRow( oBrw:aRow )
   @ 10, 90 BUTTON "Remove SubTotal" SIZE 70,14 PIXEL OF oDlg ;
      ACTION oBrw:Delete() ;
      WHEN IsTotalRow( oBrw:aRow )

   ACTIVATE DIALOG oDlg CENTERED
   RELEASE FONT oFont

return nil

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

static function InsertSubTotal( oBrw )

   local n, oCol, nRowFrom := 0, nRowLast

   if .not. IsTotalRow( oBrw:aRow )
      nRowLast    := oBrw:nArrayAt
      for n := nRowLast  to 1 step -1
         if IsTotalRow( oBrw:aArrayData[ n ] )
            EXIT
         else
            nRowFrom    := n
         endif
      next
      if nRowFrom > 0
         if nRowLast == Len( oBrw:aArrayData )
            AAdd( oBrw:aArrayData, Array( Len( oBrw:aRow ) ) )
         else
            AIns( oBrw:aArrayData, nRowLast + 1, Array( Len( oBrw:aRow ) ), .t. )
         endif
         oBrw:aArrayData[ nRowLast + 1, 2 ]   := "Sum : " + ;
               cValToChar( oBrw:aArrayData[ nRowFrom, 1 ] ) + "-" + ;
               cValToChar( oBrw:aArrayData[ nRowLast, 1 ] )

         for each oCol in oBrw:aCols
            if oCol:nFooterType == AGGR_SUM .and. ! Empty( oCol:nArrayCol )
               oBrw:aArrayData[ nRowLast + 1, oCol:nArrayCol ] := ;
                  MakeSumBlock( oBrw:aArrayData, oCol:nArrayCol, nRowFrom, nRowLast )
            endif
         next
         oBrw:nArrayAt  := nRowLast + 1
         oBrw:nRowSel   := oBrw:nArrayAt
         oBrw:oWnd:AEvalWhen()
         oBrw:Refresh()
         oBrw:SetFocus()
      endif
   endif

return nil

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

static function MakeSumBlock( aData, nCol, nRowFrom, nRowLast )

   local nRows := nRowLast - nRowFrom + 1
   local aRows := {}
   local n

   for n := nRowFrom to nRowLast
      AAdd( aRows, aData[ n ] )
   next

return { || FW_ArrSum( aRows, nCol ) }

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

static function IsTotalRow( aRow )
return Empty( aRow[ 1 ] )

//----------------------------------------------------------------------------//
 
Image

Re: Xbrowse totals

Posted: Mon Apr 06, 2015 12:42 pm
by Silvio.Falconi
Wonderfull

Re: Xbrowse totals

Posted: Mon Apr 06, 2015 4:05 pm
by hag
Thanks for the help. I'll give it a try.