Как остановить объекты ActiveX, автоматически меняя размер в офисе?
В этом разделе обсуждается проблема, с которой я столкнулся с объектами ActiveX в электронной таблице Excel. Это беспорядок для чтения и в конечном итоге не имеет согласованного ответа.
Проблема на 100% воспроизводима:
- Открыть книгу с объектами ActiveX в электронной таблице при использовании док-станции
- Отключите машину от док-станции, вызвав изменение разрешения (есть и другие причины, мои с док-станцией, похоже, это приводит к изменению разрешения)
- Нажмите элемент управления ActiveX - они сразу изменяют размер, а шрифт изменяет размер. Изменение fontsize НЕ является функцией параметра
.Font.Size
, но что-то, что не может быть изменено после возникновения проблемы, кроме постоянного увеличения fontsize
Единственное, по-видимому, авторитетное решение включает в себя патч MS (это было "исправление" несколько лет назад, хотя, поэтому это не кажется практичным для полного развертывания) и изменения реестра, что нецелесообразно для моего использования.
Я также ищу способ:
- Предотвратить это изменение
- Найдите лучшую работу
Отсутствует авторитетная информация об этой проблеме в Интернете. Я намерен опубликовать свою работу, однако, он даже не близок к идеалу, и я бы предпочел лучшее решение.
Ответы
Ответ 1
Моя работа заключается в программном повторении всех объектов OLE на листе * и записи кода в отладчик, а затем включение кнопки в основном "изменение размеров объектов" на листе - с инструкциями о том, почему эта проблема возникает.
Этот метод генерирует код для управления этой кнопкой.
Однако он не будет автоматически обновляться - это снимок и должен использоваться только непосредственно перед развертыванием приложения (если конечные пользователи будут иметь функциональность кнопки).
Затем последовательность становится:
- Выполнить код, сгенерированный следующим способом.
- Немедленное сохранение рабочей книги - это НЕ предотвращает продолжения изменений шрифта
- Повторно открыть книгу и проблему "решена".
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
* note: это не будет искать объекты, которые тоже сгруппированы.
Ответ 2
Единственное 100% надежное решение - закрыть и перезагрузить Excel (включая любые невидимые экземпляры). У любого другого решения есть некоторые проблемы.
Это одна из причин, по которой я избегаю контроля, когда это возможно. См. здесь для примера.
Ответ 3
Этот модуль был создан dlmille of E-E 20 марта 2011 г.
Это упражнение по сохранению параметров управления active-x в рабочей книге на листе, сохраняя их настройки, если/когда Excel становится "изворотливым" и размерность формы искажается
В то время как ListBox имеет свойство IntegralHeight, чей побочный эффект FALSE-параметра будет держать этот элемент управления в заданном порядке, а в то время как командные кнопки
имеют такие свойства, как перемещение/размер с ячейками и т.д., другие элементы управления не так грациозны.
Подпрограмма setControlsOnSheet(): 1) получает 6 общих настроек управления для каждого элемента управления OLEObject (active-x) на активном листе и 2) сохраняет эти настройки в массив строк, sControlSettings() и 3) добавляет/обновляет определенное имя (которое скрыто) с этими настройками.
Определенное имя для каждого элемента управления на листе создается на основе имени активного листа и имени элемента управления (который должен создать уникальный экземпляр)
Процесс: Пользователь создает все элементы управления, находящиеся на рабочем листе, и в любой момент может быть запущена процедура setControlsOnSheet()
сначала сохраните настройки для всех элементов управления, обновите эти настройки или добавьте новые настройки (как это делается для каждого элемента управления на листе).
Следует соблюдать осторожность, чтобы все настройки "выглядели правильно" (например, Excel еще не получил "изворотливый", или пользователь только что настроил один на многие из
его элементы управления и готовы "сохранить" их настройки. В противном случае будут сохранены любые настройки элементов управления неправильного размера.
Вместо того, чтобы сделать этот обычный процесс интенсивным, событие ThisWorkbook для активации листа будет "повторно инициализировать" все настройки для всех элементов управления
которые существуют только на выбранном листе. Таким образом, параметры управления на листе "восстанавливаются" до последних сохраненных настроек,
таким образом "навсегда?" избегая Excel "quirky" изменение размера последствия.
В качестве потенциального улучшения это приложение может быть внедрено в модуле класса как часть надстройки, таким образом сохраняя любой связанный код из
пользователей "нормальной" среды программирования. Например, блокировка событий активации листа будет записана в модуле класса, а не пользователь, имеющий
чтобы добавить его в свой модуль 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 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 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
Ответ 4
Аналогичные проблемы существуют для комментариев и фигур. Одним из способов является создание макроса для записи свойств .Width и .Height, а также свойств позиции листа для каждого объекта на неиспользуемом листе. Затем напишите второй макрос, чтобы восстановить эти свойства по требованию.
Ответ 5
Это происходило со мной в прошлом (после или при использовании удаленного подключения к компьютеру), но я придумал решение изменить размеры команд и их шрифтов с помощью события Workbook_WindowActivate
(это можно сделать через кнопку "reset settings", как я полагаю).
Во всяком случае, я думал, что все было исправлено до сегодняшнего дня, когда я снова использовал удаленную связь, и два командных кнопки начали плохо себя вести. Я обнаружил, что эти 2 командных указателя имели свойство Placement, равное 2 (Object перемещается с ячейками), в то время как я установил его в 3 (Object - свободное плавание) для остальных в прошлом.
Но прежде чем найти это, я пытался установить размер шрифта кнопок на то, что я хотел (через окно свойств), но Windows игнорировала любое число, которое я использовал, до тех пор, пока я не изменил высоту кнопки... он внезапно прочитал свойство размера шрифта и соответствующим образом скорректировал его.
Я не уверен, что свойство размещения на самом деле является частью проблемы, но, чтобы быть уверенным, я использую 2 решения:
(1) для размещения установлено значение 3
(2) моя функция "автоматического изменения размера", которая запускается с событием Workbook_WindowActivate
, немного увеличивает размер кнопки и шрифта, прежде чем сводить их обратно к тому, что им нужно. Но, может быть, решение (1) было бы достаточно... У меня нет времени проверять прямо сейчас. Здесь код для моего события Workbook_Activate
:
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
Теперь все работает нормально. В прошлом мне приходилось искать решение в сети. Надеюсь, это поможет хотя бы одному человеку: -)
Ответ 6
У меня было несколько проблем с кнопками, размер шрифта которых был одним из них. У меня также были кнопки для изменения размеров, а картинки в них изменялись. Я мог бы программно изменить размер кнопки назад, но не смог найти способ изменить размер изображения таким образом. Думаю, я нашел, что может быть окончательным решением этих проблем.
Если я удалю файл MSForms.exd из (в моем случае) C:\Users {UserName}\AppData\Local\Temp\Excel8.0, когда вы находитесь в разрешении экрана, вы хотите просмотреть кнопки а затем перезапустите Excel, эти проблемы, похоже, исчезнут. Существуют и другие .exd файлы, которые могут понадобиться удалить для других приложений. Некоторые из них:
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
Ответ 7
Я думаю, что у @RuiHonori был лучший ответ, но для того, чтобы я мог контролировать свои листы на всех моих листах, где бы я хотел, чтобы они были - все они были одного размера - я использовал это:
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