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:
.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 policeLa 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:
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.
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:
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.
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
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.
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
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 ;-)
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.
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)