jueves, 11 de abril de 2013

Cómo agregar elementos (opciones) a un COMBOBOX - Manual y con cursor

Hola. Saludos a todos. En esta ocasión, presentaré como configurar un objeto COMBOBOX para mostrar una lista (desplegable) de opciones, de forma manual y a través de un cursor o tabla (.dbf).

El objeto ComboBox permite la interaccion de diversas opciones en un mismo momento y espacio dentro de nuestras aplicaciones. Es muy óptimo y versatil para el manejo de datos y permite ahorrar bastante recurso y tiempo.

Manual

Para configurar un combo con datos de forma manual, debemos tener en cuenta algunas cosas. Cuando etablecemos uno o varios datos de forma manual, a traves de la propiedad RowSource del combo, estamos limitando la variacion de opciones únicamente a los datos que registramos en dicha propiedad. Esto es util en casos en donde las opciones del usuario para realizar una transaccion van de un "Si" o "No". Por ejemplo: En una aplicacion de nómina, en las altas de empleado, podemos configurar si un empleado esta activo o no


Para configurar manualmente el combo, vamos a las propiedades de este, en la pestaña DATA, ubicamos la propiedad RowSourceType y la establecemos en 1 - Value. Ubicamos la propiedad RowSource y aqui escribimos las opciones que tendra, disponibles, el combo. Separamos cada opcion con una coma, asi:

Cada opcion debe ir separada únicamente por una coma. Si Agregamos un espacio, éste estara contenido en la opcion.

Ahora... si queremos que el combo no permita escritura, en tiempo de ejecucion, vamos a las propieaddes del combo y en la pestaña LAYOUT ubicamos la propiedad STYLE y escogemos la opcion 2 - DropDownList. Con esto, resolvemos ese problema. Luego, podemos aplicar formato deseado para mejorar la presentacion del objeto. Y listo.


 Con CURSOR (temporal o tabla fisica .dbf)

Cargar un cursor con un cursor temporal o una tabla fisica es muy util cuando el numero de opciones es considerable y dispuesto a cambios. Por ejemplo: cuando diseñamos una aplicacion de nómina, definimos unicamente los parametros de ingreso y registro de unidades administrativas en donde se ubicaran los empleados. Pero es el usuario quien registra dichas unidades, y cuando realice las altas de su personal, necesita conocer esas unidades para ubicar a los trabajadores. Como programadores, no sabemos cuantas unidades tendra el sistema ni cuando se registratrán. Al hacer la apertura de la empresa, el cliente inicia operaciones con 20 empleados distribuidos en 4 unidades administrativas. Primero registra las unidades y luego a los empleados. El el formulario de alta de empleados, tiene un campo disponible para ingresar la ubicacion del trabajador, la cual se escoge a través de un combo que desplega todas las unidades disponibles (4). Pasan 4 meses y la empresa crece. El personal pasa a 50 y las unidades a 8. Entonces, como registra el cliente a sus nuevos empleados y sus ubicaciones (predispuestas a cambios, a como pueden ver) cambiantes en el modulo de altas??? Como hace el sistema para ir registrando unidades por un lado, y por otro (alta de empleados) ir mostrando algunas opciones nuevas en un combobox??? Va asi:


Sigamos la linea del ejemplo de sistema de nomina, para ser mas ilustrativos. Imaginemos que tenemos una tabla fisica llamada unidades_adm en donde registramos las unidades administrativas de la empresa, con los campos: codigounidad, nombreunidad. Esta tabla, "alimentara" el combobox ubicado en el modulo de alta de empleado. Vamos al modulo de altas de empleado, y procedemos asi:

1. Agregamos la tabla unidades_adm al entorno de datos de nuestro form.
2. En las propiedades del combo, ubicamos en la pestaña DATA la propiedad RowSourceType y seleccionamos la opcion 6 - Fields. Con esto, establecemos que el combo sera "alimentado" con los registros de un campo de una tabla. En la propiedad RowSource, seleccionamos el campo especifico con el cual deseamos hacer referencia de opciones en el combo. En este caso, unidades_adm.codigounidad. Seleccionamos la propiedad Style (en Layout) y escogemos 2  - DropDownList

Y listo. Ahora, cada vez que el usuario registre una nueva unidad, en el modulo de altas de empleados, ya las opciones estaran disponibles! :) De esta forma muy sencilla, podemos ver como mantener actualizadas las opcions de un combobox.

