IFDEF等效于VBA

时间:2009-05-29 15:20:42

标签: excel vba excel-vba office-2007 office-2003

我的代码需要在Excel 2003和Excel 2007上运行,并且有一些地方版本中的更改会导致代码停止。我尝试用If-Else语句将这些行分开,但代码不会编译,因为它不能识别用于另一个的代码。有什么方法可以告诉一个版本忽略一个代码块,类似于VBA中的C或C ++风格的#ifdef?

3 个答案:

答案 0 :(得分:4)

  

这是一个很好的起点,但它不适用于运行它的Excel版本,因为它只能在运行时计算出来,而不能在编译时计算出来。

如果您需要根据仅在运行时可发现的信息来分支代码,则可以将后期绑定视为解决方案。有两种方法可以解决版本问题。

如果您需要访问仅存在于某些版本中的属性或方法,则可以使用第一种方法,您可以使用CallByName。名称调用的优点是它允许您尽可能地保留对象的早期绑定(和intellisense)。

举一个例子,Excel 2007有一个新的TintAndShade属性。如果要更改范围的颜色,并且对于Excel 2007也确保将TintAndShade设置为0,则会遇到问题,因为您的代码无法在Excel 2003中编译,而Excel 2003没有TintAndShade作为范围对象的属性。如果您使用CallByName访问您知道不在所有版本中的属性,则代码将在所有版本中编译,但仅在您指定的版本中运行。见下文:

Sub Test() 
    ColorRange Selection, Excel.Application.version, 6 
End Sub 
Sub ColorRange(rng As Excel.Range, version As Double, ParamArray args() As Variant) 
    With rng.Interior 
        .colorIndex = 6 
        .Pattern = xlSolid 
        If version >= 12# Then 
             'Because the property name is stored in a string this will still compile.
             'And it will only get called if the correct version is in use.
            CallByName rng.Interior, "TintAndShade", VbLet, 0 
        End If 
    End With 
End Sub 

第二种方法是必须通过“New”实例化的类,并且在旧版本中甚至不存在。你不会用Excel遇到这个问题,但我会给你一个快速演示,这样你就可以看到我的意思了:

想象一下,您想要执行文件IO,并且由于某些奇怪的原因,并非所有计算机都具有Microsoft Scripting Runtime。但是出于一些同样奇怪的原因,你想确保它在可用的时候被使用。如果设置对它的引用并在代码中使用早期绑定,则代码将无法在没有该文件的系统上编译。所以你使用后期绑定:

Public Sub test()
    Dim strMyString As String
    Dim strMyPath As String
    strMyPath = "C:\Test\Junk.txt"
    strMyString = "Foo"
    If LenB(Dir("C:\Windows\System32\scrrun.dll")) Then
        WriteString strMyPath, strMyString
    Else
        WriteStringNative strMyPath, strMyString
    End If
End Sub

Public Sub WriteString(ByVal path As String, ByVal value As String)
    Dim fso As Object '<-Use generic object
    'This is late binding:
    Set fso = CreateObject("Scripting.FileSystemObject")
    fso.CreateTextFile(path, True, False).Write value
End Sub

Public Sub WriteStringNative(ByVal path As String, ByVal value As String)
    Dim lngFileNum As Long
    lngFileNum = FreeFile
    If LenB(Dir(path)) Then Kill path
    Open path For Binary Access Write Lock Read Write As #lngFileNum
    Put #lngFileNum, , value
    Close #lngFileNum
End Sub

自2003年以来,Excel对象模型的所有添加和更改都有一个完整的列表:
http://msdn.microsoft.com/en-us/library/bb149069.aspx 对于1997年至2000年间的变化,请点击此处:
http://msdn.microsoft.com/en-us/library/aa140068(office.10).aspx

答案 1 :(得分:2)

是的,可以在Excel VBA中进行条件编译。以下是一个简短的资源和一些示例代码: Conditional Compilation

#If Win32 Then
    ' Profile String functions:
    Private Declare Function WritePrivateProfileString Lib "KERNEL32" Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lpFileName As String) As Long
    Private Declare Function GetPrivateProfileString Lib "KERNEL32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As Any, ByVal lpKeyName As Any, ByVal lpDefault As Any, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As Long
#Else
    ' Profile String functions:
    Private Declare Function WritePrivateProfileString Lib "Kernel" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lpFileName As String) As Integer
    Private Declare Function GetPrivateProfileString Lib "Kernel" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As Any, ByVal lpReturnedString As String, ByVal nSize As Integer, ByVal lpFileName As String) As Integer
#End If

答案 2 :(得分:0)

你能发布有问题的代码行吗?

如果它是常量,如vbYes或xlFileFormat或其他,请使用相应的数值。

告诉我你得到了什么,我会看看我是否可以重构它。

比尔