¿Qué es un DataWindowChild?


Un DataWindowChild es un DropDownDataWindow en un objeto DataWindow. Un DropDownDataWindow se comporta como un objeto Child (hijo) del  DataWindow que lo contiene.


Los DataWindowChild son útiles por ejemplo para mostrar información de tablas maestras en forma de listado ó filtrar información de un campo.

¿Cómo se crea un DataWindowChild?

Veamos un ejemplo.

Se tiene un campo cod_area,  el cual al seleccionar muestra un listado de todas las áreas de una empresa.

  1. En la imagen tenemos los datos de la tabla maestra que almacena las Areas.

  2. Listado Tabla Area
  3. Se crea el objeto DataWindow que será vinculado como Child y mostrará el listado de Areas. Este objeto se crea según los datos de la tabla maestra Area.  En este DataWindow solo debe mostrarse los campos que se desea visualizar. Guardamos el objeto con el nombre d_area.


  4. Objeto DataWindow que se vinculara como Child
  5. Seleccionamos el campo cod_area en el cual se creara el vinculo y nos desplazamos a la pestaña Edit de la ventana de propiedades, en la opción Style Type seleccionamos la opción DropDownDW,  en la misma pestaña nos desplazamos hacia abajo y buscamos la opción DataWindow, hacemos clic y seleccionamos el DataWindow creado en el paso 2. En la opción Display Column seleccionamos el campo des_area que viene a ser el nombre, en la opción Data Column seleccionamos el campo cod_area que es el código del area seleccionada.


  6. Objeto DataWindow que contiene el Child
    Objeto DataWindow que contiene el Child
  1. El listado final del campo cod_area seria como la imagen siguiente.
Vista Final




DataWindow no visual, DataStore


El DataStore es un control DataWindow no visual, las ventaja principal de usar un DataStore frente a un DataWindow es que consume menos recursos, por ende es mas eficiente en recuperar datos.

La manipulación de un DataStore es similar a un DataWindow. En el siguiente ejemplo dejo el código para declarar y recuperar datos usando un DataStore.




DataStore ds_prueba //Declara variable del tipo DataStore

ds_prueba=Create DataStore //Se Instancia la variable

ds_prueba.DataObject="dw_authors" //Se establece el objeto DataWindow

ds_prueba.SetTransObject(SQLCA) //Se conecta a la BD

ds_prueba.Retrieve() //Recupera la información


Nota: el DataObject siempre se establece antes de conectar el DataStore a la Base de Datos.


Articulos de apoyo:
Conexión a SQL Server
Conexion a SQL Server mediante OLE DB 
Conexion a MySQL

¿Dudas?, ¿Comentarios?.




Crear columna de IDENTIDAD usando función IDENTITY en SQL Server


En SQL Server existe una función llamada IDENTITY, la cual permite crear una columna de identidad en una nueva tabla.

Esta función se utiliza en instrucciones SELECT INTO.

Otro punto importante es que esta función es distinta a la propiedad IDENTITY que se utiliza con la sentencia CREATE TABLE y ALTER TABLE.




SELECT nombre,
       apellido,
       IDENTITY(INTEGER,100,1) AS Id_emp
INTO  empleado_2
FROM  empleado


En el código anterior se crea una nueva tabla llamada empleado_2, y se crea la columna Id_emp el cual es un campo IDENTITY el cual su indice iniciara del numero 100 y se incrementara en 1.

Nota: Esta función IDENTITY no admite pasar valores mediante variables.




Validar campos de un Datawindow usando propiedad “required”


El objeto DataWindow cuenta con un método llamado FindRequired() el cual devuelve aquellas columnas que han sido marcadas como "requeridas", y contienen valores Null.

Antes, especificamos los campos que seran validados con sus respectivos mensajes, para eso entramos en modo diseño en el DataWindow.

Seleccionamos el campo a validar, luego seleccionamos la propiedad required que se encuentra en la pestaña Edit

Nos desplazamos en la lista de de columnas y escribimos el mensaje que deseamos que se muestre en el mensaje de validación.


Ahora si, estamos listos para escribir el código de validación.




long        ll_row      //Almacena la fila en donde se encuentra el campo con valor null.
integer     li_columna  //Almacena el numero de columna con valor null.
string      ls_colname  //Almacena el nombre de la columna con valor null.
string      ls_columna  //Almacena el mensaje de validación de la columna.


