Ceci est une page optimisée pour les mobiles. Cliquez sur ce texte pour afficher la vraie page.

XL 2016 VBA Challenge - Positionner un UserForm sur Objet feuille dans une feuille fractionnée

Dudu2

XLDnaute Barbatruc
Bonjour,

Positionner un UserForm sur une cellule, une TextBox ou un autre objet d'une feuille ça se fait assez facilement.

Par contre positionner le même UserForm sur cet objet quand la feuille est fractionnée, je n'y arrive pas directement.
La seule solution que j'ai pu trouver est de supprimer temporairement le fractionnement. Mais ce n'est pas très "élégant". De plus cela génère un léger mouvement d'écran induit par la suppression temporaire du fractionnement.

Le "challenge" en question consiste donc à trouver la position (Top et Left) de l'objet feuille dans la feuille fractionnée sans recourir à cet artifice de manière à positionner correctement le UserForm.

Ci-joint le fichier qui fait ça en utilisant l'artifice de suppression temporaire du fractionnement.
Si il y a une solution qui se passe de cet artifice, je préfèrerais.
Merci par avance.

Voir solution (spécifique) en Post #31 (pour positionner un UserForm sur un Objet d'une feuille).
Voir solution (générale) en Post #72 (pour positionner un Objet sur un autre Objet).
 
Dernière édition:

patricktoulon

XLDnaute Barbatruc
@Dudu2 c'est la seule chose qui n'est pas accessible il faut que la pane soit activée
@Dranreb

ben pourtant il faudrait si tant est que cela soit possible de designer une pane sans quelle soit active
tout du moins par l'identification du bouton cliqué
j'ai tester monbouton.topleftcell.select pour activer la pane et avant de lancer le positionnement mais ça ne marche pas
je ne pense pas que ca soit accessible sauf en dur decidé

peut etre avec getcrsorpos et comparaison avec range width en pixel de pane 1+/-les scrolls et comparaison avec la position du curseur lors du click sur le bouton
si x cursor >et y< c'est pane2
si x > et y> c'est pane4
si < et y> alors pane 3
si < et < alors pane 1

c'est la seule solution que je vois
je vais voir ça plus tard là je dois partir Dentiste
 
Dernière édition:

Dranreb

XLDnaute Barbatruc
À mon avis c'est suffisant pour mon calendrier s'il cherche déjà dans les autres Pane seulement si la plage n'est pas visible dans celui actif. Mais si c'est indispensable dans votre cas ça doit pouvoir s'ajouter.
Voir si explorer la boucle à l'envers arrangerait les choses
For P = Wnw.Panes.Count To 1 Step -1
 

Dudu2

XLDnaute Barbatruc
Bon, c'est bien ça, il faut utiliser le Pane dans lequel se trouve l'objet cible. Comme dans le code de @Danreb.
Par contre je ne sais pas (encore) comment déterminer si l'objet est dans le VisibleRange du Pane.
Si l'objet est un Range, Intersect() fait l'affaire. Si c'est autre chose (ex. TextBox) faut trouver un autre moyen.
 

Dranreb

XLDnaute Barbatruc
VB:
If Not Intersect(Pan.VisibleRange, Obj) Is Nothing Then
Si c'est un contrôle ActiveX je suppose que ça entre dans le cadre du 1er cas If TypeOf Obj Is MSForms.Control
Si c'est un Shape on doit bien pouvoir au moins utiliser ses TopLeftCell et RightBottomCell
 

Dudu2

XLDnaute Barbatruc
En effet, pour les Shapes, TopLeftCell (et éventuellement RightBottomCell) font l'affaire.
Pour un ActiveX en feuille, c'est incompatibilité de type dans l'Intersect évidemment.
Pour être général, il va falloir localiser le Top Left de l'objet dans les Panes.
 

Dranreb

XLDnaute Barbatruc
Non mais je parlais d'utiliser l'autre séquence, complètement différente, où il n'y a pas d'Intersect
Pas sûr que ça marche par contre. Plutôt voir si on peut isoler et utiliser le Shape qui le porte.
 

Dudu2

