FWH 16.09: RowSet AutoAppend feature

FWH 16.09: RowSet AutoAppend feature

Postby nageswaragunupudi » Tue Oct 25, 2016 4:30 pm

There are quite a few situations where providing FastEdit (inline edit) is very appropriate. Most of such situations also require auto appending new blank rows inline. That is, when the users presses down arrow key or completes edit of last row, a new blank row should be automatically created at the end of the browse. Providing buttons and dialogs for editing/adding rows retards data entry speeds and reduces productivity of the end user.

Many programmers know how to auto append blank rows using oBrw:bPastEof. Care should also be taken that new blank rows are not created when already a blank row created is not yet committed and if the user leaves the blank row, it should be removed. The programming code required for this is a bit complex.

Yet all this is possible only if the data-source being browsed supports this feature. Examples are Arrays, RecordSets opened with adLockBatchOptimistic lock.

FWH RowSet supports this feature. Not only it supports but also takes away totally the burden of writing this complex code. What all required to have a fast edit browse with safe auto-append facility is :
Code: Select all  Expand view

oRs := oCn:RowSet( cTable/cSql )
oRs:lAutoAppend  := .t.
XBROWSER oRs FASTEDIT
 

It is ready.

We can turn oRs:lAutoAppend ON only when we create a browse with autoappend and turn off at other times.

fwh\samples\maria09.prg (FWH 16.09) demonstrates this feature. The program is reproduced below.

In addition to auto-append feature, this program also demonstrates other features that are usually required in similar situations.

1) Case: With FWHMYSQL, we can specify if a field should have only UPPER CASE or lower case or Proper Case either at database level or at program level. When this feature is enabled, without using any picture clause for Gets, whatever be the case in which the user enters data, the data is converted to the required case while storing in the database. (The automatic case conversion is done only for pure ansi-strings and follow the (x)Harbour CodePage setting.)

2) Using default values at database level. The values are automatically refreshed in the browse when data is saved.

3) Default Values at program-level: When we use auto-append feature, we also require some columns to have default values which can not be modified by the user. The program demonstrates how to set default values at runtime when required.

Syntax: oRs:SetDefault( cFieldName, uDefaultValue, [lReadOnly = .t.] )
When read-only attribute is set, xbrowse, datarow do not allow user entry and even the rowset does not accept any modification by user.

4) Calculated Fields: From MySql server version 5.7 onwards it is possible to have calculated fields in the database.

5) Browse totals: Most such cases of browses require totals and need to be updated with every modification and appending.

maria09.prg
Code: Select all  Expand view

#include "fivewin.ch"

static cHost      := "localhost"
static cUser      := "gnrao"
static cPassword  := "secret"
static cDb        := "fwh"

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

function Main()

   local oRs
   local cTable   := "testauto"
   local nDocID

   SetGetColorFocus()
   FWNumFormat( 'A', .t. )

   // Check and create table
   if .not. db():TableExists( cTable ) .or. ;
      MsgYesNo( "ReCreate " + cTable )

      if db():TableExists( cTable )
         db():DropTable( cTable )
      endif

      if .not. db():CreateTable( cTable, { ;
         { "docid",  'N',  4, 0 }, ;
         { "code",   'C',  2, 0, "comment 'case:upper'"  }, ;
         { "name",   'C', 20, 0, "comment 'case:proper'" }, ;
         { "qty",    'N',  6, 3, "DEFAULT 1" }, ;
         { "rate",   'N',  5, 2, "DEFAULT 10" }, ;
         { "amount=qty*rate", 'N', 12, 2 } }, ;
         .t., "latin1" )

         ? "Table create error"
         return nil

      endif

   endif
   // end: Create table

   // Main code starts
   nDocID            := 4302  // id in parent table
   oRs               := db():RowSet( "SELECT * FROM `testauto` WHERE `docid` = ?", { nDocID } )
   oRs:lAutoAppend   := .t.  // Only one line of code to enable auto append feature

   oRs:SetDefault( "docid", nDocID ) // All rows should contain this value

   /*
   * Later to use the same RowSet for another DocID,
   * oRs:ReQuery( { nOtherDocID } )
   * oRs:SetDefault( "docid", nOtherDocID )
   *
   */


   XBROWSER oRs FASTEDIT TITLE "FWH-ROWSET : AutoAppend" SETUP SetUpBrowse( oBrw )

   db():Close()

return nil

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

static function SetupBrowse( oBrw )

   WITH OBJECT oBrw

      // separate color for row being appended
      :bClrRowFocus        := { || If( oBrw:oDbf:ID == 0, { CLR_BLACK, 0xAEEDFF }, { CLR_BLACK, RGB(185,220,255) } ) }

      // Display total in footers
      :lFooter             := .t.
      :qty:nFooterType     := AGGR_SUM
      :Amount:nFooterType  := AGGR_SUM
      :MakeTotals()

      // Show some message on blank screen
      :bPainted   := { |dc,ps,brw| If( brw:nLen == 0, brw:SayText( "Press Down Arrow to Start" ), nil ) }

   END

return nil

return nil

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

function db()

   static oCn

   if oCn == nil

      EDITVARS cHost, cUser, cPassword, cDB

      FWCONNECT oCn HOST cHost USER cUser PASSWORD cPassword DATABASE cDb
      if oCn == nil
         ? "Connect Fail"
         QUIT
      endif
   endif

return oCn

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


As the functionality of this sample can not be demonstrated with screen-shot, a video is provided.

Video Link

http://autode.sk/2er5ghp
Regards

G. N. Rao.
Hyderabad, India
User avatar
nageswaragunupudi
 
Posts: 10308
Joined: Sun Nov 19, 2006 5:22 am
Location: India

Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 53 guests