4 Stimmen

IFDEF-Äquivalent in VBA

Ich habe Code, der sowohl in Excel 2003 als auch in Excel 2007 ausgeführt werden muss, und es gibt einige Stellen, an denen Änderungen in den Versionen den Code zum Stillstand bringen. Ich habe versucht, diese Zeilen mit If-Else-Anweisungen zu trennen, aber der Code lässt sich weder in der einen noch in der anderen Version kompilieren, weil er den für die andere Version verwendeten Code nicht erkennt. Gibt es eine Möglichkeit, einer Version mitzuteilen, dass sie einen Codeblock ignorieren soll, ähnlich wie ein #ifdef in C oder C++, in VBA?

5voto

Oorang Punkte 6520

Dies ist ein guter Ausgangspunkt, aber es wird nicht mit der Version von Excel funktionieren, auf der es läuft, da dies nur zur Laufzeit und nicht zur Kompilierzeit herausgefunden werden kann.

Wenn Sie Ihren Code auf der Grundlage von Informationen verzweigen müssen, die nur zur Laufzeit verfügbar sind, können Sie Late Binding als Lösung in Betracht ziehen. Es gibt zwei Möglichkeiten, wie Sie Versionsprobleme umgehen können.

Der erste Weg kann verwendet werden, wenn Sie auf eine Eigenschaft oder Methode zugreifen müssen, die nur in bestimmten Versionen vorhanden ist, können Sie CallByName verwenden. Der Vorteil von CallByName ist, dass Sie die frühe Bindung (und Intellisense) für Ihre Objekte so weit wie möglich beibehalten können.

In Excel 2007 gibt es zum Beispiel die neue Eigenschaft TintAndShade. Wenn Sie die Farbe eines Bereichs ändern wollten und in Excel 2007 sicherstellen wollten, dass TintAndShade auf 0 gesetzt ist, würden Sie Probleme bekommen, weil Ihr Code in Excel 2003 nicht kompiliert werden kann, da TintAndShade nicht als Eigenschaft des Bereichsobjekts vorhanden ist. Wenn Sie mit CallByName auf die Eigenschaft zugreifen, von der Sie wissen, dass sie nicht in allen Versionen vorhanden ist, wird Ihr Code in allen Versionen kompiliert, aber nur in den von Ihnen angegebenen Versionen ausgeführt. Siehe unten:

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 

Der zweite Weg ist für Klassen, die über "Neu" instanziiert werden müssen und in alten Versionen gar nicht existieren. Mit Excel werden Sie nicht auf dieses Problem stoßen, aber ich werde eine kurze Demo geben, damit Sie sehen können, was ich meine:

Stellen Sie sich vor, Sie wollten File IO durchführen, und aus irgendeinem seltsamen Grund hatten nicht alle Computer die Microsoft Scripting Runtime installiert. Aber aus einem ebenso bizarren Grund wollten Sie sicherstellen, dass sie verwendet wird, wenn sie verfügbar ist. Wenn Sie einen Verweis darauf setzen und in Ihrem Code eine frühe Bindung verwenden, lässt sich der Code auf Systemen, auf denen die Datei nicht vorhanden ist, nicht kompilieren. Also verwenden Sie stattdessen Late Binding:

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

Es gibt eine umfassende Liste aller Ergänzungen und Änderungen am Excel-Objektmodell seit 2003:
http://msdn.microsoft.com/en-us/library/bb149069.aspx Für Änderungen zwischen 1997 und 2000 siehe hier:
http://msdn.microsoft.com/en-us/library/aa140068(office.10).aspx

2voto

Mark Lavin Punkte 23896

Ja, es ist möglich, eine bedingte Kompilierung in Excel VBA durchzuführen. Im Folgenden finden Sie eine kurze Anleitung und einige Beispielcodes: Bedingte Kompilierung

#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

0voto

JustPlainBill Punkte 276

Können Sie die beanstandeten Codezeilen veröffentlichen?

Handelt es sich um eine Konstante wie vbYes oder xlFileFormat oder was auch immer, verwenden Sie den entsprechenden numerischen Wert.

Zeigen Sie mir, was Sie haben, und ich werde sehen, ob ich es umgestalten kann.

Rechnung

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X