4

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

4

3 回答 3

5

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

如果您需要基于仅在运行时可发现的信息来分支代码,您可能会考虑将后期绑定作为一种解决方案。有两种方法可以绕过版本问题。

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

举个例子,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 

第二种方法是用于必须通过“新”实例化并且在旧版本中甚至不存在的类。你不会在 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

于 2009-05-29T18:22:16.957 回答
2

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

#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
于 2009-05-29T15:55:05.307 回答
0

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

如果它是像 vbYes 或 xlFileFormat 之类的常量,请使用相应的数值。

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

账单

于 2009-05-31T18:26:28.697 回答