Ce que je croyais intuitif

“Je modifie une cellule dans un contrôle de table, donc je devrais pouvoir savoir si cette cellule ou cette ligne est modifiée.”
.
LibreOffice et la gestion des macros en StarBasic n’est pas de tout repos.
.
Je tente d’intercepter la modification ou le changement de sélection d’une colonne liste déroulante d’un contrôle de table d’un sous-formulaire.
La colonne a un champ de données dont le contenu est une requête ou commande SQL. Je tente de me servir de l’événement ‘Statut de l’élément modifié’, mais LibreOffice ne le gère pas directement.
.
Voici mon constat :
.

| Élément                         | Ce qu’il est                | Ce qu’il expose                 | Ce qu’il ne fait pas
| Colonne de contrôle de table    | Liste déroulante            | Événements comme Statut modifié | Ne gère pas l’état réel de modification
| Contrôle de table               | Conteneur de colonnes       | Peut appeler updateRow()        | Ne possède pas isModified
| Sous-formulaire                 | Modèle de données           | Possède updateRow() et parfois isModified | Ne sait pas ce qui a changé dans une cellule
| Contrôle actif dans une cellule | Instance dynamique          | Peut déclencher des événements  | N’est pas accessible directement via le modèle |

.
Est-ce que quelqu’un peut m’expliquer comment fonctionne ce foutoir?

peut-etre pas intuitif, mais surtout illisible.

Vous avez parfaitement raison, ce n’est finalement pas très clair. Je vais tenter de dire cela autrement.
.
Pourquoi un objet comme une colonne d’un contrôle de table d’un sous-formulaire pouvant être associé à divers type comme une zone de texte, une liste déroulante, etc. possède un événement qui peut être intercepté par une macro via une propriété ‘Statut de l’élément modifié’ et que cet évènement (oEvent) ne possède pas la méthode ‘objet modifié’ ou ‘isModified’.
.
Pour être un peu plus clair :
.
oControlModel = oEvent.Source.Model (c’est la colonne comme objet)
oControlModel.Name = ‘lst-SiteInfo’ qui est le nom de la colonne du contrôle de table.
.
J’ai choisi l’événement ‘Statur Modifié’ pour cet objet et associé à une procédure MoveValidation.
.
Aucune méthode dans oControlModel ne suggère qu’il soit possible de vérifier si le statut est vraiment modifié comme un changement de sélection dans la colonne.
.
C’est complètement illogique. Pourquoi une colonne de type liste déroulante, possède un événement ‘Statut de l’élément modifé’ mais qu’aucune méthode existe pour vérifier la modification du contenu de cet objet.
.
oTableControl = oControlModel.Parent : il ne possède pas non plus aucune méthode pouvant indiquer une modification.
.
oSubFormModel = oTableControl.Parent : cet objet possède la méthode ‘IsModified’, mais ne semble pas tenir compte du tout du fait qu’il y ait eu un changement de sélection dans la colonne liste déroulante.
.
Pourquoi uns colonne (liste déroulante dans la situation présente) d’un contrôle de table possède un événement (Statut de l’élément modifié) dont on ne peut pas vérifier via une macro qu’il y a effectivement eu une modication de valeur dans liste déroulante?

Sub MoveValidation(oEvent)
    Dim oControlModel As Object, oSubFormModel As Object, oTableControl As Object
    Dim oControlURL As Object, oFormController As Object
    
    oControlModel = oEvent.Source.Model
    oTableControl = oControlModel.Parent	    ' Remonter jusqu'au contrôle de table
    oSubFormModel = oTableControl.Parent	' Remonter jusqu'au sous-formulaire

    ' Vérifier si le sous-formulaire est modifié
    If HasUnoMethod(oSubFormModel, "isModified") Then
        If oSubFormModel.isModified Then
            oSubFormModel.updateRow()
        End If
    End If

    oFormController = ThisComponent.CurrentController	    ' Déplacer le focus vers le champ URL
    oControlURL = oFormController.getControl("txt-URL") ' Nom exact du champ dans le formulaire
    oControlURL.setFocus()
End Sub
1 Like

toujours pas lisible, mais au moins c’est formel :wink:

un .odb d’exemple (et un sujet explicite) aideraient surement les qq gurus de base à creuser le sujet.
et probablement plutot coté anglophone. → Topics tagged base

