VBA“编译错误:语句无效外部types块”

我在Excel 2010中运行了大量的计算,因此数据types是非常重要的,以保持macros执行时间尽可能低。

我的优化思路是让用户select所有数据将被声明的数据types(同时指出每种数据types的优缺点,精度/灵活性和CPU密集度/macros执行时间之间的平衡)。 但是,当我运行macros,我收到以下错误信息:

编译错误:

声明无效外部types块

这里是代码的违规部分:

Ind2 As Double, BgrValP As Double, BgrRow As Double, M40eff As Double 

这是macros的相关部分:

 ' 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 

你有:

 Dim RangeNOut as Double Dim RangeNOut as Integer 

虽然那里的IF语句是个好主意,但VBA不会允许你这样做。 它不做有条件的“编译”,因为它不是一种编译语言。 当VBA运行你的代码时,所有的variables都被声明(不pipeDim语句所在的代码在哪里),那么代码就开始执行了。

这是一个很好的想法,你已经想出了,但在VBA中尝试这样做,就像拿一块傻腻子™来进行枪战 – 对于这项工作来说,这是一件可怕的事情。

另外,如果你担心执行速度,VBA也不是你select的武器。 我没有任何数据支持我的头顶,但我怀疑你实际上看到了三种不同的variablestypes的执行速度差异。

要将variablestypes作为parameter passing给函数,请使用以下命令:

 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 。 我不确定你想要在那里完成什么,但是:

  1. 不要使用goto 。 除了VBA风格的error handling, 几乎没有必要
  2. 无论如何,您没有为Goto定义的标签。

另请参见VBA函数重载另一个可能的选项。

注意:尽pipe起立和接受答案的状态,我尝试了以下,而且按照OP的要求工作:

 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 

所有对Func()调用都在代码的#Else部分,使用Invalid var type passed: text填充Range("A4")

可悲的是,这是行不通的。

如果确实有必要让不同variablestypes的函数做同样的事情,我认为以下是最好的select:

 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