Эквивалент IFDEF в VBA
-
06-09-2019 - |
Вопрос
У меня есть код, который должен выполняться как в Excel 2003, так и в Excel 2007, и есть несколько мест, где изменения в версиях приводят к остановке кода.Я попытался разделить эти строки с помощью операторов If-Else, но код не будет компилироваться ни в том, ни в другом случае, потому что он не распознает код, используемый для другого.Есть ли какой-нибудь способ, которым я мог бы указать одной версии игнорировать блок кода, подобный #ifdef в стиле C или C ++, в VBA?
Решение
Это хорошая отправная точка, но она не будет работать с версией Excel, на которой она запущена, поскольку это можно выяснить только во время выполнения, а не во время компиляции.
Если вам нужно разветвлять свой код на основе информации, доступной только во время выполнения, вы можете рассмотреть позднюю привязку в качестве решения.Есть два способа обойти проблемы с версией.
Первый способ можно использовать, если вам нужно получить доступ к свойству или методу, который существует только в определенных версиях, вы можете использовать CallByName .Преимущество вызова по имени заключается в том, что оно позволяет вам максимально сохранить раннюю привязку (и intellisense) для ваших объектов.
Чтобы привести пример, в Excel 2007 появилось новое свойство TintAndShade.Если вы хотите изменить цвет диапазона, а для Excel 2007 также убедитесь, что значение TintAndShade равно 0, у вас возникнут проблемы, потому что ваш код не будет компилироваться в Excel 2003, который не имеет значения TintAndShade в качестве свойства объекта range.Если вы получаете доступ к свойству, которое, как вы знаете, есть не во всех версиях, используя 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 вы не столкнетесь с этой проблемой, но я приведу краткую демонстрацию, чтобы вы могли понять, что я имею в виду:
Представьте, что вы хотели выполнить ввод-вывод файлов, и по какой-то странной причине не на всех компьютерах была установлена среда выполнения 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
Существует полный список всех дополнений и изменений в объектной модели Excel с 2003 года:
http://msdn.microsoft.com/en-us/library/bb149069.aspx
Об изменениях за период с 1997 по 2000 год читайте здесь:
http://msdn.microsoft.com/en-us/library/aa140068 (office.10).aspx
Другие советы
Да, можно выполнить условную компиляцию в 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
Можете ли вы опубликовать оскорбительные строки кода?
Если это константа типа vbYes, XlFileFormat или что-то еще, используйте соответствующее числовое значение.
Покажи мне, что у тебя есть, и я посмотрю, смогу ли провести рефакторинг.
Счет