dw_1.AcceptText()

ll_row=1
li_columna = 0

dw_1.FindRequired(Primary!,ll_row, li_columna,ls_colname, True)

IF ll_row <> 0 THEN
      dw_1.SetColumn(li_columna)
      dw_1.ScrollToRow(ll_row)

      //Obtenemos el mensaje de validación obtenido.
      ls_columna= dw_1.describe(ls_colname+'.ValidationMsg')

      //Quitamos las comillas del mensaje de validación.
      ls_columna=left(ls_columna,len(ls_columna)-1)
      ls_columna=mid(ls_columna,2,len(ls_columna))
     
      dw_1.SetFocus()
     
      //Mostramos el mensaje de validación.
      messagebox("Verifique",ls_columna,Exclamation!)
END IF


¿Dudas?, ¿Comentarios?.




Filtrar datos de columna en DataWindow


El DataWindow cuenta con los métodos SetFilter() y Filter() para realizar filtros según el criterio que le indiquemos. 

En el ejemplo realizamos diversos tipos de filtrado:


//Filtro por rango de fecha.
dw_1.SetFilter("FechaNac>=datetime('01/01/1988') AND FechaNac<=datetime('01/01/1990')")
dw_1.Filter()

// Filtro por campo único
dw_1.SetFilter("Cod_empleado='PMA42628M'")
dw_1.Filter()

//Filtro según modelo usando caracteres comodín
dw_1.SetFilter("(Nombre like '%maria%') and (Apellido like '%rodriguez%')")
dw_1.Filter()

//Filtro por rango de número
dw_1.SetFilter("Edad >20 and  Edad<=30")
dw_1.Filter()


El método SetFilter() establece los criterios de filtrado.

El método Filter() ejecuta el filtro según los criterios establecidos.

¿Dudas?, ¿Comentarios?.




Ejecutar Procedimiento Almacenado en PowerBuilder


En el ejemplo mostrare como ejecutar un Procedimiento Almacenado de SQL Server desde PowerBuilder.

Mostraremos tres escenarios distintos:

1. Cuando el Procedimientos Almacenado devuelve uno o más parámetros de salida también llamado parámetro OUTPUT.

2. Cuando  devuelve un conjunto de resultados producto de una sentencia select.

3. El tercero y más simple, cuando el Procedimiento Almacenado no tiene parámetro alguno.

Escenario 1: Cuando el Procedimiento Almacenado devuelve valor mediante variables OUTPUT.

Primero definimos el código del Procedimiento Almacenado, el cual su función es devolver el producto de la multiplicación del valor de parámetro1 y el valor de PI que es 3.1416.

Ojo, devemos definir el parametro de retorno como OUTPUT


CREATE PROCEDURE usp_escenario1 @parametro1 INTEGER,@parametro2 DECIMAL(18,2) OUTPUT
AS
BEGIN
      SET @parametro2=@parametro1 * 3.1416
END

En la cuadro siguiente el código de PowerBuilder usado.



Integer Valor
Decimal Resultado

Valor=10

//Considerar que las variables que se pasen deben ser del mismo tipo
//definido en el procedimiento almacenado

DECLARE  sp_procedure PROCEDURE FOR usp_escenario1
@parametro1 = :Valor,
@parametro2 = :Resultado OUTPUT; //Ojo definir el parametro2 como OUTPUT.


EXECUTE sp_procedure; //Ejecutamos con el nombre del Alias

FETCH sp_procedure INTO :Resultado; //Recuperamos el resultado

CLOSE sp_procedure;

messagebox("",Resultado)



Escenario 2 y Escenario 3: Cuando devuelve un conjunto de resultados producto de una sentencia select y cuando el procedimiento no tiene parámetros, como diría mi abuela aquí matamos dos pájaros de un tiro, abordando los dos últimos escenarios restantes.

Para una mejor manipulación de los resultados devueltos por un Procedimiento Almacenado es aconsejable realizarlo mediante un DataWindow, pero eso será tema de otro artículo.

Definimos el código del Procedimiento Almacenado, el cual no pasamos ningún parámetro simplemente ejecutamos el procedimiento y recuperamos el conjunto de resultados.