Para usar un cursor temporal, lo unico que hacemos es crear el cursor en el init del form y luego cargarlo al combo. EN el init del form, seleccionamos los datos en un cursor

SELECT codigounidad FROM unidades_adm INTO CURSOR temp1

y en las propiedades del combo, colocamos el nombre del cursor y campo

temp1.codigounidad

Y listo! :)

Cualquier duda, consulta o comentario, siempre es bienvenido para mejorar! :D

Saludos!
Desde Managua, Nicaragua! :D :D
Raven ;D ;D ;D


lunes, 18 de febrero de 2013

Quitar los "/" y ":" de una expresion DATETIME() pasandola a CARACTER

Hola. Saludos a todos. Hoy, conversaba con mi buen amigo, Jose Daniel Ramos, sobre como quitar los "/" y los ":" de una expresion DATETIME() y pasar dicha expresion a una sola cadena tipo caracter, es decir, de esto "18/02/2013 04:57:PM" a 18022013045730.

Para esto, colocamos un codigo como este en algun evento o metodo:

LOCAL MIFECHA

MIFECHA=TTOC(DATETIME())
MIFECHA=PADC(TTOC(DATETIME()),20," ")
MIFECHA= STRTRAN(MIFECHA,":","")
MIFECHA=STRTRAN(MIFECHA,"/","")
MIFECHA=STRTRAN(MIFECHA," ","")

**Mostramos resultados
MESSAGEBOX(MIFECHA)
**--//

Y listo. Con esto, podemos incluir un registro cronologico, tal y como mencionaba Jose, de ciertas acciones, tales como complementos de nombres para archivos guardados en carpetas (respaldos), archivos generados en aplicaciones como excel o word o PDF, entre un sin numero mas de acciones.

Mil gracias Jose Ramos por el aporte.

Saludos. Sugerencias y comentarios son siempre bienvenidos para mejorar.
Un abrazo! Desde Managua, Nicaragua.
Febrero 2013


Ravenn! :)

miércoles, 28 de noviembre de 2012

Calcular dias de diferencia entre 2 fechas

Saludos. Algunas veces necesitamos calcular los dias de diferencia entre dos fechas. Por ejemplo... cuantos dias hay entre el 01/08/2012 y el 01/09/2012 (agosto - septiembre) y obtener el resultado en un numero entero especifico (30 dias). Imaginemos que tenemos un text1 donde ingresamos la fecha inicial (01/08/2012/) y un text2, donde ingresamos la fecha final (01/09/2012). Ambos tienen una D (formato fecha) en la propiedad Format de la pestaña DATA. En el Init del fomr configuramos (segun se desee) el tipo de siglo:

**--Para mostrar 2012 en lugar de 12
SET CENTURY ON

Luego, copiamos este codigo en algun evento:

LOCAL ldFechaDesde, ldFechaHasta, ldDiaD, ldMesD, ldAnoD,  ldDiaH, ldMesH, ldAnoH, lnFechaResul

*Fecha inicial
ldFechaDesde = CTOD(ALLTRIM(THISFORM.Text1.Value))

    ldAnoD = YEAR(ldFechaDesde)
    ldMesD = MONTH(ldFechaDesde)
    ldDiaD = DAY(ldFechaDesde)
   
**Fecha final
    ldFechaHasta = CTOD(ALLTRIM(THISFORM.Text2.Value))
   
        ldAnoH = YEAR(ldFechaHasta)
        ldMesH = MONTH(ldFechaHasta)
        ldDiaH = DAY(ldFechaHasta)
**
lnFechaResul =  DATE(ldAnoH, ldMesH, ldDiaH) - DATE(ldAnoD, ldMesD, ldDiaD)

MESSAGEBOX(lnFechaResul)


Y listo. Guardamos y ejecutamos.  El numero de dias lo tenemos contenido en la variable lnFechaResul y podemos proceder a hacer uso efectivo de el.

Saludos! Desde Managua, Nicaragua!
Ravenn :D :D :D

jueves, 15 de noviembre de 2012

Crear / Diseñar un formulario de acceso (Login) a nuestras aplicaciones - Visual FoxPro.

