我在Excel 2010中运行VBA宏并进行大量计算,因此数据类型非常重要,以保持宏执行时间尽可能低。
我的优化思路是让用户选择所有数字将被声明为的数据类型(同时指出每种数据类型的优缺点,准确性/灵活性与CPU密集度/宏执行时间之间的平衡)。但是,当我运行宏时,我收到以下错误消息:
编译错误:
语句在类型块
之外无效
以下是代码的违规部分:
Ind2 As Double, BgrValP As Double, BgrRow As Double, M40eff As Double
以下是宏的相关部分:
' Develop fake data to at glance recognize whether program works.
' Source http://www.cpearson.com/excel/optimize.htm
Option Explicit
Private Sub Function1()
On Error GoTo ErrorHandler
Dim userChoice As Variant
Dim strPath As String, strFileN As String, strDirN As String, strRangeNOut As String, strRangeNIn As String, strFilename As String, strTLCorn As String, strBRCorn As String, strSelectedFile As String, strtemp_name As String
Dim lngCount As Long
Dim vResMatrix(), vCPath, vFileN As Variant
' MEeff = measure of efflux due to crudely purified HDL in scintillation
' https://msdn.microsoft.com/en-us/library/ae55hdtk.aspx
' Give the user macro options based on how fast or slow the computer is
userChoice = MsgBox("This macro by default treats all numbers as doubles for maximum precision. If you are running this macro on an old computer, you may want to redeclare numbers as singles, to speed up the macro." & vbNewLine & "You can also use integers for a quick estimate of data results.")
If userChoice = "Double" Then
Dim RangeNOut As Double, vRangeNIn As Double, Ind6 As Double, Ind4 As Double, Ind5 As Double
Dim Step2 As Double, MRow As Double, ColIn As Double, Ind3 As Double, Mcol As Double
Dim MxRNo As Double, BgrSum As Double, RowIn As Double, Ind As Double, M40eff As Double, Step As Double
Dim ColNo As Double, Startcol As Double, Startrow As Double, MeanComp As Double
Dim PlateNo As Double, MonoVal As Double, Ind1 As Double, EntryRow2 As Double, EntryRow As Double
Ind2 As Double, BgrValP As Double, BgrRow As Double, M40eff As Double
Dim BrgSum As Double, BgrVal As Double, RangeNIn As Double, RangeNOut As Double, TLCorn As Double
Dim Volcorr As Double, BRCorn As Double, MEeff As Double, MediaVal As Double
ElseIf userChoice = "Integer" Then
Dim RangeNOut As Integer, vRangeNIn As Integer, ecInd6 As Integer, Ind4 As Integer, Ind5 As Integer
Dim Step2 As Integer, MRow As Integer, ColIn As Integer, Ind3 As Integer, Mcol As Integer
Dim MxRNo As Integer, BgrSum As Integer, RowIn As Integer, Ind As Integer, M40eff As Integer
Dim Step As Integer, ColNo As Integer, Startcol As Integer, Startrow As Integer, MeanComp As Integer
Dim PlateNo As Integer, MonoVal As Integer, Ind1 As Integer, EntryRow2 As Integer, EntryRow As Integer
Dim Ind2 As Integer, BgrValP As Integer, BgrRow As Integer, M40eff As Integer
Dim BrgSum As Integer, BgrVal As Integer, RangeNIn As Integer, RangeNOut As Integer, TLCorn As Integer
Dim Volcorr As Integer, BRCorn As Integer, MEeff As Integer, MediaVal As Integer
ElseIf userChoice = "Single" Then
Dim RangeNOut As Single, vRangeNIn As Single, ecInd6 As Single, Ind4 As Single, Ind5 As Single
Step2 As Single, MRow As Single, ColIn As Single, Ind3 As Single, Mcol As Single
Dim MxRNo As Single, BgrSum As Single, RowIn As Single, Ind As Single, M40eff As Single, Step As Single
Dim ColNo As Single, Startcol As Single, Startrow As Single, MeanComp As Single
Dim PlateNo As Single, MonoVal As Single, Ind1 As Single, EntryRow2 As Single, EntryRow As Single
Ind2 As Single, BgrValP As Single, BgrRow As Single, M40eff As Single
Dim BrgSum As Single, BgrVal As Single, RangeNIn As Single, RangeNOut As Single, TLCorn As Single
Volcorr As Single, BRCorn As Single, MEeff As Single, MediaVal As Single
Else
GoTo Function1
MsgBox("This is not a supported data type: double, single, or integer.", vbCritical, "Unsupported Data Type")
以下是我目前使用的代码:
Private Sub Function2(ByVal VarType As String)
Dim mVers As String
Dim userChoice As Variant
' Give the user macro options based on how fast or slow the computer is using advanced conditional compliling
userChoice = MsgBox("This macro by default treats all numbers as doubles for maximum precision. If you are running this macro on an old computer, you may want to relare numbers as singles, to speed up the macro." & vbNewLine & "You can also use integers for a quick estimate of data results.")
userChoice = VarType
#If VarType = "Double" Or "double" Then
Dim RangeNOut As Double, vRangeNIn As Double, Ind6 As Double, Ind4 As Double, Ind5 As Double
Dim Step2 As Double, MRow As Double, ColIn As Double, Ind3 As Double, Mcol As Double
Dim MxRNo As Double, BgrSum As Double, RowIn As Double, Ind As Double, M40eff As Double, Step As Double
Dim ColNo As Double, Startcol As Double, Startrow As Double, MeanComp As Double
Dim PlateNo As Double, MonoVal As Double, Ind1 As Double, EntryRow2 As Double, EntryRow As Double
Dim Ind2 As Double, BgrValP As Double, BgrRow As Double, M40eff As Double
Dim BrgSum As Double, BgrVal As Double, RangeNIn As Double, RangeNOut As Double, TLCorn As Double
Dim Volcorr As Double, BRCorn As Double, MEeff As Double, MediaVal As Double
#ElseIf VarType = "Single" Or "single" Then
Dim RangeNOut As Single, vRangeNIn As Single, ecInd6 As Single, Ind4 As Single, Ind5 As Single
Step2 As Single, MRow As Single, ColIn As Single, Ind3 As Single, Mcol As Single
Dim MxRNo As Single, BgrSum As Single, RowIn As Single, Ind As Single, M40eff As Single, Step As Single
Dim ColNo As Single, Startcol As Single, Startrow As Single, MeanComp As Single
Dim PlateNo As Single, MonoVal As Single, Ind1 As Single, EntryRow2 As Single, EntryRow As Single
Dim Ind2 As Single, BgrValP As Single, BgrRow As Single, M40eff As Single
Dim BrgSum As Single, BgrVal As Single, RangeNIn As Single, RangeNOut As Single, TLCorn As Single
Dim Volcorr As Single, BRCorn As Single, MEeff As Single, MediaVal As Single
#ElseIf VarType = "Integer" Or "integer" Then
Dim RangeNOut As Integer, vRangeNIn As Integer, ecInd6 As Integer, Ind4 As Integer, Ind5 As Integer
Dim Step2 As Integer, MRow As Integer, ColIn As Integer, Ind3 As Integer, Mcol As Integer
Dim MxRNo As Integer, BgrSum As Integer, RowIn As Integer, Ind As Integer, M40eff As Integer
Dim Step As Integer, ColNo As Integer, Startcol As Integer, Startrow As Integer, MeanComp As Integer
Dim PlateNo As Integer, MonoVal As Integer, Ind1 As Integer, EntryRow2 As Integer, EntryRow As Integer
Dim Ind2 As Integer, BgrValP As Integer, BgrRow As Integer, M40eff As Integer
Dim BrgSum As Integer, BgrVal As Integer, RangeNIn As Integer, RangeNOut As Integer, TLCorn As Integer
Dim Volcorr As Integer, BRCorn As Integer, MEeff As Integer, MediaVal As Integer
#Else
MsgBox "VarType " & VarType & " is not valid. Check spelling."
#End If
' MEeff = measure of efflux due to crudely purified HDL in scintillation
MsgBox "For additional information about this macro:" & vbNewLine & "1. Go to tab Developer" & vbNewLine & "2. Select Visual Basic or Macro." & vbNewLine & "See the comments or MsgBoxes (message boxes)."
' Start File Explorer to select file containing data (simple GUI, much easier than coding in the file)
With Application.FileDialog(msoFileDialogOpen)
.AllowMultiSelect = True
.Show
' Display paths of each file selected
For lngCount = 1 To .SelectedItems.Count
Next lngCount
For Each strFilename In .SelectedItems
MsgBox strFilename
Function2
Next
End With
ErrorHandler:
MsgBox "Error detected" & vbNewLine & "Error" & Err.Number & ": " & Err.Description, vbCritical, "Error Handler: Error " & Err.Number
MsgBox "If you want to force the program to run, go to the line below and insert a ' mark to comment the line out." & vbNewLine & "On Error GoTo ErrorHandler", vbCritical, "Error Handler: Error " & Err.Number
End Sub
答案 0 :(得分:11)
你有:
Dim RangeNOut as Double
Dim RangeNOut as Integer
虽然那里的IF
陈述是个好主意,但VBA不会允许你这样做。它不执行条件'编译',因为它不是编译语言。当VBA运行您的代码时,所有变量都被声明(无论Dim
语句位于代码中的哪个位置),代码就会开始执行。
这是一个很好的想法,你想出来,但在VBA尝试这就像把一块Silly Putty™带到枪战中 - 它的工作非常糟糕。
另外,如果您 关注执行速度,那么VBA也不是您的首选武器。我没有任何统计数据支持它,但我怀疑你实际上看到基于你的三种不同变量类型的执行速度差异很大。
要将变量类型作为参数传递给函数,请使用:
Private Sub Function1(ByVal VarType as String)
#If VarType = "Double" then
...
#ELSEIF VarType = "Single" then
...
#ELSEIF VarType = "Integer" then
...
#ELSE
MsgBox "You passed in a 'VarType' of " & VarType & " - that's not valid"
#ENDIF
另外,我刚刚注意到你的最后Else
Goto Function1
。goto
。我不确定你想要在那里完成什么,但是:
Goto
。除了在VBA样式错误处理中,它几乎从不必要Sub test()
func "Double"
func "Single"
func "Integer"
func "String"
End Sub
Function func(v As String)
#If v = "Double" Then
Dim myvar As Double
Range("A1") = "MyVar type is: " & vartype(v)
#ElseIf v = "Single" Then
Dim myvar As Single
Range("a2") = "MyVar type is: " & vartype(v)
#ElseIf v = "Integer" Then
Dim myvar As Integer
Range("a3") = "MyVar type is: " & vartype(v)
#Else
Range("A4") = "Invalid var type passed: " & v
#End If
MsgBox "Passed in " & v
End Function
定义标签。另请参阅VBA function overloading了解其他可能的选项。
注意:尽管有upvotes和接受的答案状态,我尝试了以下内容,不会按照OP的要求工作:
Func()
对#Else
的所有来电都会在Range("A4")
部分代码中填充,并使用Invalid var type passed:
文字填充Sub Test()
Dim VType as String
While Vtype <> "Integer" and VType <> "Double" and VType <> "Single" and VType <> "Cancel"
vType = msgBox("Enter variable type")
Wend
If VType = "Integer" then
MyFuncInt()
ElseIf VType = "Double" then
MyFuncDouble()
Elseif VType = "Single"
MyFuncSingle()
Else
MsgBox "Function call cancelled"
End if
End Sub
Function MyFuncInt()
Dim AllTheVars as Integer
...
End Function
Function MyFuncDouble()
Dim AllTheVars as Double
...
End Function
Function MyFuncSingle()
Dim AllTheVars as Single
...
End Function
。
可悲的是,这不起作用。
如果真的有必要让不同变量类型的函数做同样的事情,我认为以下是最好的选择:
{{1}}