1 Like

Merci! je vais voir si je donne suite à tout cela. C’est toujours pas lisible en français, alors qu’en sera-t-il en anglais…

Bonne journée fpy!

Comme ça ?

Option Explicit
Sub EstrelasAtualizada(evt As Object)
	print "Ok!"	
End Sub


1 Like

Vous avez raison, si on utilise l’événement ‘After Updating’, mais pas avec l’événement ‘Item Status Modified’. De plus, c’est le sous-formulaire qui indique cette modification avec ‘IsModified’.
.


.
Ce que je comprends, c’est que l’événement ‘Item Statis Modified’ qui semble de prime à bord celui qui pourrait indiquer la modification de par son nom, n’est pas forcément le bon à utiliser. C’est plutôt trompeur, car je croyais avoir modifié l’état de la liste déroulante en sélectionnant un item différent dans la liste.
.

.
La sélection ne fait rien, il est nécessaire d’actualiser le sous-formulaire.
.
Je ne comprends pas toujours bien la logique, mais tout de même, merci de m’avoir indiqué le bon événement à utiliser.

Mais c’est aussi déclenché (?)

Sub ISC(evt As Object)
	Dim LBHoteis As Object
	Dim info As String, displayed As String
	LBHoteis = evt.Source.Model
	info = """Item status changed"" fired" & Chr(10)
	info = info & LBHoteis.currentValue & " <-- bound value" & Chr(10)
	info = info & LBHoteis.StringItemList(LBHoteis.SelectedItems(0)) & " <-- displayed"
	MsgBox info
End Sub


@CRDF, vous avez partiellement raison, je remarque que votre liste déroulante n’est pas une zone de liste d’un contrôle de table.
.


.
Comme vous voyez dans cette image, “Asian Wiki” est une sélection de la colonne 'lst-SiteInfo" du contrôle de table “cntr-SitesInfos” du sous-formulaire “sfrm-SitesInfosURL”.
.

.
L’événement choisi pour appeler la procédure 'TestItemStatusChanged" est “Statut de l’événement modifié”.
.
Voici la procédure de test :

Sub TestItemStatusChanged(oEvent As Object)
    Dim oListBox As Object, oControlTable As Object
    Dim oSubForm As Object

    oListBox = oEvent.Source.Model
    oControlTable = oListBox.Parent
    oSubForm = oControlTable.Parent

    ' Vérification par appel sécurisé
    If HasMethod(oListBox, "IsModified") Then
        MsgBox "oListBox a la méthode IsModified"
    Else
        MsgBox "oListBox n'a pas la méthode IsModified"
    End If

    If HasMethod(oControlTable, "IsModified") Then
        MsgBox "oControlTable a la méthode IsModified"
    Else
        MsgBox "oControlTable n'a pas la méthode IsModified"
    End If

    If HasMethod(oSubForm, "IsModified") Then
        MsgBox "oSubForm a la méthode IsModified"
    Else
        MsgBox "oSubForm n'a pas la méthode IsModified"
    End If
End Sub

.

Function HasMethod(oObj As Object, sMethodName As String) As Boolean
    Dim bResult As Boolean

    On Error GoTo ErrHandler
    
    ' Tentative d'appel de la méthode
    Select Case sMethodName
        Case "IsModified"
            bResult = oObj.IsModified
        ' Tu peux ajouter d'autres méthodes ici si besoin
        Case Else
            bResult = False
    End Select

    HasMethod = True
    Exit Function

ErrHandler:
    HasMethod = False
End Function

.
Les résultats obtenus sont les suivants :
Capture d’écran 2025-08-10 223221
.
Capture d’écran 2025-08-10 223236
.
Capture d’écran 2025-08-10 223253
.
oSubForm a bien la méthode ‘IsModified’, mais sa valeur est sur False tant que l’utilisateur n’a pas cliqué ailleurs, dans la colonne URL ou un champ du formulaire principal.
.
Le problème est que parfois malgré la sélection faite dans la colonne “Site Informatif”, LibreOfiice n’autorise pas un changement de champ. J’ai beau cliqué dans la colonne URL, aucun curseur devient actif. Je clique ailleurs dans le formulaire principal, rien n’y fait ‘IsModified’ demeure à la valeur False. Cela ne survient pas toujours, mais occasionnellement.
.
C’est cela que je ne comprends pas.