Saludos. En reiteradas ocasiones me han consultado como hacer un form de acceso (login) para nuestras aplicaciones. La solucion es sencilla. :)

 Todo parte de seguir una logica coherente: tenemos un formulario principal de nuestra aplicacion que es desde donde ejecutamos todas las transacciones. Para poder acceder a el, debemos "logearnos" o ingresar al sistema. Para esto, creamos un formulario adicional en donde podamos ingresar nuestro usuario y contraseña correspondiente. Asi mismo, debe existir, en la base de datos, una tabla en donde se lleve el control de los usuarios, contraseñas y accesos al sistema. Con accesos me refiero a los privilegios de entrada, visualizacion, adicion, modificacion y elimacion de registros. Este tema en especifico, lo tomaremos en la siguiente publicacion.

Veamos pues como se procede:

1. Diseñemos la tabla: los nombres de usuario y contraseña se almacenaran aqui. Creamos una tabla llamada "usuario" con los campos: codigousuario (numerico, width = 5, index = regular) , nom_usuar (caracter, width = 20, index = regular), contraseña (caracter, width = 15). Asi:


**Carguemos en la tabla algunos datos... para que podamos probar la funcionalidad posteriormente. Ingresemos el codigo: 1020 - usuario: Ravenn -  Contraseña: blogspot129

**Posterior a la creacion del login, se debe proceder a crear un form para la gestion (altas, bajas y modificaciones de los usuarios. Este punto, queda totalemente a criterio de los usuarios :)

2. Diseñemos el FORM: procedemos a crear un formulario para poder acceder con nuestro usuario y contraseña. Para esto, vamos al diseñador de forms y creamos un formulario llamado "Login" con los controles basicos necesarios, tales como: 2 cuadros de texto (TxtNom_Usuar, TxtContraseña), dos botones de comando (Command1, Command2). Uno para ingresar y otro para salir. Asi:


3. Escribimos el codigo:para esto, procedemos a crear un nuevo metodo en el formulario llamado "ingresar". Para esto, vamos al menu de foxpro, en el diseñador de forms y en el menu FORM, desplegamos y escogemos la opcion "NewMethod". Luego, vamos a las propiedades del form, en la pestaña Method y buscamos el metodo que acabamos de crear. Damos Db click y escribimos el siguiente codigo:

**--Ingreso**--

SELECT  usuario

SET ORDER to nom_usuar

SEEK  ALLTRIM(thisform.txtNom_usuar.value)        &&Asigna valor a variables&&

**--Devolvemos resultado
IF FOUND () AND ALLTRIM (THISFORM.txtContraseña.value) = ALLTRIM (usuario.Contraseña)
   
    **Si se encuentra el usuario y contraseña registrados.
   **Llamamos al form principal
   **Cerramos el form login

    DO FORM "principal.scx"
    THISFORM.Release
   
    **Si no encontramos usuario o contraseña
    ELSE
   
        MESSAGEBOX("El usuario y contraseña no son validos. Asegurese de digitar un usuario registrado.", 16, ;
       Error - Usuario y contraseña invalidos")
   
  **Cancelamos accion
   CANCEL

ENDIF

**--Fin--**


Ahora, vamos al evento click del Command 1 y llamamos al metodo:

THISFORM.ingresar

En el command2, escribimos (Salir):

THISFORM.Release

4. Agregamos la tabla: hacemos click derecho sobre el form y escogemos la opcion "data enviroment", ah buscamos la tabla usuario y la agregamos al entorno de datos de nuestro form.

 5. Desactivamos la tecla BloqMayus en contraseña: para evitar errores de escritura entre mayusculas y minusculas, podemos desactivar la tecla bloq mayus (para escribir solo minisculas) cuando el txtContraseña reciba el enfoque. Para esto, creamos otro metodo adicional al form llamado "desactivarBqMay" y en el, escribimos eset codigo:

**--Comprobamos el estado de la techa BloqMayus
**--Si esta encendida, procedemos a apagarla
**--CAPSLOCK() devuelve el estado de la tecla ON/OFF


IF CAPSLOCK() = .T.

        CAPSLOCK(.F.)

ENDIF
**--Fin**--

Ahora, en el evento GotFocus del TxtContraseña, llamamos al metodo:

**--
THISFORM.desactivarBqMay
**--

6. Configurar propiedades y funciones del Form: esto con el objetivo de mejorar el rendimiento del la aplicacion y evitar errores futuros.

6.1 **En las propiedades del form, en la pestaña DATA, escogemos la propiedad BufferMode y la establecemos en 2 - Optimistic. Asi mismo, la propiedad DATESESSION y establecemos 2 - private datesession (necesario para - SET EXCLUSIVE OFF - abrir archivos en modo compartido en red).

6.2 **En el evento INIT() del form, escribimos el siguiente conjunto de instrucciones.

**--Configuracion inicial
**----------------------
**----------------------

**--Apagamos conversacion de VFP
SET TALK OFF

**--Desactivamos registros marcados para eliminacion
SET DELETED ON

**--Por si usamos fecha para una vitacora de ingresos
**--El formato es dia/mes/año
SET DATE BRITISH

**--Necesario para modo compartido
SET MULTILOCKS ON


**--Abrir archivos en modo compartido
SET EXCLUSIVE OFF

**--Centrar el form
THISFORM.AutoCenter = .T.



**--Importante:
**--Configuramos modo (de bloqueo) compartido (Buffer) de tabla
**--Evitamos conflictos en red
CURSORSETPROP("Buffering", 5, "usuario")





Y listo. Guardemos y ejecutemos. Escribamos el usuario y contraseña.

Esta es una forma segura y sencilla de logearnos en nuestro sistema. No es la unica ni la mejor. Solo mi opinion! Cualquier duda, a la orden! Comenten!


Saludos! Desde Managua, Nicaragua!
Ravenn :D :D :D 


miércoles, 14 de noviembre de 2012

Generar un levantamiento de datos automatico de una tabla

Saludos. Siempre buscamos como automatizar mas los procedimientos de nuestras aplicaciones. :) Por ejemplo, para una aplicacion de facturacion, necesitamos introducir varios productos en un form (control grid) y para esto, es mas rapido si vamos digitando el codigo del producto y al presionar enter que se generen los datos de dicho producto, tales como descripcion, unidad de medida, precio, impuestos.. etc. Para lograr esto, procedemos asi:

