Wednesday, January 24, 2018

GridX Class

Imagine yourself designing a grid and saying to yourself "it looks awesome, they will definitely love this!", then installing it on your clients' units then receiving complaints from some users such as "my eyes are weak, can't you make the font bigger?" or "the colors are hurting my eyes" or "can you change the order of the columns please? I want this one to come first, then this one, then...."; and some more airing of dissatisfaction.  Well, either you will go back to the drawing board and change the appearances of your grids and recompile to satisfy them or you will argue back saying "that is the way it is, live with it!".  And either one of those will dissatisfy either you or your client.

Well worry no more, here now is my latest class on ssUltimate library that deals with Grid, i.e., GridX.  This combines all the power of all my other classes for grid object (AnchorSizer, AnchorX, GridSort, GridLock, and GridSortLock) into this one class, and more.

With this class now, you are giving your users the power to manipulate further grid on runtime based on their taste.  This class retains their last selections that whatever have been set when they exit the form, the grid will be loaded back to the last arrangement and look; just the way they left it.  And the good thing is, customization is per workstation.  Different users, different tastes.

So when they started complaining, you can casually tell them "Oh, you can adjust the appearance based on your taste", with a smile.



Wednesday, January 3, 2018

Google Calendar on VFP Form

Well, this comes from a request inside Foxite on how we can embed Google Calendar on form.  Being foxy, I originally pointed to the late Guillermo Carrero's FoxScheduler instead:  
https://sites.google.com/site/foxscheduler/

However, while it looks okay, there is an exchange of thoughts about the advantage of using Google Calendar instead of that which is the ability to share data not only within our app but  also to our personal computers and mobile devices.  That is a valid point but the thing I dislike is in order to do that, is to rely on Google's own APIs as they may change those now and then; for the betterment of google products.

And so with that in mind, and taking into consideration the argument about that sharing capability, here instead is my preferred way.  Not using google API but to embed Google Calendar via Internet Explorer automation within our form:



Declare Integer GetWindowLong In User32 Integer HWnd, Integer nIndex
Declare Integer SetWindowLong In user32 Integer HWnd,;
      INTEGER nIndex, Integer dwNewLong
Declare Integer SetWindowPos In user32;
      INTEGER HWnd,;
      INTEGER hWndInsertAfter,;
      INTEGER x,;
      INTEGER Y,;
      INTEGER cx,;
      INTEGER cy,;
      INTEGER uFlags
Declare Integer SetParent In user32;
      INTEGER hWndChild,;
      INTEGER hWndNewParent

loTest = Createobject("Form1")
loTest.Show(1)
Read Events

Define Class Form1 As Form
      Caption = 'Google Calendar on Form'
      AutoCenter = .T.
      Height = 700
      Width = 900
      ShowWindow = 2
      oIE = .F.

      Procedure Init
            Local lcURL, lnStyle, loHWnd, loIE As internetexplorer.Application
            lcURL = 'https://calendar.google.com/calendar/r'

            loIE = Createobject("InternetExplorer.Application")
            Thisform.oIE = m.loIE
            With loIE
                  .Visible = .F.
                  .Silent = .T.
                  .FullScreen=.T.

                  .Navigate2(m.lcURL)
                  .ClientToWindow(.Width,.Height)

                  Do While .ReadyState <> 4
                  Enddo

                  loHWnd = .HWnd
                  lnStyle = GetWindowLong(m.loHWnd, -6)
                  SetWindowLong(m.loHWnd, -12, Bitxor(lnStyle, 0x00400000))
                  SetParent(m.loHWnd,Thisform.HWnd)
                  This._Resize()
                  .Visible = .T.
            Endwith
            Bindevent(This,'_Resize',This,'Resize')
      Endproc

      Procedure _Resize
            With Thisform
                  SetWindowPos(.oIE.HWnd, 1, .Left, .Top, .Width, .Height,0x0001)
            Endwith
      Endproc

      Procedure Destroy
            Clear Events
            This.oIE.Quit
            This.oIE = Null
      Endproc

      Procedure KeyPress
            Lparameters nKeyCode, nShiftAltCtrl
            If m.nKeyCode = 27
                  Thisform.Release
            Endif
      Endproc

Enddefine

If you haven't logged in at your google account yet when you first run this, it will require you to. After that, IE will remember it and the next runs will go straight to Google Calendar.

Tuesday, January 2, 2018

Alter Table Trick

Okay so it is now 2018 and I want to greet every one a more prosperous new year than before.  I am now back at work and immediately I got a request from a Colleague to create a small app that can import data from an excel generated by another app, and later use my ExcelPivot class to provide the needed reports.  Instead of them doing those manually.  So the raw data from excel looks like this:


Then of course the easiest way for me to do that is to import the file and then later adjust fields:

Import From (m.lcFile) Type Xl5

That resulted to 8 columns bearing the field names a,b,c,d,e,f,g and h.  So after that,  we need to change the field names and types to proper ones like this:

