web-dev-qa-db-fra.com

Comment arrêter automatiquement la taille des objets ActiveX dans le bureau?

Ce fil discute d'un problème que j'ai rencontré avec des objets ActiveX dans une feuille de calcul Excel. C'est un gâchis à lire et n'a finalement pas de réponse cohérente.

Le problème est 100% reproductible:

  1. Ouvrir un classeur avec des objets ActiveX dans une feuille de calcul lors de l'utilisation d'une station d'accueil
  2. Déconnectez la machine de la station d'accueil, déclenchant un changement de résolution (il y a aussi d'autres causes, la mienne est avec une station d'accueil, il semble que changer la résolution en soit la cause)
  3. Cliquez sur un contrôle ActiveX - ils redimensionnent immédiatement et la police change de taille. Le changement de taille de police N'EST PAS une fonction du .Font.Size paramètre mais quelque chose qui ne peut pas être changé après que le problème se soit produit, autre que l'augmentation continue de la taille de police

La seule solution qui fait autorité semble impliquer un correctif MS (c'était un "correctif" il y a plusieurs années, cependant, donc cela ne semble pas pratique pour un déploiement complet) et des modifications de registre, ce qui n'est pas pratique pour mon cas d'utilisation.

Je cherche un moyen:

  1. Empêcher ce changement de se produire
  2. Trouvez le meilleur travail autour

Il y a un manque d'informations faisant autorité sur ce problème en ligne. J'ai l'intention de publier mon travail, cependant, il n'est même pas proche de l'idéal et je préférerais de loin une meilleure solution.

14
enderland

Mon travail consiste à parcourir par programme tous les OLE objets sur la feuille * et à écrire du code dans le débogueur, puis à inclure un bouton essentiellement "redimensionner les objets" sur la feuille - avec des instructions sur la raison de ce problème se produit.

Cette méthode générera le code pour piloter ce bouton.

Cependant, il ne sera pas mis à jour automatiquement - il s'agit d'un instantané et devrait niquement être utilisé immédiatement avant le déploiement d'une application (si les utilisateurs finaux auront la fonctionnalité du bouton).

La séquence devient alors:

  1. Exécutez le code généré avec la méthode suivante
  2. Enregistrer le classeur immédiatement - cela n'empêche pas les modifications de police de continuer à se produire
  3. Rouvrir le classeur et le problème est "résolu"

Private Sub printAllActiveXSizeInformation()
    Dim myWS As Worksheet
    Dim OLEobj As OLEObject
    Dim obName As String
    Dim shName As String

    'you could easily set a for/each loop for all worksheets
    Set myWS = Sheet1

    shName = myWS.name

    Dim mFile As String
    mFile = "C:\Users\you\Desktop\ActiveXInfo.txt"


    Open mFile For Output As #1
    With myWS
        For Each OLEobj In myWS.OLEObjects
            obName = OLEobj.name

            Print #1, "'" + obName
            Print #1, shName + "." + obName + ".Left=" + CStr(OLEobj.Left)
            Print #1, shName + "." + obName + ".Width=" + CStr(OLEobj.Width)
            Print #1, shName + "." + obName + ".Height=" + CStr(OLEobj.Height)
            Print #1, shName + "." + obName + ".Top=" + CStr(OLEobj.Top)
            Print #1, "ActiveSheet.Shapes(""" + obName + """).ScaleHeight 1.25, msoFalse, msoScaleFromTopLeft"
            Print #1, "ActiveSheet.Shapes(""" + obName + """).ScaleHeight 0.8, msoFalse, msoScaleFromTopLeft"

        Next OLEobj
    End With

    Close #1

    Shell "NotePad " + mFile



End Sub

* remarque: cela ne trouvera pas non plus les objets qui sont regroupés.

2
enderland

Ce module a été créé par dlmille de E-E le 20 mars 2011

Il s'agit d'un exercice pour stocker les paramètres de contrôle Active-X dans un classeur, sur une base de feuille, en préservant leurs paramètres si/quand Excel devient "excentrique" et que les tailles de forme deviennent de travers tandis que le ListBox a une propriété IntegralHeight dont les effets secondaires d'un FALSE Ce paramètre empêchera ce contrôle de se déplacer de travers, et bien que les boutons de commande aient des propriétés telles que déplacer/dimensionner avec des cellules, etc., d'autres contrôles ne sont pas aussi gracieux.

La routine setControlsOnSheet (): 1) obtient les 6 paramètres de contrôle communs, pour chaque contrôle OLEObject (active-x) sur la feuille active, et 2) stocke ces paramètres dans un tableau de chaînes, sControlSettings () et 3) ajoute/met à jour un nom défini (qui est masqué) avec ces paramètres.

