Artículo original: Useful Utilities (at least, I think they are)
http://weblogs.foxite.com/andykramek/archive/2006/06/18/1883.aspx
Autor: Andy Kramek
Traducido por: Ana María Bisbé York
Como todos los desarrolladores, cualquiera que sea el lenguaje o entorno preferidos, tengo mi conjunto propio de herramientas y utilidades que utilizo y hacen mi vida más sencilla. Aunque no sean especialmente genéricas, o incluso inteligentes, considero que estas pequeñas cosas ayudan realmente y por eso las ofrezco aquí, tal cual, para su disfrute, adopción y modificación.
Lo primero es un pequeño fragmento de código que escribí, porque estaba cansado de los errores de escritura en los nombres de las columnas al escribir sentencias SQL - especialmente cuando trabajo con cursores que incluyen columnas calculadas o alias. Esta pequeña rutina llamada GetFList() toma los nombres de los campos de un alias especificado (o del alias actualmente seleccionado si no se especifica nada) y lo coloca en el Portapapeles de Windows. Una vez ahí, la lista puede ser pegada en cualquier ventana con la que tenga que trabajar en ese momento. Sencillo; pero me ha ahorrado muchas horas a lo largo de los años.
********************************************************************
*** Nombre.: GetFList.prg
*** Autor.....: Andy Kramek
*** Fecha.....: 7/7/2004
*** Nota.......: Copyright (c) 2004 Tightline Computers, Inc
*** Función...: Copia la lista de los campos de la tabla actual,
*** o una especificada, en el portapapeles
********************************************************************
LPARAMETERS tcTable
LOCAL lcTable, lcAlias, lcList, lnCnt, lcField, lnSelect
*** ¿Tenemos el nombre de tabla?
lnSelect = SELECT()
IF VARTYPE(tcTable) = "C" AND NOT EMPTY( tcTable )
lcAlias = JUSTSTEM( tcTable )
*** Si no está en uso, la abre
IF NOT USED( lcAlias )
IF FILE( FORCEEXT( tcTable, 'dbf' ))
USE (tcTable) AGAIN IN 0 ALIAS (lcALias)
ELSE
_CLIPTEXT = ''
RETURN
ENDIF
ENDIF
*** Y selecciona el Alias
SELECT (lcAlias)
ELSE
*** Utiliza cualquiera que esté abierta
lcAlias = ALIAS()
ENDIF
*** Obtiene la lista de nombres de campos
IF NOT EMPTY( lcAlias )
lcList = ''
FOR lnCnt = 1 TO FCOUNT()
lcField = LOWER( ALLTRIM( FIELD( lnCnt )))
lcList = lcList + IIF( EMPTY( lcList ), "", ", " ) + lcField
NEXT
*** Agrega el nombre de alias
_CLIPTEXT = lcList + CHR(13) + CHR(10) + "*** " + lcAlias
ENDIF
*** Restablece el área de trabajo
SELECT (lnSelect)
RETURN
La segunda pequeña utilidad es una que llamo, desde las teclas clave (hot-key) en mi entorno de desarrollo, para abrir una instancia del Explorador de Windows en el disco y la carpeta actualmente seleccionada. Confieso que encuentro que es irritante el comportamiento inconsistente de Windows al acceder a ficheros del sistema. Algunas aplicaciones abren una ventana a la última carpeta a la que se ha accedido, otras sencillamente utilizan la estándar ("Mis documentos") o la carpeta estática (C:\ o "Mi PC") y otras hacen algo que tal parece aleatorio. Generalmente, cuando trabajo en VFP, necesito acceder al Explorador de Windows, necesito encontrar un archivo que está en la carpeta actual (por lo general en el directorio raíz o en la jerarquía del proyecto) o en alguna carpeta relacionada de la que conozco, en cualquier caso el nombre (por ejemplo "D:\VFP90\COMMON").
El procedimiento RunExplorer utiliza la función API ShellExecute() para abrir el Explorador de Windows en la ubicación requerida y yo la llamo empleando un comando ON KEY LABEL que está disponible desde mi tecla de función "F5". Acepta un disco/directorio como parámetro; pero el comportamiento predeterminado es utilizar el directorio de trabajo actual de VFP. He aquí el código para esto:
********************************************************************
*** Nombre.....: RUNEXPLORER.PRG
*** Autor.........: Andy Kramek
*** Fecha.........: 25/09/2004
*** Nota...........: Copyright (c) 2004 Tightline Computers, Inc
*** Función.......: Ejecuta el Explorador de Windows con el directorio
*** especificado. Si no se pasa un valor, el valor
*** predeterminado es el directorio actual de VFP
*****************************************************************
LPARAMETERS tcDir
LOCAL ARRAY laDex[1]
LOCAL lcDir, lnDex, llIsLoaded, lcParms, lnRes
*** Directorio predeterminado, si no es le pasa otra cosa
IF VARTYPE( tcDir ) # "C" OR EMPTY( tcDir )
lcDir = FULLPATH( CURDIR())
ELSE
*** Directorio predeterminado si el especificado no existe
IF NOT DIRECTORY( tcDir )
lcDir = FULLPATH(CURDIR())
ELSE
lcDir = tcDir
ENDIF
ENDIF
*** Se asegura de que esté disponible Shellexecute
lnDex = ADLLS( laDex )
IF lnDex > 0
llIsLoaded = (ASCAN( laDex, 'shellexecute', 2, -1, 2, 15 ) > 0)
ELSE
llIsLoaded = .F.
ENDIF
IF NOT llIsLoaded
*** Llama a la función
DECLARE INTEGER ShellExecute IN shell32;
INTEGER HWND,;
STRING lpOperation,;
STRING lpFile,;
STRING lpParameters,;
STRING lpDirectory,;
INTEGER nShowCmd
ENDIF
*** Abre el Explorador en la localización correcta
lcParms = "/N,,/e," + lcDir
lnRes = ShellExecute( 0, "OPEN", 'explorer.exe', lcParms, "", 1 )
RETURN
Incidentalmente, pueden ser utilizados los mismos parámetros ("/n,,/e," + <ruta>) en accesos directos del escritorio para abrir el Explorador de Windows en ubicaciones más útiles que "Mi PC". Generalmente establezco mis accesos directos para utilizar "D:\" una vez que esta es la raíz para mi disco de aplicación y por tanto el mejor lugar por el que quiero comenzar al utilizar el Explorador de Windows - pero usted puede seleccionar cualquiera.
La última pequeña utilidad que deseo compartir es una que yo utilizo menos; pero que es igualmente útil. Una de las cosas que yo hago es establecer una ruta específica en VFP (para los detalles, vea mi artículo sobre rutas. Nota de la traductora: El autor se refiere al artículo "The importance of Paths in VFP" - http://weblogs.foxite.com/andykramek/archive/2005/03/21/197.aspx, que se encuentra traducido al español bajo el título "La importancia de las rutas en VFP" y publicado en: http://comunidadvfp.blogspot.com/2003/12/la-importancia-de-las-rutas-en-vfp.html)
Por supuesto, para especificar una ruta, necesita enumerar todas las carpetas. Me fastidia mucho que Windows no tenga un mecanismo que nos permita copiar una lista de nombres - así que escribí GetSubDirs() para crear una lista, separada por punto y coma, de primer nivel de subdirectorios que existen bajo una raíz especificada y lo coloque en el portapapeles. ¿Por qué solamente el primer nivel? Solamente, debido a que mi estructura estándar de directorios no es más profunda y no necesito controlar nada de complejidad adicional. El código puede ser recursivo para controlar niveles adicionales de subdirectorios; pero esto lo dejo como ejercicio al lector ...
********************************************************************
*** Nombre........: GETSUBDIRS.PRG
*** Autor.........: Andy Kramek
*** Fecha.........: 23/09/2004
*** Nota..........: Copyright (c) 2004 Tightline Computers, Inc
*** Función.......: Crea una lista separada por ";" de subdirectorios
*** y la copia en el Portapapeles
********************************************************************
LPARAMETERS tcRoot
LOCAL ARRAY laDirs[1]
LOCAL lcRoot, lcOrigDir, lnDirs, lnCnt, lcDir, lcList
*** Necesitamos definitivamente una carpeta raíz
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
***Guarda la ubicación actual
lcOrigDir = FULLPATH( CURDIR() )
*** Activa el directorio especificado
SET DEFAULT TO (lcRoot)
*** Obtiene l lista de subdirectorios de primer nivel
lnDirs = ADIR( laDirs, '*.', 'D' )
IF lnDirs = 0
_CLIPTEXT = ""
SET DEFAULT TO (lcOrigDir)
RETURN ""
ENDIF
*** Tenemos al menos un subdirectorio
lcList = ''
FOR lnCnt = 1 TO lnDirs
*** Ignora las entradas "." y ".."
lcDir = LOWER( ALLTRIM( CHRTRAN( laDirs[lnCnt, 1], '.', '')))
IF EMPTY( lcDir )
LOOP
ENDIF
*** Agrega los directorios a la lita
lcList = lcList + IIF( EMPTY( lcList ), '', ';' ) + lcDir
NEXT
*** Copia los resultados en el portapapeles y devuelve la lista
SET DEFAULT TO (lcOrigDir)
_CLIPTEXT = lcList
RETURN lcList