Hola Pedro,

Pedro escribió:
Hola Ariel,

Gracias por la ayuda con listas desplegables, no tuve problemas al ajustarlas al documento.

necesito seleccionar de una lista desplegable un elemento que me entregará un valor en un campo numérico de un formulario en el documento .odt, ya probé con la rutina:

Sub ActualizaForm(oEvent)
Dim oModelo, oForm
Dim sCampo$, iItemSeleccionado%, sValorSelecc$, sFiltro$
oModelo = oEvent.Source.Model
sCampo = oModelo.DataField
iItemSeleccionado = oModelo.SelectedItems(0)
sValorSelecc = oModelo.ValueItemList(iItemSeleccionado) oForm = oModelo.Parent
sFiltro = sCampo + "=" + sValorSelecc

REM tildar lo siguiente si NO se desea actualizar el registro con los datos del formulario
oForm.updateRow()

oForm.Filter = sFiltro
oForm.ApplyFilter = True
oForm.reload()
End Sub

Al ejecutar esta rutina, el mensaje que aparece dice "Tipo de datos o valor inadmisible. Índice fuera del área definida".


Para saber bien en qué línea se produce el error, te aconsejo que incluyas en todas tus rutinas un manejo de error, con un mensaje de error indicando la línea (busca en la Ayuda de OOo Basic Err y Error).

Si no, no puedo saber dónde se produce exactamente. Así que lo que sigue puede no ser que resuelva tu problema (de todas formas seguramente será útil -- ...espero ).

Veamos si es lo siguiente: seguramente has copiado el código de alguno de mis ejemplos ... mea culpa [1], el empleo de updateRow() es bastante peligroso, por lo menos así solo como está: updateRow() lo que hace es actualizar la respectiva fila de la base de datos con el contenido del formulario, pero no puede emplearse siempre:

http://api.openoffice.org/docs/common/ref/com/sun/star/sdbc/XResultSetUpdate.html#updateRow
"updates the underlying database with the new contents of the current row. *Cannot* be called when on the insert row."


En varias ocasiones es necesario actualizar la fila actual: si estás por filtrar el formulario de acuerdo a lo seleccionado en la lista, es posible que el contenido actual del formulario haya sido modificado, y si aplicas el filtro, esos cambios NO se guardan, debes guardarlos tú. Para ello sirve updateRow().

Pero prueba con mover todo el formulario para insertar un nuevo registro, luego intenta aplicar updateRow(): te genera un error pues updateRow() "*Cannot* be called when on the insert row"


Lo más elegante y *seguro* para solucionar todo esto es emplear la nueva interfaz XFormOperations:
http://api.openoffice.org/docs/common/ref/com/sun/star/form/runtime/XFormOperations.html

Te recomiendo que leas la "Description".

Un work-around si no deseas emplear esa nueva interfaz, es verificar el estado del formulario antes de invocar updateRow()

        oForm = oEvent.Source.Model.Parent
        If oForm.AllowUpdates AND oForm.IsModified AND NOT oForm.IsNew Then
                oForm.updateRow()
        End If

AllowUpdates indica si el formulario acepta modificaciones. Nota que esto no quiere decir SI tienes privilegios INSERT sobre la base de datos, sino sólo si el formulario está configurado para ingresar datos. Si retorna FALSE, mediante la API igual puedes insertar datos, siempre que la base de datos te lo permita. Para averiguar esto debes emplear otros métodos (no los explico porque suponemos que trabajas con una base HSQLDB embebida y no hay problemas de privilegios de usuario).
http://api.openoffice.org/docs/common/ref/com/sun/star/form/component/DataForm.html#AllowUpdates

IsModified indica que la fila actual ha sido modificada
http://api.openoffice.org/docs/common/ref/com/sun/star/sdb/RowSet.html#IsModified

IsNew indica si el RowSet está posicionado en un registro nuevo
http://api.openoffice.org/docs/common/ref/com/sun/star/sdb/RowSet.html#IsNew

