【发布时间】:2021-09-26 21:54:16
【问题描述】:
下午好。 我正在尝试编写函数以将列表输出到单元格(使用数据验证的下拉列表)。
假设指定了一个列表,其中元素根据以下结构进行编码:父指针|指向儿童的指针| 高分辨率照片| CLIPARTO项目文本。
目前,该函数只准备好了一半,只能读取指定的列表。但是已经到了这个阶段,我想测试一下,尝试通过单元格的勾选添加一个下拉列表。
无法直接执行此操作,我尝试通过命名范围添加。
我不是要求结束该功能,而是要求您建议如何制作下拉列表。也许我的函数没有返回任何东西(尽管它确实返回了一个数组)。如何将我的计划付诸实施?
'Definition of structure
Type Node
Name As String
ID As Long
Level As Long
ChildrenMas() As Long 'an array of links to child Nodes
Parent As Long 'indicates a link to the parent
ParentMarker As String 'indicates the parent symbol
ChildrenMarker As String 'indicates the symbol that children expect for this parent
ThisIsRoot As Boolean 'For the root - true, for the rest - false
DeepCount As Long ' Number of offspring in all subsequent generations
UsedInFinalTree As Boolean 'the attribute is set at the time of determining the place in the tree for the node
End Type
Type Tree
Name As String
ElementsCount As Long
Levels As Long
End Type
Function MultilevelList(Range As Range, _
Optional Delimiter As String = "|", _
Optional Levell As Long = 0, _
Optional OutputInformation As String = "text")
ReDim RangeAsString(1 To Range.Count) As String
Dim RangeAsStringCount As Long
Dim c As Range
Dim NodesArray() As Node 'an array of tree nodes
Dim ReturnedNodesArray() As Node 'an array of tree nodes for output
Dim ReturnedNodesArrayNames() As String
Dim m As Node
Dim NewTree As Tree 'creating a tree
Dim i, j, k, SLong As Integer
Dim S As String
Dim a() As String 'array to divide the string
Dim tm, td As Boolean
i = 1
For Each c In Range
RangeAsString(i) = c.Text
i = i + 1
Next c
RangeAsStringCount = Range.Count
NewTree.Name = "Tree"
'define the length of the array as the length of the resulting Range of strings
ReDim NodesArray(1 To UBound(RangeAsString))
For i = 1 To UBound(NodesArray)
NodesArray(i).ParentMarker = "_none_ParentMarker" & i
NodesArray(i).ChildrenMarker = "_none_ChildrenMarker" & i
Next i
k = 1
For i = 1 To UBound(RangeAsString)
SLong = 0
S = RangeAsString(i)
For j = 1 To Len(S)
If Delimiter = Mid(S, j, 1) Then SLong = SLong + 1
Next
If SLong >= 2 Then
a = Split(S, Delimiter, 3)
NodesArray(k).ID = k
NodesArray(k).ParentMarker = a(0)
NodesArray(k).ChildrenMarker = a(1)
NodesArray(k).Name = a(2)
If NodesArray(k).ParentMarker = "" Then
NewTree.Levels = 1
NewTree.ElementsCount = NewTree.ElementsCount + 1
NodesArray(k).Level = 1
NodesArray(k).ThisIsRoot = True
NodesArray(k).UsedInFinalTree = True
RangeAsString(i) = Empty
RangeAsStringCount = RangeAsStringCount - 1
End If
If i + 1 <> UBound(RangeAsString) Then k = k + 1
Else
RangeAsString(i) = Empty
RangeAsStringCount = RangeAsStringCount - 1
End If
Next i
tm = False
Do Until RangeAsStringCount < 1
If tm = True Then Exit Do
td = False
For i = 1 To UBound(NodesArray)
If NodesArray(i).Level = 0 Then
For j = 1 To UBound(NodesArray)
If NodesArray(i).ParentMarker = NodesArray(j).ChildrenMarker And _
NodesArray(j).Level <> 0 Then
If IsNotEmptyArray(NodesArray(j).ChildrenMas) Then
k = UBound(NodesArray(j).ChildrenMas)
ReDim Preserve NodesArray(j).ChildrenMas(1 To UBound(NodesArray(j).ChildrenMas) + 1)
k = k + 1
NodesArray(j).ChildrenMas(k) = i
NodesArray(i).Level = NodesArray(j).Level + 1
NodesArray(i).UsedInFinalTree = True
NodesArray(i).Parent = j
RangeAsStringCount = RangeAsStringCount - 1
td = True
Else
k = 0
ReDim Preserve NodesArray(j).ChildrenMas(1 To 1)
NodesArray(j).ChildrenMas(1) = i
NodesArray(i).Level = NodesArray(j).Level + 1
NodesArray(i).UsedInFinalTree = True
NodesArray(i).Parent = j
RangeAsStringCount = RangeAsStringCount - 1
td = True
End If
B = B
End If
Next j
End If
Debug.Print i
If td = False Then RangeAsStringCount = RangeAsStringCount - 1
Next i
Loop
ReDim ReturnedNodesArray(1 To UBound(NodesArray))
ReDim ReturnedNodesArrayNames(1 To UBound(NodesArray))
k = 0
For i = 1 To UBound(NodesArray)
If Levell = 0 Then
If NodesArray(i).UsedInFinalTree = True Then
k = k + 1
ReturnedNodesArray(k) = NodesArray(i)
ReturnedNodesArrayNames(k) = ReturnedNodesArray(k).Name
End If
Else
If NodesArray(i).Level = Levell And NodesArray(i).UsedInFinalTree = True Then
k = k + 1
ReturnedNodesArray(k) = NodesArray(i)
ReturnedNodesArrayNames(k) = ReturnedNodesArray(k).Name
End If
End If
Next i
ReDim Preserve ReturnedNodesArray(1 To k)
ReDim Preserve ReturnedNodesArrayNames(1 To k)
B = UBound(RangeAsString)
If OutputInformation = "text" Then
MultilevelList = WorksheetFunction.Transpose(ReturnedNodesArrayNames)
'MultilevelList = ReturnedNodesArrayNames
End If
End Function
'function to check the initialized youth of the array
Function IsNotEmptyArray(parArray As Variant) As Boolean
On Error Resume Next
IsNotEmptyArray = LBound(parArray) <= UBound(parArray)
End Function
【问题讨论】:
-
您能否编辑您的问题以包括:1. 什么类型的下拉列表(数据验证、用户窗体控件等),以及 2. 您的函数的代码。
-
@Ambie 纠正并纠正了一切
标签: excel vba user-defined-functions