Article ID:qFRM003
Date Revised:August 15, 1997
Keywords:Date field, Quicken, Keypress, OOP
See Also:Click here to download txtdate.zip 

Question: How can a date field in VFP be made to work like Quicken?

Answer: The Quicken finance management program uses several handy keyboard shortcut keys like + to increment and - to decrement a date. It also has keys to goto the first/last day of the month and year as well as today.

NOTE: VFP5.0a has added +/- key handling when a date field is all selected.

To get the full functionality of Quicken requires just a little code in the KeyPress method of a TextBox subclass. The txtdate.zip file contains a class library and a sample form using the txtDate class.

To get VFP5.0 to use this class for date fields just Use the Tools/Options/Field Mapping page to attach this class to Date fields.

Here is the code I've used in the txtDate.KeyPress method:

LPARAMETERS nKeyCode, nShiftAltCtrl

* This TextBox subclass provides Quicken date field keys to be used to adjust
* a date field.

* Keystroke           Function
* ---------           --------
* +, =, UpArrow       increment 1 day
* -, DownArrow        decrement 1 day
* M, Shift-UpArrow    First day of month, then back 1 month
* H, Shift-DownArrow  Last day of month, then to end of next month
* Y                   First day of year, then back one year
* R                   Last day of year, then to end of next year
* T                   Today

* To remember M, H, Y and R think of MontH and YeaR

* 07-Aug-97 added arrow keys, changed to case from if

local lcKey, lnMonth, lnDay, lnYear

lcKey = upper( chr( nKeyCode ) )

do case
   case nKeyCode = 5  && up arrow
      lcKey = '-'
   case nKeyCode = 24 && down arrow
      lcKey = '+'
   case nKeyCode = 56 && shift up arrow
      lcKey = 'M'
   case nKeyCode = 50 && shift down arrow
      lcKey = 'H'
endcase

if ! ( lcKey $ "T+-=MHYR" )
   * 07-Jul-97
   * this appears to be a bug in 5.0a we should pass the other keystrokes on
   * but it causes them to appear twice in the field, so just don't DoDefault()
   *   DoDefault( nKeyCode, nShiftAltCtrl )
   return
endif

nodefault  && prevent dings from keys not normally allowed in date field

* 07-Jul-97
* again the bug would appear to be preventing the use of DoDefault to pass
* the key onto cTextBox, so send it using :: instead
* DoDefault( nKeyCode, nShiftAltCtrl ) causes ding
cTextBox::KeyPress( nKeyCode, nShiftAltCtrl )


if ( empty( this.Value ) )
   * start this at today
   this.Value = date()
endif

if ( m.lcKey == "T" )
   this.Value = date()
   return
endif

if ( m.lcKey $ '+=' )
   this.Value = this.Value + 1
   return
endif

if ( m.lcKey == '-' )
   this.Value = this.Value - 1
   return
endif

lnMonth = month( this.Value )
lnDay   = day( this.Value )
lnYear  = year( this.Value )

do case
   case ( m.lcKey == "M" )
      if ( day( this.Value ) = 1 )
         this.Value = gomonth( this.Value, -1 )
      else
         lnDay = 1
         this.Value = DateMDY( lnMonth, lnDay, lnYear )
      endif

   case ( m.lcKey == "H" )
      this.Value = gomonth( this.Value+1, 1 )
      lnMonth = month( this.Value )
      lnYear = year( this.Value )
      this.Value = DateMDY( lnMonth, 1, lnYear ) - 1

   case ( m.lcKey == "Y" )
      if ( ( lnDay = 1 ) and ( lnMonth = 1 ) )
         this.Value = gomonth( this.Value, -12 )
      else
         lnMonth = 1
         lnDay = 1
         this.Value = DateMDY( lnMonth, lnDay, lnYear )
      endif

   case ( m.lcKey == "R" )
      if ( ( lnDay = 31 ) and ( lnMonth = 12 ) )
         this.Value = gomonth( this.Value, 12 )
      else
         lnMonth = 12
         lnDay = 31
         this.Value = DateMDY( lnMonth, lnDay, lnYear )
      endif

endcase


1