Domanda

Ho codice che deve funzionare sia su Excel 2003 e Excel 2007, e ci sono alcuni punti in cui i cambiamenti nelle versioni causano il codice per fermare. Ho provato a separare queste righe con dichiarazioni if-else, ma il codice non viene compilato su entrambi perché non riconosce il codice utilizzato per l'altro. C'è un modo ho potuto dire una versione di ignorare un blocco di codice, simile ad una C o C ++ - stile #ifdef, in VBA

?
È stato utile?

Soluzione

  

Questo è un buon punto di partenza, ma non funziona con la versione di Excel che la sua esecuzione su, dal momento che può essere capito solo in fase di esecuzione, non è tempo di compilazione.

Se avete bisogno di ramo il codice in base alle informazioni solo individuabili in fase di esecuzione si potrebbe considerare l'associazione tardiva come una soluzione. Ci sono due modi per intrufolarsi intorno ai problemi di versione.

Il primo modo può essere utilizzato se avete bisogno di accedere a una proprietà o un metodo che esiste solo in alcune versioni, è possibile utilizzare CallByName. Il vantaggio di chiamare per il nome è che permette di preservare l'associazione anticipata (e IntelliSense) per gli oggetti, per quanto possibile.

Per fare un esempio, Excel 2007 ha una nuova proprietà TintAndShade. Se si voleva cambiare il colore di una serie, e per Excel 2007 garantire anche TintAndShade è stato impostato su 0 si avrebbe eseguito nei guai perché il codice non viene compilato in Excel 2003 che non ha TintAndShade come una proprietà dell'oggetto gamma. Se si accede alla proprietà che si sa non è in tutte le versioni che utilizzano CallByName, è il codice verrà compilato in tutte le versioni sottili, ma eseguito solo nelle versioni specificate. Vedi sotto:

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 

Il secondo modo è per le classi che devono essere istanziati tramite "Nuovo" e non esistono neppure nelle vecchie versioni. Non sarà eseguito in questo problema con Excel, ma io vi darò una sveltina demo in modo da poter vedere quello che voglio dire:

Immaginate che si voleva fare File IO, e per qualche strana ragione non tutti i computer aveva la Microsoft Scripting Runtime su di loro. Ma per qualche strana ragione altrettanto si voleva assicurarsi che è stato utilizzato ogni volta che era disponibile. Se impostare un riferimento ad esso e utilizzare l'associazione anticipata nel codice, il codice non viene compilato su sistemi che non hanno il file. Quindi utilizzare l'associazione tardiva, invece:

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

C'è una lista completa di tutte le aggiunte e le modifiche al modello a oggetti di Excel dal 2003:
http://msdn.microsoft.com/en-us/library/bb149069. aspx Per i cambiamenti tra il 1997 e il 2000 andare qui:
http://msdn.microsoft.com/en-us /library/aa140068(office.10).aspx

Altri suggerimenti

Sì, è possibile fare la compilazione condizionale in Excel VBA. Di seguito una breve risorse e qualche esempio di codice: Compilazione Condizionale

#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

Puoi pubblicare le linee offensive di codice?

Se è una costante come vbYes o xlFileFormat o quant'altro, utilizzare il valore numerico corrispondente.

Show me quello che hai, vedrò se riesco a refactoring.

Bill

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top