XLDnaute Barbatruc
Sinon, une petite recherche du Top Left de l'objet qui s'applique à tous les types d'objets...
VB:
Sub a()
    Dim Obj As Object
    Dim Pan As Pane
    Dim i As Integer

    Set Obj = ActiveSheet.TextBox1

    For i = 1 To ActiveWindow.Panes.Count
        Set Pan = ActiveWindow.Panes(i)
        If Obj.Left >= Pan.VisibleRange.Cells(1, 1).Left _
        And Obj.Left <= Pan.VisibleRange.Cells(1, Pan.VisibleRange.Columns.Count).Left _
        And Obj.Top >= Pan.VisibleRange.Cells(1, 1).Top
        And Obj.Top <= Pan.VisibleRange.Cells(Pan.VisibleRange.Rows.Count, 1).Top Then Exit For
    Next i

    If i <= ActiveWindow.Panes.Count Then MsgBox "Objet est dans le Range visible du Pane " & i
End Sub

Peut-être ajouter la largeur et la hauteur de l'objet et des des limites du VisibleRange pour être plus tolérant ?
Dans ce cas le test est:
Code:
        If Obj.Left >= Pan.VisibleRange.Cells(1, 1).Left _
        And Obj.Left + Obj.Width <= Pan.VisibleRange.Cells(1, Pan.VisibleRange.Columns.Count).Left _
                      + Pan.VisibleRange.Cells(1, Pan.VisibleRange.Columns.Count).Width _
        And Obj.Top + Obj.Height >= Pan.VisibleRange.Cells(1, 1).Top _
        And Obj.Top <= Pan.VisibleRange.Cells(Pan.VisibleRange.Rows.Count, 1).Top _
                     + Pan.VisibleRange.Cells(Pan.VisibleRange.Rows.Count, 1).Height Then Exit For
 
Dernière édition:

Dudu2

XLDnaute Barbatruc
Voilà, fort de ces conclusions, j'ai republié le code et le fichier en Post #31.
Maintenant, faut que j'y intègre la position par rapport à l'objet ActiveWindow à des objets de UserForm comme vous l'avez fait avant moi.

Dans un UserForm, le Parent de l'objet qui sert de référence absolue au positionnement relatif de l'objet peut être ça ? (pris dans vos codes)
- le UserForm
- un MSForms.Page d'un objet MSForms.MultiPage
- un MSForms.Frame

@Danreb, dans le code je vois des calculs savants impliquant des constantes (0.9, -0.9, +6, -6).
Je vais lire tes commentaires pour comprendre
 

Dranreb

XLDnaute Barbatruc
Oh, ce ne sont que des règles de positionnement pour que ce ne soit pas complètement collé, d'une convention pour faire coincider les bords supérieurs etc., ça ne fait plus partie du calcul de repérage de l'emplacement.
 

Dudu2

XLDnaute Barbatruc
Du positionnement d'un UserForm sur un Objet de la feuille, je suis passé au positionnement d'un Objet sur un autre Objet (dans la mesure où cela fait sens évidemment).

Quelques petites difficultés à trouver les positionnements, par exemple pour le Page / MultiPage dont les marges se calculent en combinant les propriétés de ces 2 Objets.

Edit: 16h52 - Petite correction de commentaire.
 

Pièces jointes

  • VBA Positionner un Objet sur un Objet.xlsm
    74.5 KB · Affichages: 20
Dernière édition:

Dudu2

XLDnaute Barbatruc
Bonjour @patricktoulon,
Je parle des marges des Parents des Controls.
1 - Les marges gauche et haute du UserForm (j'ai enfin compris comment les calculer).
2.1 - Les marges gauche et haute d'un Frame
2.2 - les marges gauche et haute d'une Page / Multipage
Ces marges sont à ajouter pour trouver la position du Control en coordonnées absolues dans la fenêtre

Exemple: Position Left absolue en Points d'un Control en Frame d'un UserForm:
Left du UserForm +
Marge gauche UserForm +
Left Frame +
Marge gauche du Frame +
Left du Control
 

Dudu2

XLDnaute Barbatruc
D'ailleurs je viens de modifier le fichier (à reprendre) pour identifier spécifiquement les bordures gauche et haute du UserForm en variables dédiées pour plus de clarté.
 

Discussions similaires

Les cookies sont requis pour utiliser ce site. Vous devez les accepter pour continuer à utiliser le site. En savoir plus…