20 de julio de 2013

Navegación en Formularios ABM en entornos Cliente / Servidor

Autor: Antonio L. Montagut
www.ontarioxb.es

Mucho se ha hablado en los foros, sobre la conveniencia o no, de utilizar botones de navegación en formularios de mantenimiento o ABM. Nos referimos a los botones de navegación (Primero, Anterior, Siguiente, Último).

En mi opinión, si es aconsejable. Y además la velocidad de respuesta es inmediata. Os voy ha mostrar un ejemplo de su utilización en entornos MySQL / MariaDB, para lo cual hay que tener algunas consideraciones que comentaremos más adelante.

De momento vamos a comenzar por el principio. A través del Shell o línea de comandos de MySQL / MariaDB vamos a crear una base de datos y una pequeña tabla de clientes.
DROP DATABASE IF EXISTS mybd;
CREATE DATABASE IF NOT EXISTS mydb DEFAULT CHARACTER SET utf8 COLLATE utf8_spanish_ci ;
USE mydb;

DROP TABLE IF EXISTS clientes;
CREATE TABLE IF NOT EXISTS clientes (
  CODIGO varchar(6) COLLATE utf8_spanish_ci NOT NULL DEFAULT '000000',
  NOMBRE varchar(50) COLLATE utf8_spanish_ci NOT NULL DEFAULT '',
  DOMICILIO varchar(50) COLLATE utf8_spanish_ci NOT NULL DEFAULT '',
  POBLACION varchar(50) COLLATE utf8_spanish_ci NOT NULL DEFAULT '',
  CP varchar(7) COLLATE utf8_spanish_ci NOT NULL DEFAULT '',
  PROVINCIA varchar(50) COLLATE utf8_spanish_ci NOT NULL DEFAULT '',
  NIF varchar(15) COLLATE utf8_spanish_ci NOT NULL DEFAULT '',
  TLF1 varchar(15) COLLATE utf8_spanish_ci NOT NULL DEFAULT '',
  TLF2 varchar(15) COLLATE utf8_spanish_ci NOT NULL DEFAULT '',
  FAX varchar(15) COLLATE utf8_spanish_ci NOT NULL DEFAULT '',
  WEB varchar(40) COLLATE utf8_spanish_ci NOT NULL DEFAULT '',
  EMAIL varchar(50) COLLATE utf8_spanish_ci NOT NULL DEFAULT '',
  PRIMARY KEY (CODIGO)) 
ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci ROW_FORMAT=DYNAMIC;
Una vez creada la Base de Datos con la tabla Clientes. Y tener instalado el Driver ODBC 5.1x para MySQL / MariaDB ya podemos crear en VFP la conexión a la misma mediante la técnica del SQL Pass-Through.
RELEASE NH
PUBLIC NH AS Number 
NH = 0

cSQL = "DRIVER={MySQL ODBC 5.1 Driver};" + ;
  "SERVER=localhost;" + ;
  "PORT=3306;" + ;
  "UID=usuario;" + ;
  "PWD=password;" + ; 
  "DATABASE=mybd;" + ;
  "OPTION=" + ALLTRIM(STR(1+2+2048+16384+131072,08,00))

NH = SQLSTRINGCONNECT("" + cSQL, .T.)
IF NH < 0 
  MESSAGEBOX("Error de Conexión: " + ALLTRIM(STR(NH,10,00)), 48, "Atencion")
ENDIF
Una vez se ha producido la conexión satisfactoriamente, vamos a explicar la navegación a través de los diferentes "botones". La variable "cKEY" nos va a indicar el código del registro donde estamos posicionados actualmente, y a partir del cual vamos a proceder a la navegación.
RELEASE cKEY
PUBLIC cKEY
cKEY = '000777'  && Codigo inicial
• Primer Registro:
TEXT TO cSQL TEXTMERGE NOSHOW
SELECT * 
  FROM clientes FORCE INDEX(PRIMARY) 
  ORDER BY CODIGO LIMIT 1
ENDTEXT
SQLPREPARE(NH, "" + cSQL, "tcursor")
DO WHILE SQLEXEC(NH) = 0
ENDDO
SELECT tcursor
If recno() > 0
  cKEY = tcursor.CODIGO
ELSE
  cKEY = '000000'
ENDIF
USE
• Anterior Registro:
TEXT TO cSQL TEXTMERGE NOSHOW
SELECT *
  FROM clientes FORCE INDEX(PRIMARY) 
  WHERE CODIGO < ?cKEY 
  ORDER BY CODIGO DESC LIMIT 1
ENDTEXT
SQLPREPARE(NH, "" + cSQL, "tcursor")
DO WHILE SQLEXEC(NH) = 0
ENDDO
SELECT tcursor
If recno() > 0
  cKEY = tcursor.CODIGO
ELSE
  cKEY = '000000'
ENDIF
USE
• Siguiente Registro
TEXT TO cSQL TEXTMERGE NOSHOW
SELECT * 
  FROM clientes FORCE INDEX(PRIMARY) 
  WHERE CODIGO > ?cKEY 
  ORDER BY CODIGO LIMIT 1
ENDTEXT
SQLPREPARE(NH, "" + cSQL, "tcursor")
DO WHILE SQLEXEC(NH) = 0
ENDDO
SELECT tcursor
If recno() > 0
  cKEY = tcursor.CODIGO
ELSE
  cKEY = '000000'
ENDIF
USE
• Último Registro:
TEXT TO cSQL TEXTMERGE NOSHOW
SELECT * 
  FROM clientes FORCE INDEX(PRIMARY) 
  ORDER BY CODIGO DESC LIMIT 1
ENDTEXT
SQLPREPARE(NH, "" + cSQL, "tcursor")
DO WHILE SQLEXEC(NH) = 0
ENDDO
SELECT tcursor
If recno() > 0
  cKEY = tcursor.CODIGO
ELSE
  cKEY = '000000'
ENDIF
USE
Las consideraciones a tener en cuenta son las siguientes:
  • Utilizar la clave primaria de la tabla, esa es la explicación de la instrucción FORCE INDEX (PRIMARY). Acelera las consultas de una manera increíble.
  • Traer solo un solo registro y solo uno cada vez, esa es la explicación de la instrucción LIMIT 1.
  • No utilizar SELECT * . Esto conlleva traer todos los campos del registro de la tabla. Yo lo he puesto para simplificar el ejemplo pero no es muy aconsejable.
Aquí os dejo una pantalla de ejemplo de mi aplicación donde se aprecian los botones de navegación


Antonio L. Montagut

14 de julio de 2013

Colocar los procesos de Windows en una Tabla Temporal

Saber que procesos se ejecutan en Windows aveces es necesario saberlo en FoxPro y pienso que con este codigo les ayudaria mucho.

Es simple, este solo intruduce todos los procesos en una tabla temporal en fox... y si nuestra aplicacion depende de otro programita para su funcionamiento estaria genial para verificarlo...
FUNCTION VerProcesos()
   loService = Getobject("winmgmts:{impersonationLevel=impersonate}!\\.root\cimv2")
   loProcesses = loService.ExecQuery("SELECT * FROM Win32_Process")
   CREATE CURSOR procesos (Descripcion c(60))
   For Each loProcess In loProcesses
      Servicio = loProcess.Name
      INSERT INTO procesos (Descripcion) VALUES (Servicio)
   Next
   Return
ENDFUNC