Imaginemos que tenemos una tabla llamada "productos" con los campos: codigo, descripcion, unidadmedida, preciounitario. Queremos que, en un form de facturacion, digitemos (en una columna de un grid) el codigo del producto y que al presionar ENTER, se muestren los datos (en el resto de columnas) del producto de forma automatica.

1. Vamos al entorno de datos del formulario y agregamos la tabla que contiene los datos que vamos a "levantar" o "llamar": productos

2. En este ejemplo, tomamos que el codigo del producto se digitara en el text1 de la columna1 del grid1 y el resto de columnas mostraran la informacion al presionar enter. Para esto, escribimos un codigo como este en el evento KeyPress del text1 de la column1 del grid1:

**--

IF nKeyCode = 13     &&Presionamos enter
   
        SELECT productos
              LOCATE FOR productos.codigo = VAL(THISFORM.Grid1.Column1.Text1.Value)

                  IF FOUND()
                           **Cargamos descripcion
                           THISFORM.Grid1.Column2.Text1.Value = productos.descripcion
                           **Cargamos Unidad medida
                           THISFORM.Grid1.Column3.Text1.Value = productos.unidadmedida
                           **Cargamos precio
                           THISFORM.Grid1.Column4.Text1.Value = productos.preciounitario


                                         ELSE
                              
                                                   MESSAGEBOX("Producto no registrado en sistema. Verifique, 48, "Error")

ENDIF
**--


Guardamos y ejecutamos.

Saludos! Desde Managua, Nicaragua!
Ravenn :D :D :D












Saber el numero de registros marcados para eliminacion

Saludos. Algunas veces, necesitamos saber el numero de registros que hemos marcado para eliminacion (eliminados con DELETE y establecido SET DELETED en "ON") en nuestras tablas. Una forma sencilla de saber cuantos registros tenemos eliminados (no fisicamente) es asi:

1. Establecemos SET DELETED ON en el init del form



2.

LOCAL lnRegDel

**--
SELECT facturas

COUNT FOR DELETED() TO lnRegDel

MESSAGEBOX(lnRegDel)

**--

Saludos. Desde Managua, Nicaragua!
Ravenn :D :D :D

lunes, 12 de noviembre de 2012

Activar procesos con el teclado en metodo abreviado

Saludos. A veces necesitamos activar ciertos procesos en nuestros forms con las teclas (por lo general F1, F2...). Por ejemplo, activar un (form) calendario al presionar la tecla F9, agregar un nuevo registro al presionar la tecla F3, editar un registro con la tecla F4... cerrar un form con la tecla F12... entre otros. La solucion es asi:

1. En las propiedades del form, vamos a la pestaña OTHER y seleccionamos la propiedad Keypreview, estableciendola en .T.

2. Vamos al metodo KEYPRESS del formulario y colocamos un codigo como este:

**--Generamos calendario
IF nKeyCode = -3    &&Corresponde a F4
    THISFORM.activarcalendario
ENDIF


Lo que debemos hacer es buscar en la tabla de valores de la funcion INKEY() el valor correspondiente a la tecla que deseamos... o combinacion de teclas. Aqui dejo el link de la tabla!

http://msdn.microsoft.com/es-es/library/cc451013%28v=vs.71%29.aspx


Una vez escogido, solo asignamos el valor a nkeyCode, abajo colocamos el procedimiento que queremos, y listo. :)


