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 instead of admiration 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.