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?

29
demandé sur guillermooo 2009-07-01 23:21:14

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
32
répondu Oorang 2010-08-23 14:50:41

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
18
répondu Swanny 2010-04-12 13:58:55

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.

15
répondu mandroid 2009-07-01 21:45:09

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
13
répondu Dirk Vollmar 2009-07-01 19:39:35
"151900920 Des Fonctionnalités Cachées

  1. bien qu'il soit "de base", vous pouvez utiliser des classes OOP et des objets
  2. vous pouvez faire des appels API
7
répondu Raj More 2009-07-01 19:30:25

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.

7
répondu DaveParillo 2009-09-02 20:46:19

vous pouvez implémenter des interfaces avec le mot-clé Implements .

6
répondu guillermooo 2009-07-01 19:37:12

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

6
répondu eksortso 2010-03-18 04:00:09

taper VBA. fera apparaître une liste intellisense de toutes les fonctions et constantes intégrées.

5
répondu CtrlDot 2010-08-23 14:33:06

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
4
répondu guillermooo 2009-07-01 20:09:56
  • Sauvegardez 4 touches entières en tapant debug.? xxx au lieu de debug.print xxx .
  • Crash-il en ajoutant: enum foo: me=0: end enum vers le haut d'un module contenant tout autre code.
4
répondu Alex K. 2010-04-12 14:06:07

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.

3
répondu Arjan 2009-07-01 19:36:23

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.

2
répondu Todd 2009-07-09 22:29:31

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 .

2
répondu mwolfe02 2017-05-23 12:26:00

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).

1
répondu ph mrnt 2010-03-29 21:10:46

Deftype États

cette caractéristique existe probablement pour rétrocompatibilité. Ou pour écrire un code spaghetti désespérément obscurci. Votre sélection.

0
répondu mwolfe02 2011-04-05 18:27:51