Buenas!
Qué bueno que pierdas tu tiempo en estas cosas que a veces propongo y a las que pocas veces llego a buen puerto!
Te comento:
La idea es precisamente esa, localizar el control en el que está el foco y a partir de ahi, coger el número de fila del resultset que supone el formulario, el nombre del campo (o número de columna), y el texto (o número) del campo. Después, con estas condiciones, con el mismo filtro y mismo orden que el formulario, armar un SQL que nos dirá en qué puesto está el primer registro igual al que buscamos, determinando la fila en la que el SQL lo ha encontrado, y como el SQL es igual al ResultSet del formulario, con oForm.Absolute(), tendríamos el formulario en el primer registro deseado....
De todos modos el atasque es justo al principio, es decir, que no todos los controles tienen la propiedad 'hasfocus()', y la macro que comenté, en un principio hace un barrido por todos los formularios y sus controles, después por los subformularios y sus controles, etc.
El problema que tengo es que funciona solo para los que tienen la siguiente condición:
, y después para los que tienen esta otra:
.
El resultado es que cuando le dejas libremente recorrer todos los subformularios, la primera vez te localiza el control que tiene el foco (generalmente un control de texto), y parece que todo va sobre ruedas.
Cuando fijas el foco en otro subformulario (en un control con la propiedad 'hasfocus()') y lanzas la macro, entonces te reconoce el anterior que había marcado y el nuevo, y así sucesivamente al ir escogiendo otros subformularios.
En su día pregunté en el foro de Inglés si había manera de invalidar o poner a null el 'oFormController.CurrentControl' y me dijeron que no.
He intentado pararle los pies con exit for y exit function, pero los resultados no han sido los adecuados, ya que como paras el ciclo, cuando hay un subsubformulario, directamente no le dejas penetrar a investigar.
En definitiva, que estoy un tanto perdido!
Dejo aquí el código que he estado manejando para que os riais un poco de las burradas que hago.
Decir que estoy manejando libreOffice 5.4.7.2 en Windows 10, con HSQLDB 2.3 multiusuario, aunque creo que esto no tendría mayor importancia para que funcione o no el código propuesto.
También decir que la versión de LibreOffice es la última que no se me cuelga con esta base multiusuario, las demás (toda la saga de la versión 6) se cuelga al cargar el formulario de inicio, que entiendo que es algo completito, pero con esta versión no se cuelga y con las otras si (bueno, esto es otro tema para otra discusión!)
El código iría en un botón en un formulario, y considero que tendría que servir para cualquier formulario, por lo que se puede probar en cualquier base (no sé cómo lo admitiría Firebird, aunque en un principio no toca nada de SQL- de momento-)
Código: Seleccionar todo
Sub CheckFocusB
Dim oDoc as object
Dim fname as string
oDoc = ThisComponent.DrawPage.Forms ' Formularios de la base de datos
fname = FocusNameListRecB(oDoc) ' Llamada a la función
End Sub
Function FocusNameListRecB(oDoc as object) as string
DIM oForm as object, oController as object, oGridControlView as object, oGCMP as object
Dim fName as string
Dim i as integer, j as integer, n as integer
oController = ThisComponent.CurrentController ' Controlador
n = oDoc.Count ' Número de elementos del formulario
For i=0 to n-1 ' i = Contador
If oDoc.hasElements() then ' Si el documento (en un principio formulario) tiene elementos
oForm = oDoc.getByIndex(i) ' Elemento en el documento (primer ciclo serían formularios, después controles y subformularios, después controles en los subformularios y subformularios
Select case oForm.ServiceName ' Comprobamos de qué servicio se trata
Case "stardiv.one.form.component.Form" ' Si es un formulario
fName = FocusNameListRecB(oForm) ' Variable de la función, que iguala a la función
oFormController=thiscomponent.currentController.getFormController(oForm) ' Vista o controlador del oForm
if not IsNull (oFormController.CurrentControl) Then ' Si oFormController.CurrentControl no es nulo
Nombre= oFormController.CurrentControl.model.name ' Nombre del control
Control = oForm.getByName(Nombre) ' Vista del control
if oFormController.CurrentControl.hasfocus() Then ' Si el control actual tiene foco
If not Control.SupportsService("stardiv.one.form.component.CommandButton") Then ' Y no es un botón
NombreCampo = Control.Datafield ' Obtenemos el nombre del campo
msgbox Control.ServiceName & " "& NombreCampo & " Tiene foco" ' Aviso para ir viendo si se hacen las cosas bien
Exit For ' Nos echa del ciclo
Exit function ' Nos echa de la función
End if ' Acabamos la condición de que no sea un botón
Else ' En caso de no tener foco
If Control.ServiceName= "stardiv.one.form.component.Edit" Then ' Hay veces que a pesar de ser este tipo de servicio y le pones el cursor encima, no marca que tenga foco
NombreCampo = Control.Datafield ' Obtenemos el nombre del campo
msgbox Control.ServiceName & " "& NombreCampo & " Es un campo tipo .Edit sin foco" ' Aviso para ir viendo si se hacen las cosas bien
Exit For ' Nos echa del ciclo
Exit function ' Nos echa de la función
End if ' Acabamos la condición de que sea un Edit sin foco
' Se seguirá investigando una vez resuelto el tema del exit for y exit function
' if Control.ServiceName="stardiv.one.form.component.ComboBox" or Control.ServiceName="stardiv.one.form.component.ComboBox" Then
' NombreCampo = Control.Datafield ' The name of the field in the ResultSet
' msgbox Control.ServiceName & " "& NombreCampo & " No tiene foco"
' Exit for
' Exit function
' End if
' End if
' If Control.ServiceName="stardiv.one.form.component.Grid" Then
' msgbox "Control de tabla"
'NombreCampo = Control.Datafield
'msgbox Control.ServiceName & " "& ControlName & " No tiene foco"
' Exit for
' End if
' Exit function
' End if
End if
End if
End Select
End if
next
End function