Saludos! :) Desde Managua, Nicaragua.
Ravenn :D

viernes, 9 de noviembre de 2012

Importar hoja de excel a tabla (.dbf) de foxpro

Saludos. A veces  necesitamos importar un documento de excel a una tabla fisica (.dbf) o un cursor temporal de foxpro. Una forma practica de hacerlo es asi:

1.  Debemos, primeramente, tener en cuenta que el archivo de excel debe estar guardado en formato 5.0. Para esto, escogemos la opcion 

Libro de Microsoft Excel 5.0/95 (*.xls)

2.  Debemos tener en cuenta tambien que la etructura de la hoja de calculo debe ser similar a la de la tabla, en el sentido que si una de las columnas de excel almacena datos de fecha, el campo donde dichos datos seran guardados, debe ser tipo DATE.

3. Copiamos el siguiente codigo (en un boton [click] , por ejemplo):

LOCAL lcXlsArchivo

   
lcXlsArchivo = GETFILE('xls','Nombre:','Abrir',0 ,'Abrir Archivo de Planilla de Excel')

**--Si cancelamos la apertura
IF EMPTY(lcXlsArchivo)
    RETURN .F.
ENDIF
   
**--Si abrimos archivo, guardamos en cursor

SELECT personaltemp

APPEND FROM (xarchivo) TYPE XLS



Y listo. Ya tenemos un cursor guardado con datos de una hoja de excel 5.0 :)



SALUDOS! Desde Managua, Nicaragua! Raven :D

Generar un MENU CONTEXTUAL (con click derecho del mouse) para CORTAR, COPIAR, PEGAR

Saludos. Algunas veces deseamos colocar alguans opciones, tales como CORTAR - COPIAR - PEGAR al hacer click derecho sobre algun objeto (textbox, commandButton, etc...), asi:



La forma sencilla de hacerlo, es colocar el siguiente codigo en el evento RIGHTCLICK del objeto:


DEFINE POPUP menuccp  FROM MROW(),MCOL() ;
 SHORTCUT RELATIVE  MARGIN  COLOR RGB(255,255,255);
 FONT 'MS Sans Serif', 8
      DEFINE BAR  _MED_CUT OF menuccp  PROMPT "Cortar     Ctrl + X"   PICTURE 'cut.png'
      DEFINE BAR _MED_COPY OF menuccp PROMPT  "Copiar     Ctrl + C" PICTURE 'copiar.png'
      DEFINE BAR _MED_PASTE OF menuccp PROMPT "Pegar      Ctrl + V" PICTURE 'paste.png'
      DEFINE BAR 4 OF menuccp PROMPT '\-' 
      DEFINE BAR 5 OF menuccp PROMPT "Calculadora" PICTURE 'calc.png'
     
      **--Calculadora
      ON SELECTION BAR 5 OF menuccp ! /N calc.EXE
     
     
ACTIVATE POPUP menuccp
**--//Fin

Y listo. :D Guarden los cambios y ejecuten. Yo le agregue una opcion mas para activar la calculadora de WINDOWS! Pueden agregar n numero de opciones deseadas!


Saludos! Desde Managua, Nicaragua!
Ravenn! :D

Convertir un numero NEGATIVO (-) a POSITIVO (+)

Saludos! A veces necesitamos convertir un numero resultado negativo a positivo. Es facil. Asi:

ABS(numeronegativo)


**--

ABS(-45)

**--Resultado 45


Es una sencilla operacion, pero que a veces nos puede servir de mucho.

Saludos! Desde Managua, Nicaragua!
Ravenn