Empleo NOT IsNew porque si IsNew es TRUE, no puedes emplear updateRow(), sino insertRow(). *PERO* para emplear insertRow() debes tener en cuanta un montón de cosas, tal como lo explica la descripción de XFormOperations.

Pongamos un ejemplo: el formulario está en posición para insertar un nuevo registro, sólo has ingresado algunos datos en algunos campos, si aplicas insertRow() antes de filtrar el formulario para que no se pierdan esos datos nuevos pueden pasar dos cosas no deseadas:

* guardar un registro donde NO todos los campos han sido llenados
* producir un ERROR si algún campo no llenado es un campo obligatorio (p.e. una llave primaria) o si viola la integridad referencial de la base de datos.


Por esto, lo más seguro es emplear XFormOperations.

Si quisieras emplear los métodos antiguos deberías hacer algo así:


        oForm = oEvent.Source.Model.Parent
        'esto para no perder los datos ingresados en un registro existente
        If oForm.AllowUpdates AND oForm.IsModified AND NOT oForm.IsNew Then
                oForm.updateRow()
        'esto para no perder los datos en un registro nuevo
        ElseIf oForm.IsNew Then
'acá hacer un MONTÓN de trabajo: chequear cada control del formulario, ver si su contenido ha sido enviado al formulario y/o a la base de datos, etc.....
        End If


Nuevamente te sugiero que leas la descripción de XFOrmOperations.

Una salida no muy elegante es mostrar un mensaje al usuario si IsNew=TRUE: como por ejemplo "Antes de filtrar el formulario mediante lo seleccionado en la lista, guarda los datos del registro actual o se perderán...etc..."


PS: El colistero Oscar Darío Perdiguero, manifestó un pequeño reclamo por incluir al grupo en CC en mis mensajes. Sólo seguiré tus instrucciones, por lo que, en esta oportunidad no enviaré este correo al grupo.

Te recomiendo que incluyas mi dirección en el "Para", o simplemente lo envíes a la lista de correo: yo recibo todos los mensajes de la lista.

Si esta consulta es indicada para la lista de usuarios, es algo debatible. Yo opino que sí: si bien son cuestiones de programación, el tema es general y a nivel de un usuario básico; para manejar OOo Base sacándole todo el jugo es necesario incluir algunas macros. No hay lista apropiada para este tipo de temas (pues dev@ es para temas de traducción -- o teóricamente para temas de "desarrollo", pero este tema no es de "desarrollo" sino de cómo emplear macros en un nivel básico y para las necesidades general de un usuario promedio, NO desarrollar algo profesionalmente).

Los motivos por los cuales sugiero (aunque casi siempre sin éxito) a todas personas que me consultan que envíen sus consultas directamente a la lista y no a mí solamente son:

* la respuesta puede ser útil para otros usuarios, no sólo ahora sino luego cuando busquen por internet o en el archivo de la lista (yo mismo, antes de enviar una consulta a alguna lista, antes busco en las bases de datos, y suelo encontrar la solución ahí, ahorrando tiempo a otras personas en leer un mensaje que ya ha sido solucionado antes)

* otros usuarios pueden participar y colaborar aportando su punto de vista, e incluso una solución (pues no soy el amo de la verdad y puedo [suelo] estar equivocado)

* si la respuesta es pública, ahorro tiempo luego si alguien me consulta lo mismo: esta respuesta me ha llevado casi una hora (entre buscar las referencias, chequear el código, etc.), la próxima vez que alguien me consulte lo mismo, puedo directte. remitirlo a la base de datos de la lista.

* por último, cuando algún amante de la meritocracia esté interesado en saber qué hago, no necesito enviarle mi curriculum vitae o pedir a todos aquellos a quienes he ayudado desinteresadamente que le envíen sus mails


Saludos,
Ariel

[1] ya he prometido a varios usuarios actualizar la base de ejemplo... pero nunca me tomo el tiempo para hacerlo. Trataré de que no pase de esta semana ;-)

--
Ariel Constenla-Haile
La Plata, Argentina

[EMAIL PROTECTED]
[EMAIL PROTECTED]

http://www.arielconstenlahaile.com.ar/ooo/



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Responder a