wake-up-neo.com

Versteckte Funktionen von VBA

Welche Merkmale der VBA-Sprache sind entweder schlecht dokumentiert oder werden nur selten verwendet?

29
guillermooo

Dieser Trick funktioniert nur in Access VBA, Excel und anderen nicht. Sie können ein Standardmodul jedoch aus dem Objektbrowser ausblenden, indem Sie dem Modulnamen einen Unterstrich voranstellen. Das Modul ist nur dann sichtbar, wenn Sie den Objektbrowser so ändern, dass verborgene Objekte angezeigt werden. 

Dieser Trick funktioniert mit Enums in allen Vb6-basierten VBA-Versionen. Sie können ein ausgeblendetes Mitglied einer Enumeration erstellen, indem Sie den Namen in Klammern einschließen und diesem einen Unterstrich voranstellen. Beispiel:

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

In Excel-VBA können Sie Zellen referenzieren, indem Sie sie in Klammern einschließen. Die Klammern fungieren auch als evalu-Befehl , mit dem Sie die Formelsyntax auswerten können:

Public Sub Example()
    [A1] = "Foo"
    MsgBox [VLOOKUP(A1,A1,1,0)]
End Sub

Sie können auch Rohdaten ohne MemCopy (RtlMoveMemory) weitergeben, indem Sie LSet mit benutzerdefinierten Typen derselben Größe kombinieren:

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

Oktal- und Hex-Literale sind eigentlich vorzeichenlose Typen, die beide -32768 ausgeben:

Public Sub Example()
    Debug.Print &H8000
    Debug.Print &O100000
End Sub

Wie bereits erwähnt, führt das Übergeben einer Variablen in Klammern dazu, dass ByVal übergeben wird:

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

Sie können einen String direkt einem Byte-Array zuweisen und umgekehrt:

Public Sub Example()
    Dim myString As String
    Dim myBytArr() As Byte
    myBytArr = "I am a string."
    myString = myBytArr
    MsgBox myString
End Sub

"Mid" ist auch ein Operator. Mit ihr überschreiben Sie bestimmte Teile von Strings ohne notorisch langsame String-Verkettung von 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
Oorang

Es gibt ein wichtiges, aber fast immer verfehltes Feature der Mid () - Anweisung. Hier steht Mid () auf der linken Seite einer Zuweisung im Gegensatz zu der Mid () - Funktion, die auf der rechten Seite oder in einem Ausdruck angezeigt wird.

Die Regel lautet, wenn der Zielstring kein Stringliteral ist und dies die einzige Referenz auf den Zielstring ist und die Länge des Segmentes der Länge des zu ersetzenden Segments entspricht, wird die Zeichenfolge als behandelt für die Operation veränderbar. 

Was bedeutet das? Wenn Sie einen umfangreichen Bericht oder eine große Liste von Zeichenfolgen in einem einzigen Zeichenfolgenwert zusammenstellen, bedeutet dies, dass die Verarbeitung dieser Zeichenfolgen wesentlich schneller wird.

Hier ist eine einfache Klasse, die davon profitiert. Damit erhält Ihr VBA die gleiche StringBuilder-Funktion wie .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

Und hier ist ein Beispiel, wie man es benutzt:

  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
Swanny

VBA selbst scheint eine versteckte Funktion zu sein. Leute, die ich kenne, die Office-Produkte seit Jahren verwenden, haben keine Ahnung, dass es sogar ein Teil der Suite ist.

Ich habe dies zu mehreren Fragen hier gepostet, aber der Objektbrowser ist meine Geheimwaffe. Wenn ich etwas sehr schnell Ninja-Code programmieren muss, aber nicht mit den DLLs vertraut bin, rettet Object Browser mein Leben. Das Erlernen der Klassenstrukturen ist damit viel einfacher als bei MSDN.

Das Einheimische-Fenster eignet sich auch hervorragend zum Debuggen. Machen Sie eine Pause in Ihrem Code und es werden Ihnen alle Variablen, ihre Namen sowie ihre aktuellen Werte und Typen im aktuellen Namespace angezeigt.

Und wer könnte unser guter Freund Immediate Window vergessen? Es ist nicht nur für die Debug.Print-Standardausgabe großartig, sondern Sie können auch Befehle eingeben. Sie müssen wissen, was VariableX ist?

?VariableX

Müssen Sie wissen, welche Farbe diese Zelle hat?

?Application.ActiveCell.Interior.Color

In der Tat sind all diese Fenster großartige Werkzeuge, um mit VBA produktiv zu sein.

15
mandroid

Es ist keine Funktion, aber etwas, das ich in VBA (und VB6) so oft falsch gesehen habe: Klammern wurden bei Methodenaufrufen hinzugefügt, bei denen die Semantik geändert wird:

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
Dirk Vollmar

Versteckte Funktionen

  1. Obwohl es "Basic" ist, können Sie OOP - Klassen und Objekte verwenden
  2. Sie können API-Aufrufe durchführen
7
Raj More

Möglicherweise sind die am wenigsten dokumentierten Funktionen in VBA diejenigen, die Sie nur durch Auswählen von "Ausgeblendete Elemente anzeigen" im VBA-Objektbrowser anzeigen können. Verborgene Member sind Funktionen, die in VBA enthalten sind, aber nicht unterstützt werden. Sie können sie verwenden, aber Microsoft kann sie jederzeit entfernen. Keiner von ihnen hat eine Dokumentation, aber Sie können sie im Internet finden. Möglicherweise bieten die am meisten besprochenen versteckten Funktionen den Zugriff auf Zeiger in VBA. Für ein anständiges Schreiben, check out; Nicht so leicht - Shlwapi.dll

