我的ActiveX ComboBox更改尺寸

23 浏览
0 Comments

我的ActiveX ComboBox更改尺寸

这篇帖子讨论了我在Excel电子表格中使用ActiveX对象时遇到的问题。这个帖子很难阅读,并且最终没有得到一个连贯的答案。问题是可以100%复现的:\n

    \n

  1. 在使用坞站的情况下打开带有ActiveX对象的工作簿
  2. \n

  3. 从坞站断开机器,触发分辨率的更改(还有其他原因,我是因为使用了坞站,似乎改变分辨率会导致这个问题)
  4. \n

  5. 点击一个ActiveX控件-它们立即重新调整大小,字体也会改变大小。字体大小的变化不是由.Font.Size参数控制的,而是在问题发生后无法改变的,除非不断增加字体大小
  6. \n

\n唯一看起来权威的解决方案涉及到一个微软的补丁(几年前是一个“热修复”),以及注册表编辑,这对我的使用情况来说不实际。\n我正在寻找以下解决方案之一:\n

    \n

  1. 防止这种变化发生
  2. \n

  3. 找到最佳解决方法
  4. \n

\n关于这个问题的权威信息在网上缺乏。我打算发布我的解决方案,但它离理想解决方案还有很大差距,我更希望能有一个更好的解决方案。

0
0 Comments

这个问题的出现原因是当Excel出现问题时,活动控件的尺寸会发生变化。为了解决这个问题,需要将控件的设置存储在工作簿中的一个工作表上,以保留它们的设置。

解决方法是创建一个名为setControlsOnSheet()的子程序,该子程序可以获取活动工作表上每个OLEObject(活动控件)控件的6个常见控件设置,并将这些设置存储到一个字符串数组sControlSettings()中。然后,将这些设置添加/更新到一个隐藏的定义名称中。每个工作表上的控件的定义名称是根据活动工作表名称和控件名称构建的,以创建一个唯一的实例。

使用过程如下:用户在工作表上创建需要的控件,然后可以随时运行setControlsOnSheet()子程序,以初始化所有控件的设置、刷新这些设置,或者添加新的设置。需要注意确保所有设置看起来正确(例如,Excel尚未出现问题,或者用户刚刚调整了他的控件之一并准备“保存”其设置)。否则,会存储任何尺寸不正确的控件设置。

为了避免使这个子程序变得过程密集,可以在工作表激活时使用ThisWorkbook事件来“重新初始化”刚刚选择的工作表上存在的所有控件的所有设置。这样,工作表上的控件设置将被“恢复”到最近保存的设置,从而“永远?”避免Excel的“怪异”调整尺寸的后果。

作为潜在的改进,这个应用程序可以嵌入到一个类模块中作为一个附加组件的一部分,从而将任何相关的代码保持在用户的“正常”编程环境之外。例如,工作表激活事件的捕获将被捕获在类模块中,而不是用户必须将其添加到他/她的ThisWorkbook模块中。

以下是用于刷新控件设置的refreshControlsOnSheet()函数和用于存储控件设置的storeControlSettings()子程序的代码示例。

Const CONTROL_OPTIONS = "Height;Left;Locked;Placement;Top;Width" '一些可能有用的设置进行存储和保持
Function refreshControlsOnSheet(sh As Object)
    Dim myControl As OLEObject
    Dim sBuildControlName As String
    Dim sControlSettings As Variant
    For Each myControl In ActiveSheet.OLEObjects
        sBuildControlName = "_" & myControl.Name & "_Range" '基于控件名称构建一个范围名称
        '测试之前保存的设置是否存在
        On Error Resume Next
        sControlSettings = Evaluate(sBuildControlName) '加载设置的数组
        If Err.Number = 0 Then '该控件的设置已经存储,所以刷新控件的设置
            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 '设置要存储的控件设置的数量
    Dim oControl As Variant
    Set oControl = ActiveSheet.OLEObjects(sControl)
    '存储要保留的设置,以便可以根据需要重置,从而避免Excel的调整尺寸问题
    '创建要存储的设置的数组,其顺序由CONTROL_OPTIONS指定,以保持一致性和文档化
    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" '基于控件名称构建一个范围名称
    Application.Names.Add Name:="'" & ActiveSheet.Name & "'!" & sBuildControlName, RefersTo:=sControlSettings, Visible:=False '将控件的设置添加到定义名称区域并隐藏范围名称
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
            storeControlSettings (myControl.Name)
        Next myControl
        MsgBox "Settings have have been stored", vbOKOnly
    End If
    Application.EnableEvents = True
End Sub

0
0 Comments

原因:在使用ActiveX ComboBox时,ComboBox会改变其尺寸,导致问题出现。

解决方法:目前唯一可靠的解决方法是关闭并重新启动Excel,包括任何不可见的实例。其他解决方法都存在一些问题。为了重新启动Excel(包括任何不可见的实例),可以使用命令taskkill /f /im excel.exe通过命令提示符(cmd)执行该命令。

参考链接:点击这里查看示例。

0
0 Comments

问题原因:ActiveX ComboBox在使用过程中会发生尺寸变化的问题。

解决方法:通过编程迭代工作表上的所有OLE对象,并编写调试器代码,然后在工作表上包含一个“调整对象尺寸”的按钮,并说明为什么会出现这个问题。这种方法将生成驱动该按钮的代码。但它不会自动更新,它只应在部署应用程序之前使用(如果最终用户将拥有按钮功能)。然后,按照以下顺序进行操作:

1. 运行使用以下方法生成的代码。

2. 立即保存工作簿-这不会阻止字体变化继续发生。

3. 重新打开工作簿,问题就“解决”了。

以下是用于生成代码的私有子程序printAllActiveXSizeInformation()的代码:

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

注意:这种方法无法找到被分组的对象。看起来.Shapes也与.OLEObjects一样存在分组问题。

0