VBA切换按钮在Visio中的引用

huangapple go评论68阅读模式
英文:

VBA Toggle Button referencing in Visio

问题

抱歉,您的请求已被理解。以下是翻译后的内容:

抱歉,可能是一个简单的问题,但...

我正在尝试在VBA中格式化一个切换按钮。我有60多个按钮,每个按钮都可以打开/关闭图层,我正在尝试整理这些代码。目前,格式化是在“单击”级别完成的,但这有很多重复。

Sub A2_Click()
    Dim LyrNum As Integer ' 图层编号
    Dim RiserName As String
    LyrNum = A2.Data1 ' 从Data1字段中获取
    RiserName = "A2"
    If A2 Then ' 按钮按下
        Call ToggleRiser(LyrNum, 1, RiserName) ' 调用带有图层编号和“On”的子过程
    Else
        Call ToggleRiser(LyrNum, 0, RiserName) ' 调用带有图层编号和“Off”的子过程
    End If
End Sub

然后,理想情况下调用:

Sub ToggleRiser(ItmNbr As Integer, OnOff As String, Riser As Object) ' 切换图层开关的子过程 - ItmBr是图层编号;Riser是切换按钮名称

    Dim vsoLayer1 As Visio.Layer ' 创建图层信息的变量
    Set vsoLayer1 = Application.ActiveDocument.Pages.ItemU("Filler Boxes, Half Risers and Bass Box Layers").Layers.Item(ItmNbr) ' 设置为特定的图层
    
    If OnOff Then ' 按钮按下
        Riser.BackColor = RGB(230, 180, 50) ' 更改背景为黄色
    Else
        Riser.BackColor = RGB(129, 133, 219) ' 深蓝色
    End If
    
    vsoLayer1.CellsC(visLayerVisible).FormulaU = OnOff
    vsoLayer1.CellsC(visLayerPrint).FormulaU = OnOff
End Sub

打开和关闭图层的操作正常工作,但是我在“Riser.BackColor”方面遗漏了一些内容,因为VBA没有将其识别为“A2.BackColor”。

不确定是否因为我需要将“Riser”评估为不同于字符串的东西而导致的?

提前感谢!
示例文件在这里:
https://www.dropbox.com/s/io1nwnkmhs0a28c/ToggleScriptExample.vsdm?dl=0

理想情况下,我想将按钮格式化移到ToggleLayer子过程中,或者总之找到更好的方法 - 再次数了一下,有80多个按钮!

英文:

Sorry, probably an simple question but...

I'm trying to format a toggle button in VBA. I've 60+ buttons, each turning on/off layers and I'm trying to tidy this up. At the moment the formatting is done at the "Click" level, but that's a lot of duplication

Sub A2_Click() 
    Dim LyrNum As Integer ' Layer Number
    Dim RiserName As String
        LyrNum = A2.Data1 ' Pulled for Data1 field
        RiserName = "A2"
    If A2 Then            ' Button down
        Call ToggleRiser(LyrNum, 1, RiserName) ' Call Sub with Layer Number and "On"
      Else
        Call ToggleRiser(LyrNum, 0, RiserName) ' Call Sub with Layer Number and Off
   End If
End Sub

Which ideally then calls:


Sub ToggleRiser(ItmNbr As Integer, OnOff As String, Riser As Object)  ' Sub to switch layers on and off - ItmBr is the Layer Number; Riser is the Toggle Button Name

    Dim vsoLayer1 As Visio.Layer            ' Create Variable for Layer Info
    Set vsoLayer1 = Application.ActiveDocument.Pages.ItemU("Filler Boxes, Half Risers and Bass Box Layers").Layers.Item(ItmNbr) ' Set to specific Layer called
    
      
    If OnOff Then            ' Button down
        Riser.BackColor = RGB(230, 180, 50) ' Change Background Yell
    Else
        Riser.BackColor = RGB(129, 133, 219) ' Dark Blue
    End If
    
    vsoLayer1.CellsC(visLayerVisible).FormulaU = OnOff                                                 ' 
    vsoLayer1.CellsC(visLayerPrint).FormulaU = OnOff                                                   ' 

Turning on and off the layers works fine, but I'm missing something with the "Riser.BackColor" as VBA isn't recognising this as "A2.BackColor"

Not sure if this is because I need to evaluate "Riser" as something different than a string?

Thanks in advance!

Example file is here:
https://www.dropbox.com/s/io1nwnkmhs0a28c/ToggleScriptExample.vsdm?dl=0

Ideally I want to move the button formatting into the ToggleLayer Sub, or just find a better way in general - Counted again and there's 80+ buttons!

答案1

得分: 1

I've translated the code for you:

*我在家里的电脑上没有Visio,所以无法检查示例文件或验证任何是否有效。*

正如OP所推测的,我们需要将Riser作为一个对象传递,而不是一个字符串。将调用更改为`Call ToggleRiser(LyrNum, 1, A2)`应该可以解决问题。然而,我们可以直接从Riser中提取所有需要的数据来简化代码:

Sub A2_Click()
Call ToggleRiser(A2) ' 使用Riser调用子程序
End Sub


Sub ToggleRiser(ByRef Riser As Object) ' 用于切换图层开关的子程序
Dim vsoLayer As Visio.Layer ' 创建图层信息的变量
Set vsoLayer = ActiveDocument.Pages("Filler Boxes, Half Risers and Bass Box Layers").Layers(Riser.Data1)

' 切换图层
vsoLayer.CellsC(visLayerVisible).FormulaU = Riser.Value
vsoLayer.CellsC(visLayerPrint).FormulaU = Riser.Value

' 着色Riser
If Riser.Value Then  ' 按钮按下
    Riser.BackColor = RGB(230, 180, 50)