Dokumentiert, aber möglicherweise (in Excel jedenfalls etwas unklarer) verwendet ExecuteExcel4Macro für den Zugriff auf einen versteckten globalen Namespace, der zur gesamten Excel-Anwendungsinstanz gehört, im Gegensatz zu einer bestimmten Arbeitsmappe.

7
DaveParillo

Sie können Schnittstellen mit dem Schlüsselwort Implements implementieren.

6
guillermooo

Wörterbücher. VBA ist ohne sie praktisch wertlos!

Verweisen Sie auf die Microsoft Scripting Runtime, verwenden Sie Scripting.Dictionary für jede ausreichend komplizierte Aufgabe und leben Sie ohne Ende glücklich.

Die Scripting Runtime enthält auch das FileSystemObject, das ebenfalls sehr zu empfehlen ist.

Beginnen Sie hier, dann graben Sie ein bisschen ...

http://msdn.Microsoft.com/de-de/library/aa164509%28office.10%29.aspx

6
eksortso

Durch Eingabe von VBA. wird eine Liste aller eingebauten Funktionen und Konstanten angezeigt.

5
CtrlDot

Mit ein wenig Arbeit können Sie benutzerdefinierte Sammlungen wie folgt durchlaufen:

' 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

Ihr benutzerdefinierter Erfassungscode (in einer Klasse mit dem Namen 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
guillermooo
  • Speichern Sie 4 ganze Tastenanschläge, indem Sie debug.? xxx anstelle von debug.print xxx eingeben.
  • Stürzen Sie es ab, indem Sie enum foo: me=0: end enum am Anfang eines Moduls hinzufügen, das anderen Code enthält.
4
Alex K.

Unterstützung für lokalisierte Versionen, die (zumindest im vorigen Jahrhundert) Ausdrücke mit lokalisierten Werten unterstützten. Wie Pravda für True und Fałszywy (nicht zu sicher, aber zumindest hatte es das lustige L) für False auf Polnisch ... Eigentlich könnte die englische Version Makros in jeder Sprache lesen und spontan konvertieren. Andere lokalisierte Versionen würden das jedoch nicht verarbeiten. 

SCHEITERN.

3
Arjan

IsDate("13.50") gibt True zurück, aber IsDate("12.25.2010") gibt False zurück

Dies liegt daran, dass IsDate genauer IsDateTime heißen könnte. Und weil der Punkt (.) als Zeittrennzeichen und nicht als Datumstrennzeichen behandelt wird. Siehe hier für eine vollständige Erklärung

2
mwolfe02

Das VBE-Objektmodell (Visual Basic Extensibility) ist ein weniger bekanntes und/oder wenig genutztes Feature. Sie können VBA-Code schreiben, um VBA-Code, Module und Projekte zu bearbeiten. Ich habe einmal ein Excel-Projekt geschrieben, das andere Excel-Projekte aus einer Gruppe von Moduldateien zusammenstellen würde. 

Das Objektmodell funktioniert auch mit VBScript und HTAs. Ich habe einmal eine HTA geschrieben, um mir zu helfen, eine große Anzahl von Word-, Excel- und Access-Projekten zu verfolgen. Viele der Projekte verwendeten gemeinsame Codemodule, und Module konnten leicht in einem System "wachsen" und mussten dann auf andere Systeme migriert werden. Mit meiner HTA könnte ich alle Module in einem Projekt exportieren, mit Versionen in einem gemeinsamen Ordner vergleichen und aktualisierte Routinen zusammenführen (mithilfe von BeyondCompare) und die aktualisierten Module anschließend erneut importieren.

Das VBE-Objektmodell unterscheidet sich geringfügig zwischen Word, Excel und Access und funktioniert leider nicht mit Outlook, bietet aber dennoch eine hervorragende Möglichkeit zum Verwalten von Code.

2
Todd

VBA unterstützt bitweise Operatoren zum Vergleich der Binärziffern (Bits) zweier Werte. Beispielsweise wertet der Ausdruck 4 und 7 die Bitwerte von 4 (0100) und 7 (0111) aus und gibt 4 zurück (das in beiden Zahlen aktivierte Bit). Ähnlich wertet der Ausdruck 4 oder 8 die Bitwerte in 4 (0100) aus ) und 8 (1000) und gibt 12 (1100) zurück, dh die Bits, bei denen eines der beiden wahr ist.

Leider haben die bitweisen Operatoren bei den logischen Vergleichsoperatoren die gleichen Namen: And, Eqv, Imp, Not, Or und Xor. Dies kann zu Mehrdeutigkeiten und sogar widersprüchlichen Ergebnissen führen.

Öffnen Sie beispielsweise das Direktfenster (Strg + G) und geben Sie Folgendes ein: ? (2 und 4) Dies gibt Null zurück, da zwischen 2 (0010) und 4 (0100) keine gemeinsamen Bits vorhanden sind.

1
ph mrnt

Deftype-Anweisungen

Diese Funktion besteht vermutlich aus Gründen der Rückwärtskompatibilität. Oder um hoffnungslos verschleierten Spaghetti-Code zu schreiben. Deine Wahl.

0
mwolfe02