VBA数组以字段名作为参数sorting

这里的交易…在试图超越我对Excel VBA中的类模块的恐惧,我决定创build一个类是一个数组,然后添加函数(方法)添加元素,sorting实例等。我不断重写作为函数/潜艇的正常模块,但希望使用类可能是一个前进的步骤。

代码模块

Public Type Thing Name As String SomeNumber As Double End Type 

类模块

 Private pSomething() As Thing 

接下来是所有常见的公用LET和GET,还有一个用于向数组中插入新值的函数。 然后我到达sorting函数/方法。 按Name或SomeNumber进行sorting没有问题,但到目前为止需要两个函数/方法。 我想参数化成单个函数/ mehod,然后使用可选参数来控制使用哪个字段。 以下的作品,但似乎有点笨重

 Function SortByField(Optional FieldName As String, Optional SortOrder As vbaSortOrder) Dim strTemp As Thing If SortOrder = 0 Then SortOrder = soBottomToTop If Len(FieldName) = 0 Then FieldName = "Name" Dim i As Long Dim j As Long Dim lngMin As Long Dim lngMax As Long lngMin = LBound(pSomething) lngMax = UBound(pSomething) For i = lngMin To lngMax - 1 For j = i + 1 To lngMax If IIf(SortOrder = soBottomToTop, _ IIf(FieldName = "Name", pSomething(i).Name > pSomething(j).Name, _ pSomething(i).SomeNumber > pSomething(j).SomeNumber), _ IIf(FieldName = "Name", pSomething(i).Name < pSomething(j).Name, _ pSomething(i).SomeNumber < pSomething(j).SomeNumber)) _ Then strTemp = pSomething(i) pSomething(i) = pSomething(j) pSomething(j) = strTemp End If Next j Next i End Function 

我想要做的是取代以下(这是在这个丑angular的IF(IIF …)第二部分同行废话

 IIf(FieldName = "Name", pSomething(i).Name > pSomething(j).Name, pSomething(i).SomeNumber > pSomething(j).SomeNumber) 

像这样的事情

 "pSomething(i)." & FieldName > "pSomething(j)." & FieldName 

直接问题:我如何获得string评估/转换为代码?

间接的问题:是否有其他的技术来传递一个字段名,并把它当作string之外的东西来处理?

在此先感谢您的帮助,帮助,指导,方向,参考,build议这是一个傻瓜的差事,或嘲弄的评论:)。

BiggerDon,我试图按照你的代码,你是正确的嵌套的IIF是gawdawful。 我可以build议你用SELECT CASE语句重写代码。 这可能会有所帮助。 而且,你试图达到的最大目标是什么? 这几乎看起来像一个维度数组的矫枉过正。

可能还有其他Excel VBA内置的方法,你可以利用。

我只是做了快速的网上searchsorting数组,并遇到皮尔逊的网站http://www.cpearson.com/excel/SortingArrays.aspx

你可能要检查一下。

@BiggerDon,如何为每个字段的属性的自定义types类。 循环logging并将其添加到自定义类的集合中。 当你这样做时,你可以确定哪个字段将被用作收集的关键字。 然后使用这里提出的东西。 我如何分类集合?

考虑基于自定义类而不是types的方法,并使用VBScript中的Eval()方法来评估项目的字段值。

将下面的代码放在VBA模块中

 Sub TestStorage() Dim Room As New Storage Dim i As Long Dim Elem As Object Dim Item As Variant Dim Result As String For i = 1 To 10 Set Elem = New OrdinalType Elem.Name = GetRandomFruit Elem.Index = i Room.Push Elem Next For i = 11 To 20 Set Elem = New ExtendedType Elem.Name = GetRandomFruit Elem.Index = i Elem.Additional = "Extended" Room.Push Elem Next Set Elem = Nothing ShowList Room.GetContent Room.SortByField "Name", True ShowList Room.GetContent Room.SortByField "Index", False ShowList Room.GetContent End Sub Sub ShowList(Arr) Result = "" For Each Item In Arr Result = Result & Item.Name & " (" & Item.Index & ")" If TypeName(Item) = "ExtendedType" Then Result = Result & " " & Item.Additional End If Result = Result & vbCrLf Next MsgBox Result End Sub Function GetRandomFruit() Dim Fruits Randomize Fruits = Array("Apple", "Apricot", "Banana", "Bilberry", "Blackberry", "Blackcurrant", "Blueberry", "Coconut", "Currant", "Cherry", "Cherimoya", "Clementine", "Date", "Damson", "Durian", "Elderberry", "Fig", "Feijoa", "Gooseberry", "Grape", "Grapefruit", "Huckleberry", "Jackfruit", "Jambul", "Jujube", "Kiwifruit", "Kumquat", "Lemon", "Lime", "Loquat", "Lychee", "Mango", "Mangostine", "Melon", "Cantaloupe", "Honeydew", "Watermelon", "Rock melon", "Nectarine", "Orange", "Passionfruit", "Peach", "Pear", "Plum", "Prune", "Pineapple", "Pomegranate", "Pomelo", "Raisin", "Raspberry", "Rambutan", "Redcurrant", "Satsuma", "Strawberry", "Tangerine", "Ugli Fruit") GetRandomFruit = Fruits(LBound(Fruits) + Round(Rnd * (UBound(Fruits) - LBound(Fruits)))) End Function 

添加引用到Microsoft脚本控制 ActiveX(菜单 – 工具 – 参考)。
将下面的代码放在VBA Class Module ,Name Storage

 Private Content As Variant Private SC As MSScriptControl.ScriptControl Private Sub Class_Initialize() Set SC = New MSScriptControl.ScriptControl SC.Language = "VBScript" SC.ExecuteStatement "Function EvalProp(Item, Name): EvalProp = Eval(""Item."" & Name): End Function" Content = Array() End Sub Private Function GetValue(ObjectInstance, PropertyName) GetValue = SC.Run("EvalProp", ObjectInstance, PropertyName) End Function Public Sub Push(Item) ReDim Preserve Content(UBound(Content) + 1) Set Content(UBound(Content)) = Item End Sub Public Function Pop() Set Pop = Content(UBound(Content)) ReDim Preserve Content(UBound(Content) - 1) End Function Public Sub SortByField(Optional PropName As String = "Name", Optional SortAsc As Boolean = True) Dim i As Long Dim j As Long Dim l As Long Dim u As Long Dim a As Variant Dim b As Variant Dim tmp As Object l = LBound(Content) u = UBound(Content) For i = l To u - 1 For j = i + 1 To u a = GetValue(Content(i), PropName) b = GetValue(Content(j), PropName) If (a > b And SortAsc) Or (a < b And Not SortAsc) Then Set tmp = Content(j) Set Content(j) = Content(i) Set Content(i) = tmp End If Next j Next i End Sub Public Function GetContent() GetContent = Content End Function Public Function GetSize() GetSize = UBound(Content) - LBound(Content) + 1 End Function 

将下面的代码放在VBA类模块中 ,名称OrdinalType

 Public Name As String Public Index As Double 

将下面的代码放在VBA类模块中 ,Name ExtendedType

 Public Name As String Public Index As Double Public Additional As String 

这个例子展示了如何在存储对象中创build和存储不同types的实例,在这种情况下,可以处理这些types的存储对象 – 以string作为sorting字段的名称进行sorting。 请注意,这样的VBS注射是不正常的,通常不是最佳实践。 关于处理速度 – Function GetValue()调用在我的N7110上大约需要15秒。