Le nom défini pour chaque contrôle sur une feuille est construit en fonction du nom de la feuille active et du nom du contrôle (qui doit créer une instance unique)

Processus: l'utilisateur crée tous les contrôles qui seront sur la feuille de calcul et à tout moment, la routine setControlsOnSheet () peut être exécutée, soit pour stocker initialement les paramètres de tous les contrôles, pour actualiser ces paramètres, soit pour ajouter de nouveaux paramètres (car cela le fait pour chaque contrôle de la feuille).

Il faut veiller à ce que tous les paramètres "paraissent corrects" (par exemple, Excel n'a pas encore été "décalé", ou l'utilisateur vient d'ajuster un à plusieurs de ses contrôles et est prêt à "enregistrer" leurs paramètres. Sinon, tout les paramètres des commandes mal dimensionnés seraient stockés.

Plutôt que de rendre ce processus de routine intensif, l'événement ThisWorkbook pour la feuille à activer "réinitialise" tous les paramètres de tous les contrôles qui existent sur la feuille qui vient d'être sélectionnée. De cette façon, les paramètres de contrôle sur la feuille sont "restaurés" à leurs derniers paramètres enregistrés, donc "pour toujours?" éviter la conséquence de redimensionnement "excentrique" d'Excel.

Comme une amélioration potentielle, cette application pourrait être intégrée dans un module de classe dans le cadre d'un complément, gardant ainsi tout code associé hors de l'environnement de programmation "normal" des utilisateurs. Par exemple, la feuille activant le piégeage d'événements serait capturée dans le module de classe, plutôt que l'utilisateur ne doive l'ajouter à son module ThisWorkbook.

Const CONTROL_OPTIONS = "Height;Left;Locked;Placement;Top;Width" 'some potentially useful settings to store and sustain

Function refreshControlsOnSheet(sh As Object)'routine enumerates all objects on the worksheet (sh), determines which have stored settings, then refreshes those settings from storage (in the defined names arena)

Dim myControl As OLEObject
Dim sBuildControlName As String
Dim sControlSettings As Variant

For Each myControl In ActiveSheet.OLEObjects
    sBuildControlName = "_" & myControl.Name & "_Range" 'builds a range name based on the control name
    'test for existance of previously-saved settings
    On Error Resume Next
    sControlSettings = Evaluate(sBuildControlName) 'ActiveWorkbook.Names(sBuildControlName).RefersTo 'load the array of settings
    If Err.Number = 0 Then ' the settings for this control are in storage, so refresh settings for the control
        myControl.Height = sControlSettings(1)
        myControl.Left = sControlSettings(2)
        myControl.Locked = sControlSettings(3)
        myControl.Placement = sControlSettings(4)
        myControl.Top = sControlSettings(5)
        myControl.Width = sControlSettings(6)
    End If
    Err.Clear
    On Error GoTo 0
Next myControl      
End Function

Private Sub storeControlSettings(sControl As String)
Dim sBuildControlName As String
Dim sControlSettings(1 To 6) As Variant ' set to the number of control settings to be stored
Dim oControl As Variant

Set oControl = ActiveSheet.OLEObjects(sControl)

'store the settings to retain, so they can be reset on demand, thus avoiding Excel's resizing "problem"
'create array of settings to be stored, with order dictated by CONTROL_OPTIONS for consistency/documentation

sControlSettings(1) = oControl.Height
sControlSettings(2) = oControl.Left
sControlSettings(3) = oControl.Locked
sControlSettings(4) = oControl.Placement
sControlSettings(5) = oControl.Top
sControlSettings(6) = oControl.Width


sBuildControlName = "_" & sControl & "_Range" 'builds a range name based on the control name

Application.Names.Add Name:="'" & ActiveSheet.Name & "'!" & sBuildControlName, RefersTo:=sControlSettings, Visible:=False 'Adds the control's settings to the defined names area and hides the range name
End Sub


Public Sub setControlsOnSheet()
Dim myControl As OLEObject

If vbYes = MsgBox("If you click 'Yes' the settings for all controls on your active worksheet will be stored as they CURRENTLY exist. " & vbCrLf & vbCrLf _
                & "Are you sure you want to continue (any previous settings will be overwritten)?", vbYesNo, "Store Control Settings") Then

    For Each myControl In ActiveSheet.OLEObjects 'theoretically, one could manage settings for all controls of this type...
        storeControlSettings (myControl.Name)
    Next myControl

    MsgBox "Settings have have been stored", vbOKOnly
End If
Application.EnableEvents = True 'to ensure we're set to "fire" on worksheet changes
End Sub
1
Rui Honorio

La seule solution de contournement 100% fiable consiste à fermer et redémarrer Excel (y compris toutes les instances invisibles). Toute autre solution a un problème.

C'est l'une des raisons pour lesquelles j'évite les contrôles lorsque cela est possible. Voir ici pour un exemple.

1
stenci

Je pense que @RuiHonori avait la meilleure réponse, mais pour que je puisse placer mes commandes sur toutes mes feuilles là où je voulais qu'elles soient - qui étaient toutes de la même taille - j'ai utilisé ceci:

Sub SizeControls()
    Dim myControl As OLEObject
    Dim WS As Worksheet
    For Each WS In ThisWorkbook.Worksheets
        For Each myControl In WS.OLEObjects
            myControl.Height = 42.75
            myControl.Width = 96
        Next myControl
    Next WS
End Sub
0
Steven Good

Cela m'arrivait dans le passé (après ou pendant l'utilisation d'une connexion distante à mon PC), mais j'avais trouvé une solution pour redimensionner les boutons de commande et leurs polices en utilisant le Workbook_WindowActivate événement (cela pourrait aussi être fait via un bouton "réinitialiser les paramètres").

Quoi qu'il en soit, je pensais que tout était réglé jusqu'à aujourd'hui, lorsque j'ai utilisé à nouveau une connexion distante et que deux boutons de commande ont commencé à mal se comporter. J'ai découvert que ces 2 boutons de commande avaient la propriété Placement définie sur 2 (l'objet est déplacé avec les cellules) alors que je l'avais défini sur 3 (l'objet flotte librement) pour les autres dans le passé.