Alter Table (m.lcDBF) Alter Column a c(8)
Alter Table (m.lcDBF) Rename Column a To po
Alter Table (m.lcDBF) Rename Column b To supplier
Alter Table (m.lcDBF) Alter Column c D
Alter Table (m.lcDBF) Rename Column c To Date
Alter Table (m.lcDBF) Rename Column d To Status
Alter Table (m.lcDBF) Rename Column e To workorder
Alter Table (m.lcDBF) Rename Column F To location
Alter Table (m.lcDBF) Alter Column g N(12,2)
Alter Table (m.lcDBF) Rename Column g To amount
Alter Table (m.lcDBF) Alter Column h N(12,2)
Alter Table (m.lcDBF) Rename Column h To UpdAmt

As you can see above, some involves ALTER COLUMN which changes the type of that column to a target one and all involves RENAME COLUMN to give those fields proper names.

Monday, December 11, 2017

dtPickerX - December 2017 version

Okay, so I changed some things (again) inside, for the better.  And aside from listing what those are here, I decided to make this post as the official guide post for dtPickerX class too.  So what are these enhancements and what are the previous features which I may have not highlighted before?


Enhancements:

1. Better Year Spinner.  I have improved SpinnerX class so I can use it here and this, IMHO, gives a better look and faster reaction than the native Spinner object I have used on the earlier versions of this class.

2. Better Time Picker.  I modified ScrollTime class too to give it a better look and new attitude too, then used that for the time picking section here instead of the previous DropTime class.

3. Dates Color Explosion.  I added back the capability to put notes and holidays found in one older version, but this time in a much easier fashion plus with more color markings to choose from (7 colors, the 8th box is for HotKey Tooltip).  Also now, the initial set of holidays are all set to blue color (first color).  Nevertheless, users can choose to use any of the colors later for that but it would be better to leave the blue for holidays.

Why different colors?  Well, you may wish to use the colors to indicate the urgency of a note.  Say for those you need to remember such as birthdays of your loved ones, then you can set those to a strong color like pink.  So immediately when you see a date that is encased in a pink box, you know that that is a birthday occassion.  Or for your wedding anniversary, you may want to set that to red as when you forgot such occassion, you are definitely in trouble.

Wednesday, November 8, 2017

SwitchX/OptionSwitchX Bold New Themes

Since I adjusted the library to make it more flexible, I decided to replace some themes with bolder new look to spice up further our app.  And here are the latest themes for both classes


This and other more classes are part of ssUltimate Library.  Cheers!

Thursday, September 14, 2017

xBox via SQL Pass-Through and Stored Procedures

Since xBox was created while I am still working with pure VFP, the approach I did was designed to work only on VFP's native backend.  So to have something like this:



You have to put in its InteractiveChange Event codes like this:

Local lcSQL
TEXT TO lcSQL NOSHOW 
Select vesselname,vesselid from Vessels
      where [MySearch] $ vesselname 
      order By
      into Cursor curVessel NOFILTER
ENDTEXT
This._searchgrid(m.lcSQL,'curVessel.VesselName')

Where [MySearch] will be automatically replaced by xBox class with whatever you have already typed.  And curvessel.VesselName is the value it will return, the one that will be held by its .Value property.  There is secondary value it can return after that via .ExtraValue property but that is another topic.  If you are already a subscriber or user of ssUltimate's xBox, then you already know about this.

Lately, I decided to use MariaDB and so to make xBox working there, I showed the way here: http://sandstorm36.blogspot.com/2017/04/xbox-on-mysql-backend.html

But that requires two jumps as follows:

* Get data from MariaDB/MySQL
SQLExec(gomyapp.dbHandle,'Select vesselname,vesselid from Vessels order by vesselname','vessels')
* Use generated cursor on the class
Local lcSQL
TEXT TO lcSQL NOSHOW  
Select vesselname,vesselid from Vessels
      where [MySearch] $ vesselname 
      order By
      into Cursor curVessel NOFILTER
ENDTEXT
This._searchgrid(m.lcSQL,'curVessel.VesselName')

Or you can reverse the process limiting the number of records of the  cursor generated from the other backend using WHERE clause on the SPT query instead of the one needed by xBox class.  

Today, I added two new direct calls to the other backend which will not require a 2nd jump anymore.  Two new class methods, 1st is for SQL Pass-Through query approach and another for Stored Procedure approach.  Let us see how the call is made on those two:

via _SPT() Method.  This expects parameters as follows:
Lparameters ndbHandle, cSQL, cCursor, vValue, vExtraValue

Tuesday, September 12, 2017

CtrlBox New Features

Brief History

Originally CtrlBox is intended solely as a slave of my TitleBarX class when I decided to experiment with shapes for the controls there (minimize, maximize/restore, and close).  Later I decided to create it as a master of its own (while still being used by TitleBarX).  So now, it can be dragged and dropped onto a form and that will replace your form's native titlebar.

New Features

  1. Now it auto hides the form's native titlebar
  2. Now it auto repositions itself onto top-right corner
  3. New built-in titlebar of its own.  I added this today as sometimes I wanted to make the form movable but still using this class.  For this new titlebar to appear, you have to set _WithBar = .T. (default is .F. or no titlebar).  This is affected further by the following:
    • Caption - the caption to be shown on the titlebar


Properties affecting Caption follow:

  • FontName = default is Calibri
  • FontSize = default is 12
  • FontBold = default is .T.
  • ForeColor = default is RGB(255,255,255)
  • Alignment = default is 2 (center).  I know some of you will love to have a caption in the middle
  • BarHeight = Default is 20.  The height of the titlebar. This also affects the caption height