CREATE PROCEDURE usp_escenario2_3
AS
BEGIN
      CREATE TABLE #cliente
      (
        codigo int,
        nombre varchar(15)
      ) 
     
      INSERT INTO #cliente VALUES(1,'PEPE')
      INSERT INTO #cliente VALUES(2,'JUAN')
      INSERT INTO #cliente VALUES(3,'MARIA')
     
      SELECT codigo,nombre FROM #cliente
END


En la cuadro siguiente el código de PowerBuilder usado.



Integer codigo
String  nombre

//Considerar que las variables que se pasen deben ser del mismo tipo definido en
//el procedimiento almacenado

DECLARE sp_procedure PROCEDURE FOR usp_escenario2_3;

EXECUTE sp_procedure; //Ejecutamos con el nombre del Alias

FETCH sp_procedure INTO :codigo,:nombre; //Recuperamos el resultado

DO WHILE sqlca.sqlcode = 0
      Messagebox("Resultado",string(codigo)+" " +nombre)
      FETCH sp_procedure INTO :codigo,:nombre;
LOOP
CLOSE  sp_procedure;


Articulos de apoyo:
Conexión a SQL Server
Conexion a SQL Server mediante OLE DB




¿Por qué y para qué es bueno PowerBuilder?


PowerBuilder
En algún momento nos hemos hecho la misma pregunta, ¿Que es PowerBuilder?, ¿Para que sirve PowerBuilder?, o también, ¿Es bueno PowerBuilder?, pero antes de nada un poco de historia.

PowerBuilder fue desarrollado hace ya muchos años atrás, en los años 1991 bajo el mando de la compañía PowerSoft lanzando la versión 1.0, la versión 2.0 fue lanzada en 1992, en esta versión PowerBuilder incluye la herencia y encapsulación, haciendo de PowerBuilder un lenguaje netamente orientado a objetos.  En 1995 PowerSoft fue adquirida por la compañía Sybase, lanzando las versiones sucesoras.

PowerBuilder es una herramienta empresarial, para arquitecturas  cliente/servidor , distribuida y web, orientado completamente a objetos, adicionalmente PowerBuilder posee un objeto nativo para la gestión y manipulación de datos llamado DataWindow el cual nos permite Insertar, Actualizar, Eliminar datos, adicionalmente nos permite visualizar los datos en múltiples formatos y vistas según la necesidad.

El objeto DataWindow se ha convertido en la piedra angular de PowerBuilder, hace que el trabajo con datos sea realmente sencillo, donde el programador con pocas líneas de código pueda tener una interfaz de usuario con validación y actualización de datos en minutos, haciendo más productivo la etapa de desarrollo.

Desde mi punto de vista PowerBuilder es por excelencia el mejor Lenguaje de Programación para desarrollar herramientas y sistemas empresariales para la gestión de datos, este es quizá su punto fuerte y donde mejor se desempeña.

He leído en la página de Sybase donde indica que PowerBuilder es un lenguaje de programación de propósito general, pero a mi modo de ver no es así, PowerBuilder no es recomendable para desarrollar aplicaciones de uso general, donde PoweBuilder es experto e idóneo, y como ya lo mencione es en la Gestión de Datos, es ahí donde PowerBuilder es la mejor elección.




Mostrar cuadro de dialogo "Abrir" para seleccionar un archivo


Aquí dejo un ejemplo de cómo utilizar el cuadro de dialogo Abrir para seleccionar un archivo de nuestro ordenador y guadar la ruta y el nombre del archivo en una variable.


String    ls_ruta, ls_file 


GetFileOpenName('Elegir Archivo',ls_ruta, ls_file,"XLS","Texto (*.txt),*.txt,Excel (*.xls),*.xls")

 /*

- El primer parámetro  indicamos el titulo que tendrá el cuadro de dialogo
- El segundo parámetro, si seleccionas un solo archivo guarda la ruta  completa del archivo
   Ejm: "C:\imagenes\miarchivo.jpg"
   Si, seleccionase más de un archivo, guarda la ruta del directorio donde se encuentra el archivo seleccionado. 
   Ejm: "C:\imagenes"
- El tercer parámetro  Almacena el nombre del archivo
- El  cuarto parámetro es opcional, indicamos el tipo de archivo por defecto definidos en el filtro.
- El quinto parámetro es opcional, ahi indicamos el filtro para que se muestre determinados archivos 
*/ 


