How do I use variables to set properties in VBA (Excel)

前端 未结 3 971
轮回少年
轮回少年 2020-11-29 09:27

Take this code:

With ActiveSheet.Shapes.AddShape(msoShapeRectangle, x, y, w, h).TextFrame
  .Parent.Line.Visible = False
  .Parent.Fill.ForeColor.RGB = RGB(r         


        
相关标签:
3条回答
  • 2020-11-29 10:17

    Solution 1.

    Use CallByName.

    Option Explicit
    
    Private Type Callable
      o As Object
      p As String
    End Type
    
    Public Sub SetProperty(ByVal path As String, ByVal Value As Variant, Optional ByVal RootObject As Object = Nothing)
      With GetObjectFromPath(RootObject, path)
        If IsObject(Value) Then
          CallByName .o, .p, VbSet, Value
        Else
          CallByName .o, .p, VbLet, Value
        End If
      End With
    End Sub
    
    Public Function GetProperty(ByVal path As String, Optional ByVal RootObject As Object = Nothing) As Variant
      With GetObjectFromPath(RootObject, path)
        GetProperty = CallByName(.o, .p, VbGet)
      End With
    End Function
    
    Public Function GetPropertyAsObject(ByVal path As String, Optional ByVal RootObject As Object = Nothing) As Object
      With GetObjectFromPath(RootObject, path)
        Set GetPropertyAsObject = CallByName(.o, .p, VbGet)
      End With
    End Function
    
    
    Private Function GetObjectFromPath(ByVal RootObject As Object, ByVal path As String) As Callable
      'Returns the object that the last .property belongs to
      Dim s() As String
      Dim i As Long
    
      If RootObject Is Nothing Then Set RootObject = Application
    
      Set GetObjectFromPath.o = RootObject
    
      s = Split(path, ".")
    
      For i = LBound(s) To UBound(s) - 1
        If Len(s(i)) > 0 Then
          Set GetObjectFromPath.o = CallByName(GetObjectFromPath.o, s(i), VbGet)
        End If
      Next
    
      GetObjectFromPath.p = s(UBound(s))
    End Function
    

    Usage:

    ? getproperty("activecell.interior.color")
    16777215 
    
    SetProperty "activecell.interior.color", vbYellow
    'Sets yellow background
    
    ? getproperty("names.count", application.ActiveWorkbook)
    0 
    
    ? getproperty("names.count", GetPropertyAsObject("application.activeworkbook"))
    0
    

    Solution 2.

    Dynamically add code.
    Don't do this. It's wrong and it requires having that "Allow access to VB project" tick set.

    Add a reference to Microsoft Visual Basic for Applications Extensibility X.X.

    Create a module called ModuleForCrap.

    Add a dynamically constructed sub/function:

    ThisWorkbook.VBProject.VBComponents("ModuleForCrap").CodeModule.AddFromString _
    "function foobar() as long" & vbNewLine & _
    "foobar = 42" & vbNewLine & _
    "end function"`
    

    Call it:

    msgbox application.run("ModuleForCrap.foobar")
    

    Delete it:

    With ThisWorkbook.VBProject.VBComponents("ModuleForCrap").CodeModule
      .DeleteLines .ProcStartLine("foobar", vbext_pk_Proc), .ProcCountLines("foobar", vbext_pk_Proc)
    End With
    
    0 讨论(0)
  • 2020-11-29 10:19

    You could try looking at CallByName, but I don't think it's going to do what you want (at least, not easily if you're going to want to evaluate multi-dot object/property references).

    0 讨论(0)
  • 2020-11-29 10:30

    False evaluates to Zero. You can construct an integer variable to equate to zero and have it turn out the same way as False.

    0 讨论(0)
提交回复
热议问题