Mais avant de trouver cela, j'essayais de définir la taille de police des boutons à ce que je voulais (via la fenêtre des propriétés), mais Windows ignorait tout nombre que j'utilisais, jusqu'à ce que je change la hauteur du bouton ... tout d'un coup, il a lu la propriété de taille de police et l'a ajustée en conséquence.

Je ne sais pas si la propriété de placement fait réellement partie du problème, mais juste pour être sûr, j'utilise les 2 solutions:

(1) le placement est défini sur 3

(2) ma fonction de "redimensionnement automatique" qui se déclenche avec le Workbook_WindowActivate event augmente un peu la taille du bouton et de la police avant de les ramener à ce qu'ils devraient. Mais peut-être que la solution (1) serait suffisante ... Je n'ai pas le temps de tester pour le moment. Voici le code de mon Workbook_Activate un événement:

Worksheets(1).Shapes("CommandButton1").Top = 0
Worksheets(1).Shapes("CommandButton1").Left = 206.25
Worksheets(1).Shapes("CommandButton1").Width = 75
Worksheets(1).OLEObjects(1).Object.Font.Size = 10
Worksheets(1).Shapes("CommandButton1").Height = 21
Worksheets(1).Shapes("CommandButton1").Height = 18.75
Worksheets(1).OLEObjects(1).Object.Font.Size = 8

Maintenant, tout fonctionne bien. Cela m'a pris du temps dans le passé pour trouver une solution sur le net. J'espère que cela aidera au moins une personne là-bas ;-)

0
Xeliax

Des problèmes similaires existent pour les commentaires et les formes. Une solution consiste à écrire une macro pour enregistrer les propriétés . Width et . Height ainsi que les propriétés de position de feuille de chaque objet sur une feuille de calcul inutilisée. Ensuite, écrivez une deuxième macro pour rétablir ces propriétés à la demande.

0
Gary's Student

J'ai eu plusieurs problèmes avec les boutons, la taille de la police étant l'un d'entre eux. J'ai également redimensionné les boutons et redimensionné les images qu'ils contenaient. Je pouvais changer la taille du bouton par programmation, mais je ne pouvais pas trouver un moyen de changer la taille de l'image de cette façon. Je pense avoir trouvé la solution ultime à ces problèmes.

Si je supprime le fichier MSForms.exd de (dans mon cas) C:\Users {UserName}\AppData\Local\Temp\Excel8.0 pendant que vous êtes dans la résolution d'écran, vous souhaitez afficher les boutons, puis redémarrez Excel, ces problèmes semblent disparaître. Il existe d'autres fichiers .exd que vous devrez peut-être supprimer pour d'autres applications. Certains d'entre eux sont:

C:\Users\[user.name]\AppData\Local\Temp\Excel8.0\MSForms.exd

C:\Users\[user.name]\AppData\Local\Temp\VBE\MSForms.exd

C:\Users\[user.name]\AppData\Local\Temp\Word8.0\MSForms.exd

Il y en a aussi pour PowerPoint, mais je n'arrive pas à localiser le document de support connexe (qui n'appelle pas vraiment ces problèmes spécifiques pour autant que je m'en souvienne)

0
tbaker818