*--------------------------------------------------------
* FUNCTION FindField(lcCampo, lcAlias)
*--------------------------------------------------------
* Busca un nombre de campo en una tabla y retorna .T. si tuvo exito.
* USO: ? FindField("MiCampo", "MiAlias")
* ? FindField("MiCampo") && Busca en el alias corriente
*--------------------------------------------------------
FUNCTION FindField(lcCampo, lcAlias)
LOCAL ln
IF EMPTY(lcAlias)
lcAlias = ALIAS()
ENDIF
IF USED(lcAlias)
ln = AFIELDS(MiArray, lcAlias)
IF ln > 0
ln = ASCAN(MiArray, UPPER(lcCampo))
ENDIF
ELSE
ln = 0
MESSAGEBOX("El alias no existe.",16)
ENDIF
RETURN ln
ENDFUNC
Luis María Guayán
30 de abril de 2000
Busca un nombre de campo en una tabla
Buscar un nombre de campo en una tabla y retorna .T. si tuvo exito.
29 de abril de 2000
Calcular el domingo de pascua de un año
Con esta función podemos conocer la fecha del Domingo de Pascua de cualquier año.
*---------------------------------------------------------------
* FUNCTION _Pascua(tnAnio)
*---------------------------------------------------------------
* USE: _Pascua(1999)
* PARAMETRO: Año a calcular
* RETORNO: Fecha del Domingo de Pascua
*---------------------------------------------------------------
FUNCTION _Pascua(tnAnio)
LOCAL lnCentena, lnAux, lnNroAureo, lnDomingo, lnEpactaJul, ;
lnCorrSolar, lnCorrLunar, lnEpactaGreg, lnDiasLunaP, ;
lnDiasLuna15, lnDiasPascua, ldFecIni, ldFecPascua
IF NOT BETWEEN(tnAnio,1000,9999)
MESSAGEBOX("Rango inválido [1000..9999]")
RETURN {//}
ENDIF
lnCentena = INT(tnAnio / 100)
lnAux = (tnAnio + 1) % 19
lnNroAureo = lnAux + (19 * INT((19 - lnAux) / 19))
lnDomingo = 7 + (1 - tnAnio - INT(tnAnio / 4) + lnCentena - INT(lnCentena / 4)) % 7
lnEpactaJul = ((11 * lnNroAureo) - 10) % 30
lnCorrSolar = - (lnCentena - 16) + INT((lnCentena- 16) / 4)
lnCorrLunar = INT((lnCentena - 15 - INT((lnCentena - 17) / 25)) / 3)
lnEpactaGreg = (30 + lnEpactaJul + lnCorrSolar + lnCorrLunar) % 30
lnDiasLunaP = 24 - lnEpactaGreg + (30 * INT(lnEpactaGreg / 24))
lnDiasLuna15 = (27 - lnEpactaGreg + (30 * INT(lnEpactaGreg / 24))) % 7
lnDiasPascua = lnDiasLunaP + (7 + lnDomingo - lnDiasLuna15) % 7
ldFecIni = DATE(tnAnio, 03, 21)
ldFecPascua = ldFecIni + lnDiasPascua
RETURN ldFecPascua
ENDFUNC
23 de abril de 2000
En que metodo pongo formatos especiales condicionados
En que metodo pongo formatos especiales condicionados, por ejemplo colores en funcion de su Value.
Trabajando con los textbox puede surgir la necesidad de ponerle un formato especial en función de que su valor (por ejemplo ponerlos en rojo, cuando su valor sea negativo).
Surge la duda de en que metodos poner el codigo para colorearlos, Valid, Refresh, ... ¿se me quedo alguno? ¿Como lo hago todo mas sencillo? ¿Tengo que repetir todo esto es cada texbox?
Bueno, lo primero pensar que deberiamos tener redefinida la clase estandard texbox (o aun mejor todas las clases visuales), y nuestros texbox hacerlos que dependieran de nuestras nuevas clases redefinidas, de tal manera que cuando hagamos un cambio en la clase cs_textbox (mi ejemplo), este se realice en todos los que usemos.
Trabajando con VFP6 + SP3, se podria estar tentado en utilizar el metodo value_assign, que es ejecutado cada vex que el valor de un textbox cambia, pero el metodo assign todavia tiene diversos bugs y problemas, como mas gordo citar que si se pone codigo en un value_assign (a nivel de clase), cualquier textbox de esa clase que usemos nos va a decir que se han realizado cambios en el (GETFLDSTATE), por tanto descartado el assign.
Los metodos a modificar son los siguientes:
En el ejemplo que estamos tratando, tambien creo un metodo a nivel de la clase texbox, por ejemplo llamado AnyChange y desde los tres metodos anteriores llamo a este AnyChange.
El codigo del AnyChange es:
Pablo Roca
Trabajando con los textbox puede surgir la necesidad de ponerle un formato especial en función de que su valor (por ejemplo ponerlos en rojo, cuando su valor sea negativo).
Surge la duda de en que metodos poner el codigo para colorearlos, Valid, Refresh, ... ¿se me quedo alguno? ¿Como lo hago todo mas sencillo? ¿Tengo que repetir todo esto es cada texbox?
Bueno, lo primero pensar que deberiamos tener redefinida la clase estandard texbox (o aun mejor todas las clases visuales), y nuestros texbox hacerlos que dependieran de nuestras nuevas clases redefinidas, de tal manera que cuando hagamos un cambio en la clase cs_textbox (mi ejemplo), este se realice en todos los que usemos.
Trabajando con VFP6 + SP3, se podria estar tentado en utilizar el metodo value_assign, que es ejecutado cada vex que el valor de un textbox cambia, pero el metodo assign todavia tiene diversos bugs y problemas, como mas gordo citar que si se pone codigo en un value_assign (a nivel de clase), cualquier textbox de esa clase que usemos nos va a decir que se han realizado cambios en el (GETFLDSTATE), por tanto descartado el assign.
Los metodos a modificar son los siguientes:
- InteractiveChange - Se modifica el valor con el raton
- ProgrammaticChange - Se modifica el valor por codigo
- Refresh - Se actualiza un textbox vinculado a datos (p.ejemplo con un SKIP)
En el ejemplo que estamos tratando, tambien creo un metodo a nivel de la clase texbox, por ejemplo llamado AnyChange y desde los tres metodos anteriores llamo a este AnyChange.
El codigo del AnyChange es:
IF VARTYPE(this.value)="N" this.forecolor = IIF(this.value < 0, RGB(255,0,0),0) this.disabledforecolor = IIF(this.value < 0,RGB(255,0,0),0) ENDIFEs decir si el valor es numerico y negativo lo pone en rojo.
Pablo Roca
18 de abril de 2000
Calcular la diferencia entre dos fechas en años, meses y días
Función para calcular la cantidad de años, meses y días entre dos variables tipo Date.
*-----------------------------------------------------
* FUNCTION Dif_AMD(tdIni, tdFin)
*-----------------------------------------------------
* Calcula la diferencia entre dos fechas en:
* años, meses y días
* Usa la función DiasDelMes()
*-----------------------------------------------------
FUNCTION Dif_AMD(tdIni, tdFin)
LOCAL ldAux, lnAnio, lnMes, lnDia, lcRet
*--- Fecha inicial siempre menor
IF tdIni>tdFin
ldAux = tdIni
tdIni = tdFin
tdFin = ldAux
ENDIF
lnAnio = YEAR(tdFin) - YEAR(tdIni)
ldAux = GOMONTH(tdIni, 12 * lnAnio)
*--- No cumplio el año aun
IF ldAux > tdFin
lnAnio = lnAnio - 1
ENDIF
lnMes = MONTH(tdFin) - MONTH(tdIni)
IF lnMes < 0
lnMes = lnMes + 12
ENDIF
lnDia = DAY(tdFin) - DAY(tdIni)
IF lnDia < 0
lnDia = lnDia + DiasDelMes(tdIni)
ENDIF
*--- Si el dia es mayor, no cumplio el mes
IF (DAY(tdFin) < DAY(tdIni))
IF lnMes = 0
lnMes = 11
ELSE
lnMes = lnMes - 1
ENDIF
ENDIF
lcRet = ALLTRIM(STR(lnAnio))+ " AÑOS, " + ;
ALLTRIM(STR(lnMes))+ " MESES Y " + ;
ALLTRIM(STR(lnDia))+ " DIAS."
RETURN lcRet
ENDFUNC
*-----------------------------------------------------
* FUNCTION DiasDelMes(dFecha)
*------------------------------------------------
* Retorna los días de un mes. Usada por Dif_AMD
*------------------------------------------------
FUNCTION DiasDelMes(dFecha)
LOCAL ld
ld = GOMONTH(dFecha,1)
RETURN DAY(ld - DAY(ld))
ENDFUNC
Luis María Guayán
14 de abril de 2000
Proteger y ocultar el codigo fuente de las clases
Haz una copia de los archivos VCX y VCT
Pablo Roca
COMPILE CLASSLIB libreriadeclases USE libreriadeclases.vcx EXCLUSIVE REPLACE ALL Methods WITH "" USEEsto eliminara todo el codigo fuente de un VCX. Si alguien intenta modificar un procedimiento entonces todas las clases dejarn de funcionar, ya que no hay codigo fuente a compilar.
Pablo Roca
9 de abril de 2000
Crear un fichero de Log que nunca se llena
No se llena pero tiene un tamaño máximo, guarda lo mas nuevo
**********************************************************************
*
* Funcion: LOG_GRAB
*
* Graba una linea en el log (en raizLOG.TXT)
*
* Parametros:
*
* tcTexto - texto a grabar
*
* Ejemplos:
*
* ret = LOG_GRAB("Inicio de Programa")
*
* Retorno:
*
* .T. Grabacion correcta
* .F. Error en la grabacion
*
* Nota:
*
**********************************************************************
FUNCTION LOG_GRAB
PARAMETERS tcTexto
LOCAL plRet, pnFich, pnFichn, pnFtama, pnTammax, pnLongAc
LOCAL pcChar, pnPos
plRet = .T.
pnLongAc = 0
pnTammax = 30000 && tamaño maximo
pnFtama = 0
IF FILE(SYS(5)+SYS(2003)+'log.txt') && ¿Existe el archivo?
pnFich = FOPEN(SYS(5)+SYS(2003)+'log.txt',12) && Sí: abrir lect./escrit.
pnFtama=FSEEK(pnFich, 0, 2) && Mueve el puntero a EOF
&& y devuelve el tamaño
ELSE
pnFich = FCREATE(SYS(5)+SYS(2003)+'log.txt') && Si no, crearlo
ENDIF
IF pnFich < 0 && Comprobar el error
&& abriendo el archivo
plRet = .F.
WAIT 'No puedo abrir o crear el archivo de salida (fich)' WINDOW NOWAIT
ELSE && Si no hay error,
&& escribir en el archivo
IF pnFtama > pnTammax && Si el tamaño es mayor que el max
pnFichn = FCREATE(SYS(5)+SYS(2003)+'logn.txt') && Crear nuevo log
IF pnFichn < 0
WAIT 'No puedo abrir o crear el archivo de salida (fichn)' WINDOW NOWAIT
ELSE
pnPos = FSEEK(pnFich, -(pnTammax - 256), 1)
pcChar = FREAD(pnFich, 1)
DO WHILE pcChar <> CHR(10)
pcChar = FREAD(pnFich, 1)
ENDDO
pnPos = FSEEK(pnFich, 0, 1)
DO WHILE NOT(FEOF(pnFich))
= FPUTS(pnFichn,FGETS(pnFich))
ENDDO
=FCLOSE(pnFich)
=FCLOSE(pnFichn)
DELETE FILE SYS(5)+SYS(2003)+'log.txt'
RENAME SYS(5)+SYS(2003)+'logn.txt' TO SYS(5)+SYS(2003)+'log.txt'
pnFich = FOPEN(SYS(5)+SYS(2003)+'log.txt',12)
pnFtama=FSEEK(pnFich, 0, 2)
ENDIF
ENDIF
=FWRITE(pnFich, DTOC(DATE())+CHR(9))
=FWRITE(pnFich, TIME()+CHR(9))
=FWRITE(pnFich, tcTexto+CHR(13)+CHR(10))
ENDIF
=FCLOSE(pnFich) && Cerrar archivo
RETURN plRet
Pablo Roca
7 de abril de 2000
Función API me retorna el directorio de archivos temporales de Windows
Función que retorna la carpeta de archivos temporales de Windows.
*--------------------------------------------
FUNCTION _TempPath
*--------------------------------------------
* Retorna la ruta de los archivos temporales
* con "" al final ("C:\TEMP")
*--------------------------------------------
LOCAL lcPath, lnRet
lcPath = SPACE(255)
lnSize = 255
DECLARE INTEGER GetTempPath IN WIN32API ;
INTEGER nBufSize, ;
STRING @cPathName
lnRet = GetTempPath(lnSize, @lcPath)
IF lnRet <= 0
lcPath = ""
ELSE
lcPath = SUBSTR(lcPath, 1, lnRet)
ENDIF
RETURN lcPath
ENDFUNC
Luis María Guayán
5 de abril de 2000
Parámetros del MESSAGEBOX() no documentados
Existen dos parámetros no documentados de la función MESSAGEBOX(), estos son:
MB_SYSTEMMODAL = 4096
MB_TASKMODAL = 8192
*-- Ejemplo:
inkey(10)
*-- Cambia a cualquier otra ventana
? MESSAGEBOX("AL TOP", 0 + 16 + MB_SYSTEMMODAL, "Aplicación de VFP")
Añadiendo estos valores a los otros que controlan el ícono y estilo de botones, afectaran al modo modal y al ambito del diálogo. Mientras que MB_SYSTEMMODAL tiene muy poco efecto visible sobre el diálogo (sin embargo, hay diferencias internas), MB_TASKMODAL provocará que el diálogo aparezca no solo encima de las ventanas de la aplicación activa, sino que también sobre cualquier ventana de cualquier aplicación.
4 de abril de 2000
Ejecutar el sonido predeterminado del sistema
Cómo ejecutar el sonido predeterminado del sistema.
*--------------------------------------------
FUNCTION _MessageBeep(tnSound)
*--------------------------------------------
* Ejecuta el sonido del sistema
* USO: _MessageBeep()
*--------------------------------------------
IF EMPTY(tnSound) OR TYPE("tnSound") tnSound = 1
ENDIF
DECLARE INTEGER MessageBeep IN WIN32API ;
INTEGER nSound
=MessageBeep(tnSound)
RETURN
ENDFUNC
Luis María Guayán
1 de abril de 2000
Numero de colores soportados
Para poder determinar el numero de colores disponibles, son necesarias tres llamadas a la API de windows: GetDC(), GetDeviceCaps(), and ReleaseDC().
A continuación se muestran las funciones capaces de devolver este valor. Nota: En la version de FoxPro de Windows se debe cargar FOXTOOLS.FLL antes de llamar a la función.
A continuación se muestran las funciones capaces de devolver este valor. Nota: En la version de FoxPro de Windows se debe cargar FOXTOOLS.FLL antes de llamar a la función.
FUNCTION NumColors * version de 32 bit para uso con * VFP bajo Win 95 y superiores, * y Windows NT 3.51 y superiores DECLARE INTEGER GetDC IN Win32API; INTEGER hWnd DECLARE INTEGER GetDeviceCaps IN Win32API; INTEGER hDC, INTEGER nIndex DECLARE INTEGER ReleaseDC IN Win32API; INTEGER hWnd, INTEGER hDC LOCAL lnresult, lnhDC, lnplanes, lnpixels lnresult = 0 lnhDC = GetDC(0) IF lnhDC > 0 * Get the number of color planes lnplanes = GetDeviceCaps(lnhDC, 14) * Get the number of bits per pixel lnpixels = GetDeviceCaps(lnhDC, 12) * Calculate the return value lnresult = 2 ^ (lnplanes * lnpixels) = ReleaseDC(0, lnhDC) ENDIF RETURN lnresult
FUNCTION NumColors
* Para usar con FPW 2.5 y superiores
* y VFP bajo Windows 3.1
PRIVATE m.result, m.getdc, m.getdevcaps,;
m.releasedc, m.hdc, m.planes, m.pixels
m.result = 0
m.getdc = RegFN('GetDC', 'I', 'I')
m.getdevcaps = RegFN('GetDeviceCaps', 'II', 'I')
m.releasedc = RegFN('ReleaseDC', 'II', 'I')
m.hdc = CallFN(m.getdc, 0)
IF m.hdc > 0
* Get the number of color planes
m.planes = CallFN(m.getdevcaps, m.hdc, 14)
* Get the number of bits per pixel
m.pixels = CallFN(m.getdevcaps, m.hdc, 12)
* Calculate the return value
m.result = 2 ^ (m.planes * m.pixels)
= CallFN(m.releasedc, 0, m.hdc)
ENDIF
RETURN m.result
Primer día del mes de un día de la semana
Hay algunas ocasiones en las que es útil saber el primer día del mes en el que cae un día de
la semana. Por ejemplo en los Estados Unidos el primer lunes de septiembre es vacaciones.
La siguiente función dado un mes y un año devuelve la fecha en la que cae un día de la semana 1 = Domingo, 2 = Lunes,...
* Saber el primer Lunes de septiembre del año actual.
La siguiente función dado un mes y un año devuelve la fecha en la que cae un día de la semana 1 = Domingo, 2 = Lunes,...
* FUNCTION: FirstDay.prg
LPARAMETERS pnmonth, pnyear, pndow
* Parameter list description
* pnmonth numero del mes (1-12)
* pnyear numero del año (en formato cuatro digitos)
* pndow dia de la semana a investigar (Domingo = 1, Lunes = 2, etc.)
LOCAL ldresult, lddate, lndow
lddate = DATE(pnyear, pnmonth, 1)
ldresult = lddate
* Fuerza a VFP 5.0/6.0 a usar el Domingo
* como primer dia de la semana
* Versiones anteriores deberan borrar el parametro
lnfirstday = DOW(lddate, 1)
IF lnfirstday IF lnfirstday < pndow
ldresult = lddate + (pndow - lnfirstday)
ELSE
ldresult = lddate + (7 + pndow) - lnfirstday
ENDIF
ENDIF
RETURN ldresult
Ejemplo:* Saber el primer Lunes de septiembre del año actual.
ldSeptMon = FirstDay(9, YEAR(DATE()), 2)
Suscribirse a:
Comentarios
(
Atom
)