Here is a small sample. Not perfect, but can be improved upon. This sample uses the sales.dbf in the fwh\samples folder.
This is the logic I was using in the DOS-Clipper days. The skip block here is adopted from samples provided by Clipper for DBU and Browse in their sample folder. This needs to be improved but this is a working sample with a few minor bugs to be resolved.
#include "FiveWin.Ch"
#include "ord.ch"
#include "xbrowse.ch"
REQUEST DBFCDX
static aNew
static lAppend := .f.
//------------------------------------------------------------------//
function Main()
local oDlg, oBrw
USE SALES NEW EXCLUSIVE
aNew := Array( Sales->( FCount() ) )
BlankArray()
DEFINE DIALOG oDlg SIZE 440,440 PIXEL
@ 10,10 XBROWSE oBrw SIZE 200,200 PIXEL OF oDlg ;
COLUMNS 'Date', 'Client', 'Article' ;
ALIAS 'SALES' LINES CELL FASTEDIT
oBrw:aCols[ 1 ]:bEditValue := { |x| If( x == nil, If( Sales->( RecNo() > LastRec() ), aNew[ 1 ], Sales->Date ), ;
If( Sales->( RecNo() > LastRec() ), aNew[ 1 ] := x, Sales->Date := x ) ) }
oBrw:aCols[ 2 ]:bEditValue := { |x| If( x == nil, If( Sales->( RecNo() > LastRec() ), aNew[ 2 ], Sales->Client ), ;
If( Sales->( RecNo() > LastRec() ), aNew[ 2 ] := x, Sales->Client := x ) ) }
oBrw:aCols[ 3 ]:bEditValue := { |x| If( x == nil, If( Sales->( RecNo() > LastRec() ), aNew[ 3 ], Sales->Article ), ;
If( Sales->( RecNo() > LastRec() ), aNew[ 3 ] := x, Sales->Article := x ) ) }
AEval( oBrw:aCols, { |o| o:nEditType := EDIT_GET } )
AEval( oBrw:aCols, { |o| o:bOnChange := { || OnChange( oBrw ) } } )
ADD TO oBrw DATA RecNo() HEADER 'RecNo'
oBrw:bSkip := { |n| Sales->( NewSkipper( n ) ) }
oBrw:bKeyCount := { || Sales->( LastRec() ) + If( lAppend, 1, 0 ) }
oBrw:bKeyNo := { || Sales->( RecNo() ) }
oBrw:bPastEof := { || If( ! Eof(), ( lAppend := .t., BlankArray(), oBrw:GoDown(), oBrw:KeyCount() ), nil ) }
oBrw:bChange := { || If( lAppend .and. ! Eof(), ( lAppend := .f., BlankArray(), oBrw:Refresh() ), nil ) }
oBrw:bRClicked := { || xbrowse( anew ) }
oBrw:CreateFromCode()
ACTIVATE DIALOG oDlg CENTERED
CLOSE SALES
return ( 0 )
//------------------------------------------------------------------//
init procedure PrgInit
SET DATE ITALIAN
SET CENTURY ON
SET EPOCH TO YEAR(DATE())-50
SET DELETED ON
SET EXCLUSIVE OFF
RDDSetDefault( 'DBFCDX' )
SET OPTIMIZE ON
return
//------------------------------------------------------------------//
exit procedure PrgExit
SET RESOURCES TO
return
//------------------------------------------------------------------//
static function NewSkipper( nSkip )
local nSkipped := 0
DEFAULT nSkip := 1
if nSkip == 0
// DbSkip( 0 )
elseif nSkip > 0
do while nSkipped < nSkip .and. ! Eof()
DbSkip( 1 )
if Eof()
if lAppend
nSkipped++
else
DbSkip( -1 )
endif
exit
endif
nSkipped++
enddo
else
do while nSkipped > nSkip
DbSkip( -1 )
if Bof()
DbGoTop()
Exit
else
nSkipped--
endif
enddo
endif
return nSkipped
//------------------------------------------------------------------//
static function BlankArray()
local n
for n := 1 to Len( aNew )
aNew[ n ] := Blank( Sales->( FieldGet( n ) ) )
next n
return nil
//------------------------------------------------------------------//
static function OnChange( oBrw )
if Sales->( Eof() )
if ! Empty( aNew[ 1 ] ) .and. ! Empty( aNew[ 2 ] )
Sales->( DbAppend() )
Sales->Date := aNew[ 1 ]
Sales->Client := aNew[ 2 ]
Sales->Article := aNew[ 3 ]
oBrw:GoBottom()
oBrw:Refresh()
endif
endif
return nil
//------------------------------------------------------------------//