if ls_ruta = '' OR IsNull(ls_ruta) then return 
//Valida que exista el archivo
 if  FileExists(ls_ruta)=false then
     messagebox("Verifique","El archivo no existe")
     
return
end if





Conectar PowerBuilder con Base de Datos MySQL 5.x


PowerBuilder puede trabajar de manera excelente con MySQL, la conexión se realiza mediante conexión ODBC usando el driver que el mismo MySQL pone a disposición y que lo pueden descargar en este enlace http://www.mysql.com/downloads/connector/odbc/ . La conexión se realizara sin necesidad de crear ningún DSN, si no de manera directa.

Para el ejemplo nos conectaremos a la base de datos mysql.

Este ejemplo considera que se tiene acceso al servidor MySQL así como a la base de datos mysql.



SQLCA.dbms="ODBC"
SQLCA.dbparm="ConnectString='DRIVER={MySQL ODBC 5.1 Driver}; SERVER=localhost;PORT=3306;DATABASE=mysql;UID=usuario;PWD=contrasena;
OPTION=135168;DisableBind=1;'"

connect using  SQLCA;

Nota:
  • En la sección "DRIVER={}" la conexión puede variar según la versión del driver que descarguemos de la página de MySQL, para el ejemplo se descargo el driver mysql-connector-odbc-5.1.6-win32
  • Los parámetros usados SERVER,PORT, DATABASE,UID,PWD puede variar según la configuración actual de su servidor.







Alternar colores en cada Fila de un DataWindow


A continuación veremos como crear un DataWindow tipo Grid en donde los colores de cada fila se alternen, el objetivo es llegar a tener un DataWindow  que nos muestre un listado tipo Grid donde se alternen los colores.

Este es un ejemplo de un DataWindow Grid con el listado de la tabla authors de la base de datos pubs en SQL Server 2000

Ejemplo de alternar colores


Pues bien para empezar crearemos dos funciones: f_dw_get_objects, f_registros_colores

El código de cada función a continuación:

f_dw_get_objects
El código para que copie/pegue

Nota: No olvidar definir los parámetros según la imagen mostrada. 

//f_dw_get_objects
//Esta función a sido creada por PowerBuilder asi que lo copiamos tal cual.
//Esta funcion retorna todas las columnas contenidas en el DataWindow




string obj_string, obj_holder

int obj_count, start_pos=1, tab_pos, count = 0



obj_string = Describe(dw_arg,"datawindow.objects")

tab_pos =  Pos(obj_string,"~t",start_pos)

DO WHILE tab_pos > 0

obj_holder = Mid(obj_string,start_pos,(tab_pos - start_pos))

     IF (Describe(dw_arg,obj_holder+".type") = obj_type or obj_type = "*") AND &

          (Describe(dw_arg,obj_holder+".band") = band or band = "*") THEN

                count = count + 1

                obj_list[count] = obj_holder

     END IF

     start_pos = tab_pos + 1

     tab_pos =  Pos(obj_string,"~t",start_pos)

LOOP

obj_holder = Mid(obj_string,start_pos,Len(obj_string))

IF (Describe(dw_arg,obj_holder+".type") = obj_type or obj_type = "*") AND &

     (Describe(dw_arg,obj_holder+".band") = band or band = "*") THEN

     count = count + 1

     obj_list[count] = obj_holder

END IF

Return count


f_registro_colores

El código para que copie/pegue

Nota: No olvidar definir los parámetros según la imagen mostrada. 

//Esta funcion toma como parametro el DataWindow y alterna los colores 
string    lista[]

integer   li_nn

integer   li_columnas

long      gl_color_registros



//Esta variable se puede declarar como global

gl_color_registros=RGB(191,223,255) //El color que deseamos


li_columnas=f_dw_get_objects(adw_origen,lista,"column","*")

for li_nn = 1 to li_columnas

     adw_origen.modify(lista[li_nn]+'.background.color="16777215~tif (mod(getrow(),2)=0,16777215,'+string(gl_color_registros) +')"')

next

