Antes que nada mis felicitaciones por ser uno de los favoritos de todoexpertos, mi pregunta es como hacer mantenimiento de datos en power builder, se que existen muchas formas pero me gustaría que tu me dieras la mejor opción para poder hacerlo y me des ejemplos, es decir captura de errores, validación de campos, etc. El otro día encontré un ejemplo de validaciones con funciones pero se me olvido la página, bueno me gustaría saber como haces tu las validaciones o mantenimiento de datos en power builder y
5 Respuestas
Respuesta de Antonio Garcia
2
2
Antonio Garcia, clipper todas sus versiones (manejo total) power builder todas...
Pero solo trato de compartir lo poco que se, bien. Esta pregunta es un poco complicada de responder pero tratare de hacerlo lo más resumida posible, Un poco de referencia: Power builder es un lenguaje un poco peculiar y diferente al resto de los lenguajes, como ya te habrás dado cuenta no es un lenguaje orientado a objetos, por esta y otras razones, los generadores de power builder reunieron y generaron una serie de rutinas que otros desarrolladores generaban para hacer un poco más simple la tarea cotidiana y le llamaron pfc's, estas rutinas, objetos, clases, etc. están basadas en movimientos y tareas estándar, o sea algo que siempre va a ser así véalo por donde lo vea, por ejemplo un mantenimiento, este tipo de evento o tarea, es simplemente dar a una tabla la capacidad de insertar un registro (altas), modificar (cambios), y borrar (bajas), que es lo que normalmente se conoce como el ABC, si nos fundamos en esto, estamos visualizando un objeto que en principio se determine para hacer estas tareas. Ahora incrementemos el poder del lenguaje con lo que se conoce hoy día como la herencia, esto significa entonces que yo puedo hacer una pantalla, que contenga todos los elementos necesarios para dar un mantenimiento a una tabla, y luego heredar esta ventana y así poder utilizar siempre las mismas características en todos mis mantenimientos, es más si hiciera un cambio automáticamente este seria desplegado a todos los mantenimientos hijos. Opinión personal: Las pfc's incluidas en power builder son muy buenas y te ayudan a resolver muchas tareas con poco esfuerzo, sin embargo, suceden cosas como, que pasa cuando hay una nueva version y desaparecen ciertos comandos o instrucciones, o estos se vuelven obsoletos, pues eso paso en la transición de la version 6.5 a la 7.x, cambiaron las pfc's y todos aquellos que tenían sus aplicaciones basadas en estas rutinas, tuvieron que reprogramar algunas cosas. Esta es una de las razones más importantes por las cuales prefiero entonces, generar mis propias rutinas, clases, objetos, etc., puesto que así yo tengo el control total de mis aplicaciones, y pues hasta ahora por más que he migrado lo único que he encontrado es soluciones alternas a lo que yo ya hice hace 1 o 2 versiones antes, como por ejemplo, el centrado de una ventana, en la version 8.0 ya incluye el centrado de una ventana, el cual no funciona muy bien, puesto que no centra en caso de ser una ventana tipo child, motivo por el cual aun sigo utilizando mi rutina desde la version 6.0 Idea: Con todo lo anterior dicho, ahora es tiempo de que puedas pensar en generar tu propio manejador de mantenimientos: Elementos: Una ventana Un recuadro 5 botones Un datawindow control Preparación: Se toma la ventana y se coloca dentro de ella los elementos botones, recuadro, datawindow. Se integra a cada uno de los botones las tareas de insertar, borrar, modificar, grabar, (update())y al ultimo la salida de la ventana (close), cada una de estas tareas son manejadas por el datawindow control directamente, en el caso de modificación, el datawindow contiene una función que controla el status de cada una de las columnas esta función se llama SETITEMSTATUS(), esta cambia la forma de comportamiento de cada linea, te sugiero le eches un vistazo a la ayuda (nada complicado). Una vez asignado estas tareas, grabar la ventana en una librería que reconozcas como general, (y por supuesto en esta o estas incluir algunas otras cosas que puedas añadir). Utilizando la creación: Simplemente presionas el botón de herencia, y heredas la ventana que acabas de crear, ahora ya de entrada, puede controlar todo aquello que asignamos en la parte de preparación, entonces solo resta integrar un datawindow object el cual tendrás que crear por separado, y asignarlo al datawindow control, pudiendo entonces dar mantenimiento a una tabla Tienes que tener en cuenta que cuando asignes todos los campos de la tabla al datawindow, y unicamente presentes en esta los que vas a mantener, de esa manera la tabla no excluye a ninguno cuando hagas una acción en esta. Todo esto que te cuento, es lo más simple y abstracto que puedo decirte, a esto le puedes añadir tu toque personal, y complicar las cosas de tal manera que esa pantalla que inicio siendo simple, pueda ser muy sofisticada. Modo de validación Como estas utilizando el datawindow, este contiene 2 eventos que permiten hacer una validación. Itemerror() Itemchanched() ITEMERROR, controla el error del datawindow o de la base de datos, personalmente no lo utilizo en esta ocasión, posee un elemento numérico que deberá retornar, sus valores son: 0 - rechaza el valor que esta en el campo, y despliega un error 1 - rechaza el valor y no despliega error 2 - acepta el valor 3 - rechaza el valor pero permite cambiar de foco. Como ya habrás adivinado yo lo integro en 1 directamente hago un RETURN(1) El que me interesa es el ITEMCHANGED() Este evento te da 3 elementos necesarios para la validación de tus ingresos, 1 - row = la linea que actualmente esta siendo utilizada 2 - dwo = el objeto que esta siendo modificado 3 - data el valor por el cual va a ser cambiado el actual, este se encuentra en un formato string. Ok Este evento también retorna un valor numérico. 0 - lo acepta todo 1 - rechaza el valor y no deja cambiar de foco 2 - rechaza el valor pero si deja cambiar foco. Un ejemplo de uso: Imagina que en pantalla tienes un campo en el cual integras el precio de un producto, y quieres validar que no sea negativo su valor, la cosa seria ma o meno así: INTEGER li_return = 0 DECIMAL{2} ldc_precio CHOOSE CASE LOWER(dwo.name) CASE 'precio' ldc_precio = DEC(data) IF (ldc_precio < 0) THEN li_return = 1 messagebox('error', 'el precio del producto no puede ser negativo') END IF END CHOOSE RETURN(li_return) Cuidadín cuidadín ...! Cuando en el botón de grabar, osea cuando ya vayas ha efectuar, o ejecutar la función de UPDATE() del datawindow, utiliza la función ACCEPTTEXT() que produce una actualización forzada del campo que tenia el foco antes de saltar al siguiente, es por la falta de esta función que algunos campos son grabados con un valor nulo, ademas esta función también actúa sobre el itemchanged() y el itemerror(), y si se produce un error o propio o del dw, este inmediatamente es activado, Esto es a grandes rasgos una idea la cual puedes utilizar y complicar tanto como gustes o necesites. Lo mismo puedes pensar para un reporte, una vista, una consulta, una búsqueda, una ventana inicial, un menu, en fin. Con esto te digo que puedes componer tus propias pfcs, pero con la diferencia que tu tienes el control.
- Anónimoahora mismo
Respuesta de aldob
1
1
aldob, Ingeniero en Sistemas con amplia experiencia en desarrollo de...
Mantenimiento de datos es un concepto muy genérico... El secreto de todo en PB está en la herencia, podes ir desarrollando objetos genéricos de los más usados y después sencillamente crear nuevos que hereden de éstos para resolver casos particulares. Si hablás de datos estás hablando de dw, el objeto más poderoso que tiene PB ya que te permite conectarte a cualquier bd de una manera simple y directa. Podés crear un obj dw genérico al que le codifiqués los eventos: 1)Dberror (errores de bd) Acá podés sacar un mensaje que indique el error que ha ocurrido y tal vez genere un log de errores de BD para que lo vea un administrador cada tanto. Los elementos que necesitás están dados como argumentos del evento, es decir están a tu disposición en el script. Personalmente acá tengo una función que recibe el sqldbcode y busca en una tabla la traducción de este error (originalmente en el lenguaje del DBMS) al castellano. También informa la fila en la que ocurrió el error (otro de los argumentos) 2)Error Cuando hay algún error grave. Acá genero un log con lo que ocurrió ya que me interesa porque generalmente es un error de programación (referencia a obj nulos, etc) y le agregó está línea "action = ExceptionIgnore!" para evitar que se cierre PB 3) Itemerror (Error en el tipo de dato de una columna) Acá tengo un case que analiza el tipo de dato de la columna en la que ocurrióo el error y saca un mensaje en castellano, además setea la columna a nulo para que el error no se siga produciendo ... //una porción de código código CHOOSE CASE Upper(ls_datatype) CASE "LONG","NUMBER","INT","REAL" decimal null_dec SetNull(null_dec) This.SetItem(row, ls_colname, null_dec) RETURN 3 CASE "DATE" date null_date SetNull(null_date) This.SetItem(row, ls_colname, null_date) RETURN 3 CASE "DATETIME" datetime null_datetime SetNull(null_datetime) This.SetItem(row, ls_colname, null_datetime) RETURN 3 END CHOOSE Código ... --- Esta dw la uso en todos los lugares donde trabajo con ingreso de datos. Después de esta dw heredo otra que uso en los listados y que además tiene codificado el retrieveEnd() para que saque un mensaje si no existen registros. Luego empezás a armar ventanas que contengan estas dw y le agregás botones que trabajen con las dw, ej: Consultar/Recuperar, Agregar, Quitar, Cancelar, Guardar, Buscar, etc. Lo primero que podes hacer es una ventana estándar de ABM en la que planteas todas las opciones posibles para lo que son ABMs simples (una tabla) y después heredas de la venta creando ventanas nuevas a las que les asignas el dataobject correspondiente al control dw y listo. Una dato importante, las windowFunctions permite realizar polimorfismo (es decir que los descendientes sobreescriban y/o extioendan funcionalidad de los ancestros de una manera muy simple y eficiente. A medida que vas avanzando en el desarrollo te vas a ir dando cuenta de cosas que podes generalizar, en estos casos fíjate donde podes colocar el código correspondiente como para tener que escribirlo una vez y después heredar. En internet hay varios lugares de donde sacar manuales pero además la ayuda de PB y los online books son una gran fuente de material y ej. de codificación. También están los ejemplos del programador. Si querés que yo te pase algunos manuales que tengo (700kb) necesito una dirección de mail.
Gracias por las felicitaciones pero según el ranking no estoy en una buena posición. Bueno, lo que pides es bastante largo, pero se va ha hacer lo que se pueda. Si me pasas una dirección de correos te puedo enviar más información. Para la validadción de datos en datawindows/datastore uso lo siguiente: He creado un objeto de usuario basado en las datawindows para el control de errores, y evitar valores nulos. Para ello en el evento updatestar meto el siguiente código: datetime ldtm_GetItemDateTime decimal ldc_GetItemDecimal integer li_GetObjects long ll_Cont1,ll_Cont2,ll_RowCount string ls_GetObjects[],ls_ColType,ls_ColType4,ls_GetItemString,ls_Type,ls_ColType7 this.of_setbase(true) ll_RowCount = this.rowcount() li_GetObjects = this.inv_base.of_getobjects(ls_GetObjects,'*','*',false) for ll_Cont1 = 1 to ll_RowCount for ll_Cont2 = 1 to li_GetObjects ls_Type = upper(this.describe(ls_GetObjects[ll_Cont2] + ".type")) if ls_Type = 'COLUMN' then ls_ColType = upper(this.describe(ls_GetObjects[ll_Cont2] + ".coltype")) ls_ColType4 = left(ls_ColType,4) ls_ColType7 = left(ls_ColType,7) if ls_ColType4 = 'CHAR' then ls_GetItemString = this.getitemstring(ll_Cont1,ls_GetObjects[ll_Cont2]) if ls_GetItemString = '' or isnull(ls_GetItemString) then ls_GetItemString = ' ' this.setitem(ll_Cont1,ls_GetObjects[ll_Cont2],ls_GetItemString) end if elseif ls_ColType7 = 'DECIMAL' then ldc_GetItemDecimal = this.getitemdecimal(ll_Cont1,ls_GetObjects[ll_Cont2]) if isnull(ldc_GetItemDecimal) then ldc_GetItemDecimal = 0 this.setitem(ll_Cont1,ls_GetObjects[ll_Cont2],ldc_GetItemDecimal) end if elseif ls_ColType = 'DATETIME' then ldtm_GetItemDateTime = this.getitemdatetime(ll_Cont1,ls_GetObjects[ll_Cont2]) if isnull(ldtm_GetItemDateTime) then ldtm_GetItemDateTime = datetime(date('01/01/1900')) this.setitem(ll_Cont1,ls_GetObjects[ll_Cont2],ldtm_GetItemDateTime) end if end if end if next next De esta forma evito la entrada de valores nulos y no me preocupo del número de campos y longitud de la dw.
He de añadir que que en este caso uso las PFC como base, por lo que mi objeto n_ds_general y n_dw_general están heredados de n_ds y n_dw de las PFE respectivamente. Para la validación de campos nulos uso las siguientes funciones publicas que retornan un boleano: f_EsNulo_f(datetime) f_EsNulo_d(date) f_EsNulo_s(String) f_EsNulo_n(Numeric) y el código es el siguiente para cada uno: f_EsNulo_d(Date) Retorna: Boolean ---------------------------------------- //verifica fecha If isnull (adt_fecha) OR adt_fecha = date ('01/01/1900') Then return TRUE Else return FALSE End if f_EsNulo_f(DateTime) Retorna: Boolean ---------------------------------------- datetime ldt_fnull ldt_fnull = datetime(date(1900,1,1), 00:00:00) If isnull (adt_fecha) OR adt_fecha = ldt_fnull Then return TRUE Else return FALSE End if f_EsNulo_n(Decimal) Retorna: Boolean ---------------------------------------- If isnull (adec_numero) OR adec_numero = 0 Then return TRUE Else Return FALSE End if f_EsNulo_s(String) Retorna: Boolean ---------------------------------------- If isnull (as_cadena) OR Trim (as_cadena) = "" Then return TRUE Else return FALSE End if Te recomiendo que coloques todas estas funciones y los objetos de dw y ds en una librería para que la tengas todas juntas.
- Anónimoahora mismo
Respuesta de achafio
1
1
achafio, Bachiller Ingenieria de Sistemas e Informatica Conocimientos en...
Pero estamos para ayudarnos unos a otros. Bueno, en cuanto a tu pregunta, acerca de la validación, yo utilizo eventos, y desde ahí hago la validación, cuando es nulo, si ha ingresado valores erróneos, etc. Acerca del mantenimiento de datos, eso depende de lo que quieras hacer. Quisiera que me des más detalle de esta parte. Cualquier otra duda o problema, solo dímela
- Anónimoahora mismo
Respuesta de fernando_ghg
1
1
fernando_ghg, Ingeniero Tecnico en Informatica de Sistemas