Caractéristiques cachées de VBA
Quelles caractéristiques de la langue VBA sont soit mal documentées, soit tout simplement pas souvent utilisées?
16 réponses
cette astuce ne fonctionne que dans Access VBA, Excel et d'autres ne le permettent pas. Mais vous pouvez faire un Module standard caché du navigateur d'objet en préfixant le nom du Module avec un underscore. Le module ne sera alors visible que si vous changez le navigateur d'objet pour afficher les objets cachés.
ce truc fonctionne avec Enums dans toutes les versions VB6 de VBA. Vous pouvez créer un membre caché d'un Enum en encliquetant son nom entre parenthèses, puis en le préfixant avec un underscore. 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 les cellules en les mettant entre parenthèses, les crochets fonctionnent aussi comme une évaluer la commande 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 la 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
Octal Et Hexadécimal Littéraux sont en fait non signé
Public Sub Example()
Debug.Print &H8000
Debug.Print &O100000
End Sub
comme mentionné, en passant une variable entre parenthèses 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 assigner une chaîne de caractères directement dans un tableau d'octets et vice-versa:
Public Sub Example()
Dim myString As String
Dim myBytArr() As Byte
myBytArr = "I am a string."
myString = myBytArr
MsgBox myString
End Sub
"Mi" est également un opérateur. En l'utilisant, vous réécrivez des parties spécifiques de cordes sans la concaténation de cordes 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 y a une caractéristique importante mais presque toujours manquée de L'énoncé Mid (). C'est là que Mid() apparaît du côté gauche d'une tâche par opposition à la fonction Mid() qui apparaît du côté droit ou dans une expression.
La règle est que, si la si la chaîne de caractères n'est pas une chaîne littérale, et c'est la seule référence à la chaîne de caractères et la longueur du segment inséré correspond à la longueur du segment remplacée, la chaîne sera traitée comme mutables pour l'opération.
ça veut dire Quoi? Cela signifie que si vous construisez un grand rapport ou une liste énorme de chaînes en une seule valeur de chaîne, alors l'exploitation de cela rendra votre traitement de chaîne beaucoup plus rapide.
Voici une classe simple qui en bénéficie. Il donne à votre VBA la même capacité de 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 en voici un exemple sur la façon d'utiliser it:
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 caractéristique cachée. Les gens que je connais qui utilisent des produits de bureau depuis des années n'ont aucune idée que c'est même une partie de la suite.
j'ai posté ceci sur plusieurs questions ici, mais le navigateur objet est mon arme secrète. Si je dois coder quelque chose de vraiment rapide ninja, mais ne suis pas familier avec la dll, le navigateur objet sauve ma vie. Il est beaucoup plus facile d'apprendre les structures de classe que MSDN.
la fenêtre locale est idéal pour le débogage. Mettez une pause dans votre code et il vous montrera toutes les variables, leurs noms, et leurs valeurs et types courants dans l'espace de noms courant.
et qui pourrait oublier notre bon ami fenêtre immédiate? Non seulement C'est génial pour Debug.Imprimer sortie standard, mais vous pouvez entrer des commandes ainsi. Vous voulez savoir ce qu'est VariableX?
?VariableX
besoin de savoir quelle couleur est cette cellule?
?Application.ActiveCell.Interior.Color
en fait toutes ces fenêtres sont de grands outils pour être productif avec VBA.
ce n'est pas une fonctionnalité, mais une chose que j'ai vu de travers tant de fois dans VBA (et VB6): La Parenthèse ajoutée sur les appels de méthode où elle va changer 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
- bien qu'il soit "de base", vous pouvez utiliser des classes OOP et des objets
- vous pouvez faire des appels API
peut-être que les fonctionnalités les moins documentées de VBA sont celles que vous ne pouvez exposer qu'en sélectionnant" Afficher les membres cachés " sur le navigateur objet VBA. Les membres cachés sont les fonctions qui sont dans VBA, mais qui ne sont pas supportées. Vous pouvez les utiliser, mais microsoft pourrait les éliminer à tout moment. Aucun d'eux n'a de toute documentation fournie, mais vous pouvez trouver sur le web. Probablement le plus parlé de ces caractéristiques cachées fournit l'accès aux pointeurs dans VBA. Pour un bon article, vérifier sortie; pas si léger - Shlwapi.dll
documentée, mais peut-être plus obscure (dans excel de toute façon) utilise ExecuteExcel4Macro pour accéder à un espace de noms caché 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 est pratiquement sans valeur sans eux!
fait référence à L'exécution du script Microsoft, utilisez Scripting.Dictionary
pour toute tâche suffisamment compliquée, et vivez heureux pour toujours.
L'exécution du script vous donne aussi le FileSystemObject, qui est également fortement recommandé.
commence ici, puis creuse un peu...
http://msdn.microsoft.com/en-us/library/aa164509%28office.10%29.aspx
taper VBA.
fera apparaître une liste intellisense de toutes les fonctions et constantes intégrées.
avec un peu de travail, vous pouvez itérer sur les 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 collecte 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
- Sauvegardez 4 touches entières en tapant
debug.? xxx
au lieu dedebug.print xxx
. - Crash-il en ajoutant:
enum foo: me=0: end enum
vers le haut d'un module contenant tout autre code.
supporte les versions localisées, qui (au moins au siècle précédent) supportent les expressions utilisant des valeurs localisées. Comme Pravda pour True et Fałszywy (pas trop sûr, mais au moins il a le L drôle) pour False En polonais... En fait, la version anglaise serait capable de lire des macros dans n'importe quelle langue, et convertir à la volée. D'autres versions localisées ne le supporteraient pas.
échec.
le modèle d'objet VBE (Visual Basic Extensibility) est une caractéristique moins connue et/ou sous-utilisée. Il vous permet d'écrire du code VBA pour manipuler le code VBA, les modules et les projets. J'ai écrit une fois un projet Excel qui assemblerait D'autres projets Excel à partir d'un groupe de fichiers de modules.
le modèle d'objet fonctionne aussi à partir de VBScript et HTAs. J'ai écrit un HTA à un moment donné pour m'aider à garder la trace d'un grand nombre de Word, Excel et des projets D'accès. De nombreux projets utilisez des modules de code communs, et il était facile pour les modules de "croître" dans un système et ensuite besoin d'être migré vers d'autres systèmes. Mon HTA me permettrait d'exporter tous les modules dans un projet, de les comparer aux versions dans un dossier commun et de fusionner les routines mises à jour (en utilisant BeyondCompare), puis de réimporter les modules mis à jour.
le modèle d'objet VBE fonctionne un peu différemment entre Word, Excel et Access, et ne fonctionne malheureusement pas avec Outlook du tout, mais fournit toujours un grand capacité de gérer le code.
IsDate("13.50")
retourne True
mais IsDate("12.25.2010")
retourne False
c'est parce que IsDate
pourrait être plus précisément appelé IsDateTime
. Et parce que la période ( .
) est traitée comme un séparateur de temps et non un séparateur de date. Voir ici pour une explication complète .
VBA prend en charge les opérateurs bitwise pour comparer les chiffres binaires (bits) de deux valeurs. Par exemple, l'expression 4 et 7 évalue les valeurs de bits de 4 (0100) et 7 (0111) et renvoie 4 (le bit qui est activé dans les deux nombres.) De même, l'expression 4 ou 8 évalue les valeurs de bits dans 4 (0100) et 8 (1000) et renvoie 12 (1100), c'est-à-dire les bits où l'un ou l'autre est vrai.
malheureusement, les opérateurs bitwise ont les mêmes noms à la comparaison logique opérateurs: Et, 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 et 4) Ceci renvoie zéro, puisqu'il n'y a pas de bits en commun entre 2 (0010) et 4 (0100).
cette caractéristique existe probablement pour rétrocompatibilité. Ou pour écrire un code spaghetti désespérément obscurci. Votre sélection.