Quelles fonctionnalités du langage VBA sont soit mal documentées, soit simplement peu utilisées?
Cette astuce ne fonctionne que dans Access VBA, Excel et d'autres ne le permettront pas. Cependant, vous pouvez masquer un module standard à l'explorateur d'objets en préfixant son nom par un trait de soulignement. Le module ne sera alors visible que si vous modifiez le navigateur d'objets pour afficher les objets cachés.
Cette astuce fonctionne avec Enums dans toutes les versions de VBA basées sur vb6. Vous pouvez créer un membre caché d'un Enum en mettant son nom entre parenthèses, puis en le préfixant d'un trait de soulignement. Exemple:
Public Enum MyEnum
meDefault = 0
meThing1 = 1
meThing2 = 2
meThing3 = 3
[_Min] = meDefault
[_Max] = meThing3
End Enum
Public Function IsValidOption(ByVal myOption As MyEnum) As Boolean
If myOption >= MyEnum.[_Min] Then IsValidOption myOption <= MyEnum.[_Max]
End Function
Dans Excel-VBA, vous pouvez référencer des cellules en les mettant entre crochets. Ces crochets fonctionnent également comme une commande evaluer vous permettant d’évaluer la syntaxe de la formule:
Public Sub Example()
[A1] = "Foo"
MsgBox [VLOOKUP(A1,A1,1,0)]
End Sub
Vous pouvez également transmettre des données brutes sans utiliser MemCopy (RtlMoveMemory) en combinant LSet avec des types définis par l'utilisateur de même taille:
Public Sub Example()
Dim b() As Byte
b = LongToByteArray(8675309)
MsgBox b(1)
End Sub
Private Function LongToByteArray(ByVal value As Long) As Byte()
Dim tl As TypedLong
Dim bl As ByteLong
tl.value = value
LSet bl = tl
LongToByteArray = bl.value
End Function
Les littéraux octaux et hexadécimaux sont en fait des types non signés. Ils produiront tous les deux -32768:
Public Sub Example()
Debug.Print &H8000
Debug.Print &O100000
End Sub
Comme mentionné précédemment, le fait de passer une variable entre parenthèses le fait passer à ByVal:
Sub PredictTheOutput()
Dim i&, j&, k&
i = 10: j = i: k = i
MySub (i)
MySub j
MySub k + 20
MsgBox Join(Array(i, j, k), vbNewLine), vbQuestion, "Did You Get It Right?"
End Sub
Public Sub MySub(ByRef foo As Long)
foo = 5
End Sub
Vous pouvez affecter une chaîne directement dans un tableau d'octets et inversement:
Public Sub Example()
Dim myString As String
Dim myBytArr() As Byte
myBytArr = "I am a string."
myString = myBytArr
MsgBox myString
End Sub
"Mid" est aussi un opérateur. En l’utilisant, vous écrasez des portions spécifiques de chaînes sans la concaténation de chaînes notoirement lente de VBA:
Public Sub Example1()
''// This takes about 47% of time Example2 does:
Dim myString As String
myString = "I liek pie."
Mid(myString, 5, 2) = "ke"
Mid(myString, 11, 1) = "!"
MsgBox myString
End Sub
Public Sub Example2()
Dim myString As String
myString = "I liek pie."
myString = "I li" & "ke" & " pie" & "!"
MsgBox myString
End Sub
Il existe une caractéristique importante, mais presque toujours oubliée, de la déclaration Mid (). C'est là que Mid () apparaît à gauche d'une affectation, par opposition à la fonction Mid () qui apparaît à droite ou dans une expression.
La règle est la suivante: si la chaîne cible n'est pas un littéral et qu'il s'agit de la seule référence à la chaîne cible et que la longueur du segment inséré correspond à la longueur du segment remplacé, la chaîne sera traitée comme mutable pour l'opération.
Qu'est-ce que ça veut dire? Cela signifie que si vous construisez un rapport volumineux ou une longue liste de chaînes en une seule valeur de chaîne, son exploitation accélérera le traitement de votre chaîne.
Voici un cours simple qui en profite. Cela donne à votre VBA la même capacité que StringBuilder que celle de .Net.
' Class: StringBuilder
Option Explicit
Private Const initialLength As Long = 32
Private totalLength As Long ' Length of the buffer
Private curLength As Long ' Length of the string value within the buffer
Private buffer As String ' The buffer
Private Sub Class_Initialize()
' We set the buffer up to it's initial size and the string value ""
totalLength = initialLength
buffer = Space(totalLength)
curLength = 0
End Sub
Public Sub Append(Text As String)
Dim incLen As Long ' The length that the value will be increased by
Dim newLen As Long ' The length of the value after being appended
incLen = Len(Text)
newLen = curLength + incLen
' Will the new value fit in the remaining free space within the current buffer
If newLen <= totalLength Then
' Buffer has room so just insert the new value
Mid(buffer, curLength + 1, incLen) = Text
Else
' Buffer does not have enough room so
' first calculate the new buffer size by doubling until its big enough
' then build the new buffer
While totalLength < newLen
totalLength = totalLength + totalLength
Wend
buffer = Left(buffer, curLength) & Text & Space(totalLength - newLen)
End If
curLength = newLen
End Sub
Public Property Get Length() As Integer
Length = curLength
End Property
Public Property Get Text() As String
Text = Left(buffer, curLength)
End Property
Public Sub Clear()
totalLength = initialLength
buffer = Space(totalLength)
curLength = 0
End Sub
Et voici un exemple d'utilisation:
Dim i As Long
Dim sb As StringBuilder
Dim result As String
Set sb = New StringBuilder
For i = 1 to 100000
sb.Append CStr( i)
Next i
result = sb.Text
VBA lui-même semble être une fonctionnalité cachée. Les personnes que je connais et qui utilisent des produits Office depuis des années n’ignorent même pas que cela fait même partie de la suite.
J'ai posté ceci sur plusieurs questions ici, mais le navigateur d'objets est mon arme secrète. Si j'ai besoin de code ninja quelque chose de très rapide, mais ne suis pas familier avec les dll, Object Browser me sauve la vie. Il est beaucoup plus facile d’apprendre les structures de classe que MSDN.
La fenêtre Locals est également idéale pour le débogage. Mettez une pause dans votre code et il vous montrera toutes les variables, leurs noms, ainsi que leurs valeurs et types actuels dans l’espace de noms actuel.
Et qui pourrait oublier notre bon ami Immediate Window? Non seulement c'est bon pour la sortie standard Debug.Print, mais vous pouvez aussi y entrer des commandes. Besoin de savoir ce qu'est VariableX?
?VariableX
Besoin de savoir de quelle couleur est cette cellule?
?Application.ActiveCell.Interior.Color
En fait, toutes ces fenêtres sont d'excellents outils pour être productif avec VBA.
Ce n'est pas une fonctionnalité, mais une chose que j'ai souvent vue de travers dans VBA (et VB6): une parenthèse a été ajoutée aux appels de méthodes, ce qui changerait la sémantique
Sub Foo()
Dim str As String
str = "Hello"
Bar (str)
Debug.Print str 'prints "Hello" because str is evaluated and a copy is passed
Bar str 'or Call Bar(str)
Debug.Print str 'prints "Hello World"
End Sub
Sub Bar(ByRef param As String)
param = param + " World"
End Sub
Caractéristiques cachées
Les fonctionnalités les moins documentées de VBA sont probablement celles que vous ne pouvez exposer qu'en sélectionnant "Afficher les membres cachés" dans le navigateur d'objets VBA. Les membres cachés sont les fonctions de VBA, mais non prises en charge. Vous pouvez les utiliser, mais Microsoft peut les éliminer à tout moment. Aucun d'entre eux n'a de documentation fournie, mais vous pouvez en trouver sur le Web. Peut-être le plus parlé de ces fonctionnalités cachées fournit un accès aux pointeurs dans VBA. Pour une rédaction décente, consultez; Pas si léger - Shlwapi.dll
Documenté, mais peut-être plus obscur (dans Excel de toute façon), utilisez ExecuteExcel4Macro pour accéder à un espace de nom global masqué qui appartient à l'ensemble de l'instance d'application Excel, par opposition à un classeur spécifique.
Vous pouvez implémenter des interfaces avec le mot clé Implements
.
Dictionnaires. VBA ne vaut pratiquement rien sans eux!
Référencez Microsoft Scripting Runtime, utilisez Scripting.Dictionary
pour toute tâche suffisamment compliquée et vivez heureux pour toujours.
Le Scripting Runtime vous fournit également le FileSystemObject, qui est également hautement recommandé.
Commencez ici, puis creusez un peu ...
http://msdn.Microsoft.com/en-us/library/aa164509%28office.10%29.aspx
Taper VBA.
affichera une liste intellisense de toutes les fonctions et constantes intégrées.
Avec un peu de travail, vous pouvez parcourir des collections personnalisées comme ceci:
' Write some text in Word first.'
Sub test()
Dim c As New clsMyCollection
c.AddItems ActiveDocument.Characters(1), _
ActiveDocument.Characters(2), _
ActiveDocument.Characters(3), _
ActiveDocument.Characters(4)
Dim el As Range
For Each el In c
Debug.Print el.Text
Next
Set c = Nothing
End Sub
Votre code de collection personnalisé (dans une classe appelée clsMyCollection
):
Option Explicit
Dim m_myCollection As Collection
Public Property Get NewEnum() As IUnknown
' This property allows you to enumerate
' this collection with the For...Each syntax
' Put the following line in the exported module
' file (.cls)!'
'Attribute NewEnum.VB_UserMemId = -4
Set NewEnum = m_myCollection.[_NewEnum]
End Property
Public Sub AddItems(ParamArray items() As Variant)
Dim i As Variant
On Error Resume Next
For Each i In items
m_myCollection.Add i
Next
On Error GoTo 0
End Sub
Private Sub Class_Initialize()
Set m_myCollection = New Collection
End Sub
debug.? xxx
au lieu de debug.print xxx
.enum foo: me=0: end enum
en haut d'un module contenant un autre code.Prise en charge des versions localisées, qui (du moins au siècle précédent) prenaient en charge les expressions utilisant des valeurs localisées. Comme Pravda pour True et Fałszywy (pas très sûr, mais au moins, il avait le drôle L) pour False en polonais ... En fait, la version anglaise pourrait lire des macros dans n'importe quelle langue et convertir à la volée. Les autres versions localisées ne gèreraient pas cela.
ÉCHOUER.
IsDate("13.50")
renvoie True
mais IsDate("12.25.2010")
renvoie False
En effet, IsDate
pourrait être nommé plus précisément IsDateTime
. Et parce que la période (.
) est traitée comme un séparateur d'heure et non comme un séparateur de date. Voir ici pour une explication complète .
Le modèle objet VBE (Visual Basic Extensibility) est une fonctionnalité moins connue et/ou sous-utilisée. Il vous permet d’écrire du code VBA pour manipuler du code, des modules et des projets VBA. J'ai déjà écrit un projet Excel qui assemblerait d'autres projets Excel à partir d'un groupe de fichiers de module.
Le modèle objet fonctionne également à partir de VBScript et de HTA. J'ai écrit un HTA à un moment donné pour m'aider à suivre un grand nombre de projets Word, Excel et Access. De nombreux projets utilisaient des modules de code communs, et il était facile pour les modules de "se développer" sur un système et de devoir ensuite migrer vers d'autres systèmes. Mon HTA me permettait d'exporter tous les modules d'un projet, de les comparer aux versions d'un dossier commun, de fusionner les routines mises à jour (avec BeyondCompare), puis de réimporter les modules mis à jour.
Le modèle d'objet VBE fonctionne légèrement différemment entre Word, Excel et Access. Malheureusement, il ne fonctionne pas du tout avec Outlook, mais offre néanmoins une excellente capacité de gestion du code.
VBA prend en charge les opérateurs au niveau des bits pour comparer les chiffres binaires (bits) de deux valeurs. Par exemple, l'expression 4 And 7 évalue les valeurs de bits de 4 (0100) et 7 (0111) et renvoie 4 (le bit activé dans les deux chiffres). ) et 8 (1000) et renvoie 12 (1100), c’est-à-dire les bits où l’un ou l’autre est vrai.
Malheureusement, les opérateurs de bits ont les mêmes noms dans les opérateurs de comparaison logique: And, Eqv, Imp, Not, Or et Xor. Cela peut conduire à des ambiguïtés, voire à des résultats contradictoires.
Par exemple, ouvrez la fenêtre Immédiate (Ctrl + G) et entrez: ? (2 And 4) Cela renvoie zéro, car il n'y a pas de bits en commun entre 2 (0010) et 4 (0100).
Cette fonctionnalité existe probablement pour assurer la compatibilité ascendante. Ou pour écrire du code spaghetti désespérément obfusqué. Votre choix.