Else
    Riser.BackColor = RGB(129, 133, 219)
End If

End Sub


--------------------------
尽管如此,我们可以通过使用一个[包装器类][1]来更好地处理**所有**的Risers,而不浪费硬编码的点击事件。

首先,创建一个类,我将其称为`RiserWrapper`。这个类具有一个通用的事件启用ToggleButton,我们可以将一个Riser传递给它,以捕获所有的点击事件。

Public WithEvents mRiser as MSForms.ToggleButton ' 传递的Riser已启用事件

Private Sub mRiser_Click()
'''点击事件以切换所需的图层并设置Riser颜色
Dim vsoLayer as Visio.Layer
Set vsoLayer = ActiveDocument.Pages("Filler Boxes, Half Risers and Bass Box Layers").Layers(mRiser.Data1)

' 切换图层
vsoLayer.CellsC(visLayerVisible).FormulaU = mRiser.Value
vsoLayer.CellsC(visLayerPrint).FormulaU = mRiser.Value

' 着色Riser
If mRiser.Value Then
    mRiser.BackColor = RGB(230, 180, 50)
Else
    mRiser.BackColor = RGB(129, 133, 219)
End If

End Sub


接下来,我们将Risers包装起来并将它们存储在一个集合中。在`ThisDocument`中:

Private Risers as Collection ' 用于保存启用事件的Risers的集合(必须放在模块的顶部)

Private Sub Document_RunModeEntered(ByVal doc As IVDocument)
'''初始化绘图
Dim ctl as OLEObject ' 文档上的一个对象,直接访问使用.Object
Set Risers = New Collection

' 循环遍历文档中的控件对象以查找按钮
For Each ctl in doc.OLEObjects
    ' 通过TypeName筛选,启用所有CommandButtons的Click事件
    If TypeName(ctl.Object) = "ToggleButton" Then Risers.Add NewRiser(ctl.Object)
Next

End Sub

Private Function NewRiser(ByRef Riser as Object) as RiserWrapper
'''包装给定的Riser并返回包装后的对象
Set NewRiser = New RiserWrapper ' 创建包装器实例
Set NewRiser.mRiser = Riser ' 包装Riser
End Function


至此完成!
  [1]: https://codekabinett.com/rdumps.php?Lang=2&targetDoc=vba-handling-events-indefinite-sources

Please note that I've provided the translation as requested, but code translation may sometimes require additional context and adaptation to the specific programming environment.

英文:

I don't have Visio on my home computer, so I can't check the example file or verify that any of this actually works.

As OP speculated, we need to pass the Riser as an Object instead of a string. Changing the call to Call ToggleRiser(LyrNum, 1, A2) should do the trick. However, we can extract all the data we need directly from the Riser to simplify the code:

Sub A2_Click() 
   Call ToggleRiser(A2)  ' Call Sub with Riser
End Sub
Sub ToggleRiser(ByRef Riser As Object)  ' Sub to switch layers on and off
    Dim vsoLayer As Visio.Layer            ' Create Variable for Layer Info
    Set vsoLayer = ActiveDocument.Pages("Filler Boxes, Half Risers and Bass Box Layers").Layers(Riser.Data1)
    
    'Toggle Layer
    vsoLayer.CellsC(visLayerVisible).FormulaU = Riser.Value                                                 
    vsoLayer.CellsC(visLayerPrint).FormulaU = Riser.Value

    'Color Riser
    If Riser.Value Then                     ' Button down
        Riser.BackColor = RGB(230, 180, 50)  
    Else
        Riser.BackColor = RGB(129, 133, 219)
    End If
End Sub

That said, we can do better by using a Wrapper Class to handle all of the Risers without wasting space on hard-coded Click events.

First, create a class, which I'll call RiserWrapper. This has a generic event-enabled ToggleButton that we can pass a Riser to which will catch all the click events.

Public WithEvents mRiser as MSForms.ToggleButton 'The passed Riser is event-enabled

Private Sub mRiser_Click()
'''The click event to toggle the desired layer and set the Riser color
    Dim vsoLayer as Visio.Layer
    Set vsoLayer = ActiveDocument.Pages("Filler Boxes, Half Risers and Bass Box Layers").Layers(mRiser.Data1)

    'Toggle the Layer
    vsoLayer.CellsC(visLayerVisible).FormulaU = mRiser.Value
    vsoLayer.CellsC(visLayerPrint).FormulaU = mRiser.Value

    'Color Riser
    If mRiser.Value Then
        mRiser.BackColor = RGB(230, 180, 50)  
    Else
        mRiser.BackColor = RGB(129, 133, 219)
    End If
End Sub

Next, we wrap the Risers and store them in a Collection. In ThisDocument:

Private Risers as Collection         'Collection to hold event-enabled Risers (must go at the top of the module)

Private Sub Document_RunModeEntered(ByVal doc As IVDocument)
'''Initialize drawing
    Dim ctl as OLEObject           'An Object on the drawing, access directly with .Object
    Set Risers = New Collection

    'Loop through the Control objects in the document to find the buttons
    For Each ctl in doc.OLEObjects
        'Filter by TypeName, enabling Click events for all CommandButtons
        If TypeName(ctl.Object) = "ToggleButton" Then Risers.Add NewRiser(ctl.Object)
    Next
End Sub

Private Function NewRiser(ByRef Riser as Object) as RiserWrapper
'''Wraps a given Riser and returns the wrapped object
    Set NewRiser = New RiserWrapper                     'Create wrapper instance
    Set NewRiser.mRiser = Riser                         'Wrap the Riser
End Function

And we're done!

huangapple
  • 本文由 发表于 2023年4月13日 21:10:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76005841.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定