vba 循环遍历形状列表框(更改类型)
vba Looping through Shape Listbox (change type)
所以我有这个带有几个列表框的电子表格。在这些列表框中,我有一些 values/items 实际上是过滤器。我想让每个列表框的每个 item/filter 修改我代码中的 SQL 查询。
所以我被要求遍历列表框,我设法通过循环电子表格的形状来做到这一点,但最终......这些列表框现在被视为 VBA 中的形状,而不是列表框了。我正在寻找一种方法来在列表框中转动我的形状,或者从 Shapes 类型中找到一种方法来循环每个列表框的项目。这是我的代码的一部分,到目前为止,我遍历每个 shapes/listboxes,如果在我的形状名称中有单词“CFRA”,那么我想在我的列表框中选择的每个项目中循环,以便我的函数 return他们。
Private Function getListFilters() As String
My_Sheet.Activate
Dim Shp
For Each Shp In My_Sheet.Shapes
pos = InStrRev(Shp.Name, "CFRA", , vbTextCompare)
MsgBox (pos)
If pos <> 0 Then
MsgBox (TypeName(Shp))
End If
Next
End Function
提前感谢那些愿意帮助我的人,祝你今天愉快:)
由于您没有说明要从列表框中提取什么,请尝试下一个Function
。它将提供名称中包含“CFRA”字符串的列表框对象。当然可以使用任何字符串:
Private Function getListObjX(strPartName As String, sh As Worksheet) As MSForms.ListBox
Dim oObj As OLEObject
For Each oObj In sh.OLEObjects
If oObj.Name Like "*" & strPartName & "*" Then
'Debug.Print oObj.Name, TypeName(oObj.Object): Stop
If TypeName(oObj.Object) = "ListBox" Then
Set getListObjX = oObj.Object: Exit Function
End If
End If
Next
End Function
可以通过以下方式调用:
Sub testGetListObj()
Dim sh As Worksheet, lstB As MSForms.ListBox, lstBF As ListBox
Dim i As Long, arrSel As Variant, k As Long
Set sh = ActiveSheet
Set lstB = getListObjX("CFRA", sh)
If lstB Is Nothing Then MsgBox "No such an ActiveX list box...": Exit Sub
ReDim arrSel(lstB.ListCount - 1)
For i = 0 To lstB.ListCount - 1
If lstB.Selected(i) Then
'Debug.Print lstB.List(i)
arrSel(k) = lstB.List(i): k = k + 1
End If
Next i
ReDim Preserve arrSel(k - 1)
MsgBox Join(arrSel, "|")
End Sub
但是,作为 ActiveX 列表框类型,您可以简单地使用其事件之一。当然,如果您不需要从多个列表框中取项...
我还为 return 表单列表框的对象准备了一个函数(在您澄清问题之前)。也许,别人会用它...
Dim oObj As ListBox
For Each oObj In sh.ListBoxes 'even not being shown by intellisense, this collection exists...
If oObj.Name Like "*" & strPartName & "*" Then
'Debug.Print oObj.Name
Set getListObjF = oObj: Exit Function
End If
Next
End Function
同样可以调用,但是lstB
应该声明为As ListBox
。
已编辑,使功能一步到位:
Private Function getListFilters(strPartName) As String
Dim sh As Worksheet, lstB As MSForms.ListBox
Dim oObj As OLEObject, i As Long, arrSel As Variant, k As Long
Set sh = ActiveSheet ' use here your sheet
For Each oObj In sh.OLEObjects
If oObj.Name Like "*" & strPartName & "*" Then
If TypeName(oObj.Object) = "ListBox" Then
Set lstB = oObj.Object: Exit For
End If
End If
Next
If lstB Is Nothing Then MsgBox "No such an ActiveX list box...": Exit Function
ReDim arrSel(lstB.ListCount - 1)
For i = 0 To lstB.ListCount - 1
If lstB.Selected(i) Then
arrSel(k) = lstB.List(i): k = k + 1
End If
Next i
ReDim Preserve arrSel(k - 1)
getListFilters = Join(arrSel, "|")
End Function
并且该函数将被简单地称为:
Debug.Print getListFilters("CFRA")
您通过OLEObjects
-作品集sheet访问ActiveX
-对象。有趣的控制信息在这样一个对象的属性Object
中:
使用 VBA 函数 TypeName
确定您拥有哪种 OLE 对象
可以使用 Object.ListCount
属性.
获取的项目数
要访问列表框的项目,循环遍历 Object.list
属性(索引从 0 开始,因此循环必须 运行 从 0 到 ListCount- 1)
要检查一个项目是否被选中,使用匹配.Object.Selected 属性.
以下代码将循环打印作品所有列表框中的所有选定项目sheet:
Sub listBoxes()
Dim objx As OLEObject
For Each objx In ActiveSheet.OLEObjects
Debug.Print "Name = " & objx.Name & " Typ = " & TypeName(objx.Object)
If TypeName(objx.Object) = "ListBox" Then
Dim i As Long
For i = 0 To objx.Object.ListCount - 1
If objx.Object.Selected(i) Then
Debug.Print objx.Name, objx.Object.list(i)
End If
Next i
End If
Next
End Sub
Update:显示 Shapes、OleObjects 和 [=61= 之间的连贯性]ActicX 控制 sheet:
A Shape 是所有不属于 cell/range 的容器。可以是任何一种绘制的形状形式(矩形、箭头、星星...),可以是图像、图表、OLEObject、表单控件等。
OLEObject 不是来自 Excel 而是使用称为 OLE 的技术放入 Excel sheet 中的东西, Object Linking and Embedding.
ActiveX 是一个控件(编辑框、列表框...)。这些控件由 Microsoft 开发,旨在 运行 在不同的环境(例如浏览器)中使用。它们可以通过 dll 访问,并且此 dll 已添加到 Excel 和其他办公程序中。
每个 ActiveX 控件都作为 OLEObject 添加到 sheet 中,但您也可以拥有不是 ActiceX 对象的不同 OLEObject(例如嵌入的 Word 文档)。
当你想通过 VBA 访问这些东西时,你可以使用 Shapes
集合,它列出了 sheet 的所有形状(包括所有 OLEObjects),或者你可以使用列出所有 OLEObject(包括所有 ActiveX 控件)的 OLEObjects
集合。但是,没有ActiveX集合,所以如果你想获取所有的ActiceX-Controls,你必须循环上面提到的两个集合。
如果要从形状集合中访问 OLEObject,首先需要检查形状的类型,它的类型必须是 msoOLEControlObject
(12) 或 msoEmbeddedOLEObject
(7) .可以找到所有形状类型的列表 here。
如果形状是 7 或 12,您可以使用 Shape.OLEFormat.Object
访问 OLEObject
。以下循环结果完全相同(ws
只是一个 worksheet 变量)
Dim sh As Shape, oleObj As OLEObject
For Each sh In ws.Shapes
If sh.Type = msoOLEControlObject Or sh.Type = msoEmbeddedOLEObject Then
Set oleObj = sh.OLEFormat.Object
Debug.Print oleObj.Name, oleObj.OLEType
End If
Next
For Each oleObj In ws.OLEObjects
Debug.Print oleObj.Name, oleObj.OLEType
Next
注意 sh.Name 和 sh.OLEFormat.Object.Name 不一定相同。
现在最后一步是找到特定类型的 ActiveX 控件,这已经在上面的原始答案的代码中显示 - 可以通过 oleObj.object
访问 ActiveX 控件。如果 VBA 函数 TypeName
过滤掉例如您的列表框,请检查对象类型。
所以我有这个带有几个列表框的电子表格。在这些列表框中,我有一些 values/items 实际上是过滤器。我想让每个列表框的每个 item/filter 修改我代码中的 SQL 查询。 所以我被要求遍历列表框,我设法通过循环电子表格的形状来做到这一点,但最终......这些列表框现在被视为 VBA 中的形状,而不是列表框了。我正在寻找一种方法来在列表框中转动我的形状,或者从 Shapes 类型中找到一种方法来循环每个列表框的项目。这是我的代码的一部分,到目前为止,我遍历每个 shapes/listboxes,如果在我的形状名称中有单词“CFRA”,那么我想在我的列表框中选择的每个项目中循环,以便我的函数 return他们。
Private Function getListFilters() As String
My_Sheet.Activate
Dim Shp
For Each Shp In My_Sheet.Shapes
pos = InStrRev(Shp.Name, "CFRA", , vbTextCompare)
MsgBox (pos)
If pos <> 0 Then
MsgBox (TypeName(Shp))
End If
Next
End Function
提前感谢那些愿意帮助我的人,祝你今天愉快:)
由于您没有说明要从列表框中提取什么,请尝试下一个Function
。它将提供名称中包含“CFRA”字符串的列表框对象。当然可以使用任何字符串:
Private Function getListObjX(strPartName As String, sh As Worksheet) As MSForms.ListBox
Dim oObj As OLEObject
For Each oObj In sh.OLEObjects
If oObj.Name Like "*" & strPartName & "*" Then
'Debug.Print oObj.Name, TypeName(oObj.Object): Stop
If TypeName(oObj.Object) = "ListBox" Then
Set getListObjX = oObj.Object: Exit Function
End If
End If
Next
End Function
可以通过以下方式调用:
Sub testGetListObj()
Dim sh As Worksheet, lstB As MSForms.ListBox, lstBF As ListBox
Dim i As Long, arrSel As Variant, k As Long
Set sh = ActiveSheet
Set lstB = getListObjX("CFRA", sh)
If lstB Is Nothing Then MsgBox "No such an ActiveX list box...": Exit Sub
ReDim arrSel(lstB.ListCount - 1)
For i = 0 To lstB.ListCount - 1
If lstB.Selected(i) Then
'Debug.Print lstB.List(i)
arrSel(k) = lstB.List(i): k = k + 1
End If
Next i
ReDim Preserve arrSel(k - 1)
MsgBox Join(arrSel, "|")
End Sub
但是,作为 ActiveX 列表框类型,您可以简单地使用其事件之一。当然,如果您不需要从多个列表框中取项...
我还为 return 表单列表框的对象准备了一个函数(在您澄清问题之前)。也许,别人会用它...
Dim oObj As ListBox
For Each oObj In sh.ListBoxes 'even not being shown by intellisense, this collection exists...
If oObj.Name Like "*" & strPartName & "*" Then
'Debug.Print oObj.Name
Set getListObjF = oObj: Exit Function
End If
Next
End Function
同样可以调用,但是lstB
应该声明为As ListBox
。
已编辑,使功能一步到位:
Private Function getListFilters(strPartName) As String
Dim sh As Worksheet, lstB As MSForms.ListBox
Dim oObj As OLEObject, i As Long, arrSel As Variant, k As Long
Set sh = ActiveSheet ' use here your sheet
For Each oObj In sh.OLEObjects
If oObj.Name Like "*" & strPartName & "*" Then
If TypeName(oObj.Object) = "ListBox" Then
Set lstB = oObj.Object: Exit For
End If
End If
Next
If lstB Is Nothing Then MsgBox "No such an ActiveX list box...": Exit Function
ReDim arrSel(lstB.ListCount - 1)
For i = 0 To lstB.ListCount - 1
If lstB.Selected(i) Then
arrSel(k) = lstB.List(i): k = k + 1
End If
Next i
ReDim Preserve arrSel(k - 1)
getListFilters = Join(arrSel, "|")
End Function
并且该函数将被简单地称为:
Debug.Print getListFilters("CFRA")
您通过OLEObjects
-作品集sheet访问ActiveX
-对象。有趣的控制信息在这样一个对象的属性Object
中:
使用 VBA 函数
TypeName
确定您拥有哪种 OLE 对象可以使用
获取的项目数Object.ListCount
属性.要访问列表框的项目,循环遍历
Object.list
属性(索引从 0 开始,因此循环必须 运行 从 0 到 ListCount- 1)要检查一个项目是否被选中,使用匹配.Object.Selected 属性.
以下代码将循环打印作品所有列表框中的所有选定项目sheet:
Sub listBoxes()
Dim objx As OLEObject
For Each objx In ActiveSheet.OLEObjects
Debug.Print "Name = " & objx.Name & " Typ = " & TypeName(objx.Object)
If TypeName(objx.Object) = "ListBox" Then
Dim i As Long
For i = 0 To objx.Object.ListCount - 1
If objx.Object.Selected(i) Then
Debug.Print objx.Name, objx.Object.list(i)
End If
Next i
End If
Next
End Sub
Update:显示 Shapes、OleObjects 和 [=61= 之间的连贯性]ActicX 控制 sheet:
A Shape 是所有不属于 cell/range 的容器。可以是任何一种绘制的形状形式(矩形、箭头、星星...),可以是图像、图表、OLEObject、表单控件等。
OLEObject 不是来自 Excel 而是使用称为 OLE 的技术放入 Excel sheet 中的东西, Object Linking and Embedding.
ActiveX 是一个控件(编辑框、列表框...)。这些控件由 Microsoft 开发,旨在 运行 在不同的环境(例如浏览器)中使用。它们可以通过 dll 访问,并且此 dll 已添加到 Excel 和其他办公程序中。
每个 ActiveX 控件都作为 OLEObject 添加到 sheet 中,但您也可以拥有不是 ActiceX 对象的不同 OLEObject(例如嵌入的 Word 文档)。
当你想通过 VBA 访问这些东西时,你可以使用 Shapes
集合,它列出了 sheet 的所有形状(包括所有 OLEObjects),或者你可以使用列出所有 OLEObject(包括所有 ActiveX 控件)的 OLEObjects
集合。但是,没有ActiveX集合,所以如果你想获取所有的ActiceX-Controls,你必须循环上面提到的两个集合。
如果要从形状集合中访问 OLEObject,首先需要检查形状的类型,它的类型必须是 msoOLEControlObject
(12) 或 msoEmbeddedOLEObject
(7) .可以找到所有形状类型的列表 here。
如果形状是 7 或 12,您可以使用 Shape.OLEFormat.Object
访问 OLEObject
。以下循环结果完全相同(ws
只是一个 worksheet 变量)
Dim sh As Shape, oleObj As OLEObject
For Each sh In ws.Shapes
If sh.Type = msoOLEControlObject Or sh.Type = msoEmbeddedOLEObject Then
Set oleObj = sh.OLEFormat.Object
Debug.Print oleObj.Name, oleObj.OLEType
End If
Next
For Each oleObj In ws.OLEObjects
Debug.Print oleObj.Name, oleObj.OLEType
Next
注意 sh.Name 和 sh.OLEFormat.Object.Name 不一定相同。
现在最后一步是找到特定类型的 ActiveX 控件,这已经在上面的原始答案的代码中显示 - 可以通过 oleObj.object
访问 ActiveX 控件。如果 VBA 函数 TypeName
过滤掉例如您的列表框,请检查对象类型。