这里的交易......在试图超越我对Excel VBA中的类模块的恐惧时,我决定创建一个类是一个数组,然后添加函数(方法)来添加元素,排序一个这些是我在正常模块中作为函数/ subs重写的东西,但希望使用类可能是向前迈出的一步。
代码模块
Public Type Thing
Name As String
SomeNumber As Double
End Type
课程模块
Private pSomething() As Thing
接下来是所有常用的公共LET和GET,以及用于向数组中插入新值的函数。然后我进入排序功能/方法。按Name或SomeNumber排序没有问题,但到目前为止需要两个函数/方法。我想参数化为单个函数/ 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
我想做的是取代以下(在这个gawdawful IF(IIF ...)无意义的第二部分中它的同伴
IIf(FieldName = "Name", pSomething(i).Name > pSomething(j).Name, pSomething(i).SomeNumber > pSomething(j).SomeNumber)
......用这样的东西
"pSomething(i)." & FieldName > "pSomething(j)." & FieldName
直接问题:如何获取要评估/转换为代码的字符串?
间接问题:是否有其他技术可以传入字段名并将其视为字符串以外的其他内容?
提前感谢任何帮助,帮助,指导,指导,参考,建议,这是一个愚蠢的错误或嘲弄的评论:)。
答案 0 :(得分:3)
BiggerDon, 我试图遵循你的代码,你是对的,嵌套的IIF是gawdawful。我可以建议您使用SELECT CASE语句重写代码。这可能会有所帮助。 此外,您想要实现的目标是什么?对于单维数组而言,这几乎看起来有点过分。
您可以使用内置的其他Excel VBA方法。
我刚刚对网格排序进行了快速的互联网搜索,并且遇到了Pearson的网站http://www.cpearson.com/excel/SortingArrays.aspx
你可以查看一下。
答案 1 :(得分:1)
@BiggerDon, 如何为每个字段添加属性的自定义类型类。 遍历记录并将它们添加到自定义类的集合中。执行此操作时,您可以确定将哪个字段用作集合的键。 然后使用这里介绍的东西。 How do I sort a collection?
答案 2 :(得分:0)
考虑一种基于自定义类而不是类型的方法,并使用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类模块中,名称{{1} }:
Storage
将以下代码放在 VBA类模块中,名称为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
:
OrdinalType
将以下代码放在 VBA类模块中,名称为Public Name As String
Public Index As Double
:
ExtendedType
此示例显示如何在存储对象中创建和存储不同类型的实例,这些实例能够处理这些类型(在此特定情况下) - 将字符串作为排序字段名称进行排序。请注意,此类VBS注射异常,通常不是最佳做法。关于处理速度 - 我的N7110上Public Name As String
Public Index As Double
Public Additional As String
通话大约需要15 mksecs。