Ahora en el DataWindow en su evento Constructor() poner el siguiente código:



//Evento constructor del DataWindow
f_registros_colores(this)





Crear DataWindow Dinámico


A continuación veremos cómo se crea un DataWindow dinámico de manera fácil y clara.

Para el ejemplo usamos la base de datos pubs de SQL Server 2000, listaremos tres campos de la tabla authors.

Para desarrollar el ejemplo creamos una ventana y dentro de ella creamos un botón llamado cb_1, creamos un datawindow llamado dw_1.

En el evento clicked del botón cb_1 insertaremos el código siguiente:



Ejecutamos el programa y el resultado debería ser similar a la siguiente imagen.






Conexión a SQL Server 2000 desde PowerBuilder 9.x usando archivo INI



Siguiendo con el tema de manejo y uso de conexiones a SQL server, en el presente código veremos cómo realizar una conexión a SQL Server 2000 tomando sus parámetros de conexión desde un archivo INI.

El primer paso es definir de manera correcta la estructura del archivo INI, registrando los principales parámetros que se necesita para realizar una conexión con éxito.

Pues bien aquí dejo una muestra del archivo INI usado en este ejemplo.

Nombre del Archivo: conexion.ini




[sqlserver] 
DBMS=MSS Microsoft SQL Server 6.x
Database=prueba
ServerName=ATENA
LogId=sa


Código para realizar la conexión


String startupfile


startupfile="conexion.ini" 


SQLCA.DBMS = ProfileString (startupfile, "sqlserver", "DBMS", "")
SQLCA.database = ProfileString (startupfile, "sqlserver", "Database", "")
SQLCA.servername = ProfileString (startupfile, "sqlserver", "ServerName", "")
SQLCA.logid =ProfileString (startupfile, "sqlserver", "LogId", "")
SQLCA.logpass ="contraseña"


connect using SQLCA;

Los archivos INI también son útiles para almacenar información acerca de las preferencias de los usuarios así como otros parámetros usados por la aplicación.




Creación de variable "transaction"



Hay situaciones en las que es necesario lidiar con más de una base de datos, pero ¿como realizamos esta operación?, ¿desconectamos la variable de transacción SQLCA y nos conectamos a la nueva base de datos?, afortunadamente en PowerBuilder esta tarea es sencilla, solo debemos crear un objeto transaction y asignar sus parámetros de conexión  y listo, tendremos dos objetos transaction conectados a sus respectivas base de datos.

En este ejercicio se crea un nuevo objeto transaction y se asigna sus parámetros de conexión y finalmente se asigna a un DataWindow el nuevo objeto transaction.


transaction NewTrx


NewTrx = create transaction 


NewTrx.dbms="OLE DB"
NewTrx.logid="sa"
NewTrx.logpass="1234"
NewTrx.servername="ATENA"
NewTrx.DBParm="PROVIDER='SQLOLEDB',DATASOURCE='ATENA',PROVIDERSTRING='prueba'"

connect using NewTrx;
if sqlca.sqlcode<>0 then
   MessageBox ("ERROR", "Error en conexión" + NewTrx.sqlerrtext)
   return
  end if

messagebox("Exito","Se Conecto a la Base de Datos")


dw_1.setTransObject(NewTrx) 





Conexión a SQL SERVER 2000 mediante OLE DB



PowerBuilder desde la versión 10 no tiene soporte para conexiones nativas con Sql Server, en su reemplazo la conexión se realiza vía OLE DB y ADO.NET.

Pues bien ante este problema pondré el código que utilice para realizar la conexión  mediante OLE DB:

SQLCA.dbms="OLE DB"
SQLCA.logid="sa"
SQLCA.logpass="1234"
SQLCA.servername="ATENA"
SQLCA.DBParm="PROVIDER='SQLOLEDB',DATASOURCE='ATENA',PROVIDERSTRING='database=prueba'"

connect;
if sqlca.sqlcode<>0 then
   MessageBox ("ERROR", "Error en conexión" + sqlca.sqlerrtext)
   return
  end if

messagebox("Exito","Se Conecto a la Base de Datos")



Detalles del servidor:

Nombre de Servidor: "ATENA"
Nombre de Base Datos: "prueba"
Usuario para conexion: "sa"
Contraseña del usuario: "1234"