Useful Utilities (at least, I think they are)
Like all developers, whatever their preferred language or environment, I have my own personal set of tools and utilities that I use to make life a little easier for myself. Although not particularly generic, or even clever, I find that these little things really help so I offer them here, as is, for your enjoyment, adoption and modification.
The first is a little bit of code that I wrote because I was fed up with mis-spelling column names when writing SQL Statements – especially when working with cursors that included calculated or aliased columns. This little routine, named GetFList() gets the list of field names for a specified alias (or the currently selected alias if nothing is specified) and places them on to the Windows Clipboard. Once there, the list can simply be pasted into whatever window I happen to be working in at the time. Simple, but it has saved me many hours over the years.
********************************************************************
*** Name.....: GetFList.prg
*** Author...: Andy Kramek
*** Date.....: 7/7/2004
*** Notice...: Copyright (c) 2004 Tightline Computers, Inc
*** Function.: Copy the list of fields in the current, or specified, table to the clipboard
********************************************************************
LPARAMETERS tcTable
LOCAL lcTable, lcAlias, lcList, lnCnt, lcField, lnSelect
*** Did we get a table name
lnSelect = SELECT()
IF VARTYPE(tcTable) = "C" AND NOT EMPTY( tcTable )
lcAlias = JUSTSTEM( tcTable )
*** If it's not used, open it
IF NOT USED( lcAlias )
IF FILE( FORCEEXT( tcTable, 'dbf' ))
USE (tcTable) AGAIN IN 0 ALIAS (lcALias)
ELSE
_ClipText = ''
RETURN
ENDIF
ENDIF
*** And Select the Alias
SELECT (lcAlias)
ELSE
*** Use whatever is currently selected
lcAlias = ALIAS()
ENDIF
*** Get the list of field names
IF NOT EMPTY( lcAlias )
lcList = ''
FOR lnCnt = 1 TO FCOUNT()
lcField = LOWER( ALLTRIM( FIELD( lnCnt )))
lcList = lcList + IIF( EMPTY( lcList ), "", ", " ) + lcField
NEXT
*** Add the alias name
_ClipText = lcList + CHR(13) + CHR(10) + "*** " + lcAlias
ENDIF
*** Restore work area
SELECT (lnSelect)
RETURN
The second little utility is one that I call from a hot-key in my development environment to open an instance of Windows Explorer to the currently selected drive and directory. I confess that I find the inconsistent behavior of the windows that access the file system irritating. Some applications open a window to the last directory that was accessed, others simply use a standard (“My files”) or static directory (C:\ or “My Computer”) and others again do something which is apparently randomized. Generally, when working in VFP, if I need to access Windows Explorer I want to find a file that is either in the current working directory (typically the root directory of a project hierarchy) or in some specific related directory which I know the name of anyway (e.g. “D:\VFP90\COMMON”).
The RunExplorer procedure uses the ShellExecute() API function to open Windows Explorer to the required location and I call it using a simple ON KEY LABEL command so that it is available on my “F5” function key. It will accept a specific drive/directory as a parameter but the default behavior is to use the current VFP working directory. Here is the code for it:
********************************************************************
*** Name.....: RUNEXPLORER.PRG
*** Author...: Andy Kramek
*** Date.....: 25/09/2004
*** Notice...: Copyright (c) 2004 Tightline Computers, Inc
*** Function.: Runs Windows Explorer with the specified directory selected
*** .........: Defaults to VFP current working directory if none passed
*****************************************************************
LPARAMETERS tcDir
LOCAL ARRAY laDex[1]
LOCAL lcDir, lnDex, llIsLoaded, lcParms, lnRes
*** Default to current directory if nothing is passed in
IF VARTYPE( tcDir ) # "C" OR EMPTY( tcDir )
lcDir = FULLPATH( CURDIR())
ELSE
*** Default if specified directory does not exist
IF NOT DIRECTORY( tcDir )
lcDir = FULLPATH(CURDIR())
ELSE
lcDir = tcDir
ENDIF
ENDIF
*** Make sure we have Shellexecute available
lnDex = ADLLS( laDex )
IF lnDex > 0
llIsLoaded = (ASCAN( laDex, 'shellexecute', 2, -1, 2, 15 ) > 0)
ELSE
llIsLoaded = .F.
ENDIF
IF NOT llIsLoaded
*** Load the function
DECLARE INTEGER ShellExecute IN shell32;
INTEGER hwnd,;
STRING lpOperation,;
STRING lpFile,;
STRING lpParameters,;
STRING lpDirectory,;
INTEGER nShowCmd
ENDIF
*** Open Explorer to the correct location
lcParms = "/n,,/e," + lcDir
lnRes = ShellExecute( 0, "open", 'explorer.exe', lcParms, "", 1 )
RETURN
Incidentally the same parameters (“/n,,/e,” + <path>) can be used in desktop shortcuts to open windows explorer to a more useful location than “my computer”. I usually set my shortcuts to use “D:\” since that is the root of my application drive and therefore the most likely place that I will want to start using Windows Explorer from – but you can choose anything.
The final little utility that I want to share is one that I use less often directly, but which is useful anyway. One of the things that I always do is to set an explicit search path in VFP (see my blog article on paths for details) but of course in order to specify a path you need to list all of the directories. It has always struck me as odd that Windows Explorer has no mechanism that will allow you to copy a list of names – so I wrote GetSubDirs() to create a comma-separated list of the first level sub-directories that exist under the specified root and push it on to the clipboard. Why just first level? Only because my standard project directory structure does not use anything deeper and I have no need to handle any additional complexity. The code could easily be made recursive to handle additional levels of sub-directories but I leave that as an exercise for the reader…J
********************************************************************
*** Name.....: GETSUBDIRS.PRG
*** Author...: Andy Kramek
*** Date.....: 23/09/2004
*** Notice...: Copyright (c) 2004 Tightline Computers, Inc
*** Function.: Build a ";" separated list of SubDirectories and copy it to the clipboard
********************************************************************
LPARAMETERS tcRoot
LOCAL ARRAY laDirs[1]
LOCAL lcRoot, lcOrigDir, lnDirs, lnCnt, lcDir, lcList
*** We definitely need a root directory
IF EMPTY( tcRoot ) OR NOT DIRECTORY( tcRoot )
lcRoot = GETDIR( CURDIR(), "Must specify a Root Directory", "Get SubDirs" )
IF EMPTY(lcRoot)
lcRoot = FULLPATH( CURDIR())
ENDIF
ELSE
lcRoot = FULLPATH( tcRoot )
ENDIF
*** Save the original location
lcOrigDir = FULLPATH( CURDIR() )
*** Switch to the specified directory
SET DEFAULT TO (lcRoot)
*** Now get a list of 1st level Sub_directories
lnDirs = ADIR( laDirs, '*.', 'D' )
IF lnDirs = 0
_ClipText = ""
SET DEFAULT TO (lcOrigDir)
RETURN ""
ENDIF
*** We have at least one sub-directory
lcList = ''
FOR lnCnt = 1 TO lnDirs
*** Ignore "." and ".." entries
lcDir = LOWER( ALLTRIM( CHRTRAN( laDirs[lnCnt, 1], '.', '')))
IF EMPTY( lcDir )
LOOP
ENDIF
*** Add the directory to the list
lcList = lcList + IIF( EMPTY( lcList ), '', ';' ) + lcDir
NEXT
*** Copy results to the clipboard and return the list
SET DEFAULT TO (lcOrigDir)
_ClipText = lcList
RETURN lcList