Подтвердить что ты не робот

Скрытые особенности VBA

Какие особенности языка VBA либо плохо документированы, либо просто не часто используются?

4b9b3361

Ответ 1

Этот трюк работает только в Access VBA, Excel и других, это не позволит. Но вы можете сделать стандартный модуль скрытым от браузера объектов, префиксное имя модуля с помощью подчеркивания. Модуль будет отображаться только тогда, когда вы измените браузер объектов, чтобы отображать скрытые объекты.

Этот трюк работает с Enums во всех версиях VBA на основе vb6. Вы можете создать скрытый элемент Enum, заключая его в скобки, затем префикс его с подчеркиванием. Пример:

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

В Excel-VBA вы можете ссылаться на ячейки, заключая их в скобки, скобки также функционируют как команда оценки, позволяющая оценить формулу синтаксис:

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

Также вы можете передавать необработанные данные без использования MemCopy (RtlMoveMemory), комбинируя LSet с определенными пользователем типами одного и того же размера:

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

Восьмеричные и шестнадцатеричные литералы на самом деле являются неподписанными типами, они будут выводить -32768:

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

Как уже упоминалось, передача переменной внутри скобок приводит к ее передаче 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

Вы можете назначить строку непосредственно в массив байтов и наоборот:

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

"Середина" также является оператором. Используя его, вы перезаписываете определенные части строк без 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

Ответ 2

Существует важная, но почти всегда пропущенная функция оператора Mid(). Вот где Mid() появляется в левой части задания в отличие от функции Mid(), которая появляется в правой части или в выражении.

Правило заключается в том, что если строка-мишень не является строковым литералом, и это единственная ссылка на целевую строку, а длина вставляемого сегмента соответствует длине заменяемого сегмента, то строка будет быть обработанными как изменяемые для операции.

Что это значит? Это означает, что если вы создаете большой отчет или огромный список строк в одно строковое значение, то использование этого приведет к значительному сокращению вашей строки.

Вот простой класс, который выигрывает от этого. Это дает вашей VBA ту же возможность StringBuilder, что .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 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

И вот пример того, как его использовать:

  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

Ответ 3

Сам VBA кажется скрытой. Люди, которых я знаю, которые использовали продукты Office в течение многих лет, не представляют себе даже часть пакета.

Я разместил это по нескольким вопросам здесь, но обозреватель объектов - это мое секретное оружие. Если мне нужно, чтобы код ниндзя был чем-то реальным быстрым, но я не знаком с dll, Object Browser сохраняет мою жизнь. Это значительно облегчает изучение структур классов, чем MSDN.

Окно Locals отлично подходит для отладки. Поместите паузу в свой код, и он покажет вам все переменные, их имена и их текущие значения и типы в текущем пространстве имен.

И кто мог забыть нашего хорошего друга? Это не только отлично подходит для стандартного вывода Debug.Print, но вы также можете вводить в него команды. Нужно знать, что такое VariableX?

?VariableX

Вам нужно знать, какой цвет имеет эта ячейка?

?Application.ActiveCell.Interior.Color

Фактически все эти окна - отличные инструменты для продуктивности с VBA.

Ответ 4

Это не особенность, но вещь, которую я часто видела в VBA (и VB6): Parenthesis добавлена ​​в вызовы методов, где она изменит семантику:

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

Ответ 5

Скрытые функции

  • Хотя это "Basic", вы можете использовать классы и объекты OOP
  • Вы можете совершать вызовы API

Ответ 6

Возможно, наименее документированные функции в VBA - это те, которые вы можете открыть, выбрав "Показать скрытых членов" в обозревателе объектов VBA. Скрытые члены - это те функции, которые находятся в VBA, но не поддерживаются. Вы можете использовать их, но microsoft может их устранить в любое время. Ни у кого из них нет документации, но вы можете найти ее в Интернете. Возможно, самые обсуждаемые из этих скрытых функций обеспечивают доступ к указателям в VBA. Для достойной записи проверьте; Не так легкий - Shlwapi.dll

Документированный, но, возможно, более неясный (в любом случае) используется ExecuteExcel4Macro для доступа к скрытому глобальному пространству имен, принадлежащему всему экземпляру приложения Excel, в отличие от конкретной книги.

Ответ 7

Вы можете реализовать интерфейсы с ключевым словом Implements.

Ответ 8

Словари. VBA практически бесполезен без них!

Ссылка на Runtime Microsoft Scripting Runtime, используйте Scripting.Dictionary для любой достаточно сложной задачи и живите долго и счастливо.

Сценарий Runtime также предоставляет вам файл FileSystemObject, который также рекомендуется.

Начните здесь, а затем немного окопайтесь...

http://msdn.microsoft.com/en-us/library/aa164509%28office.10%29.aspx

Ответ 9

Ввод VBA. приведет к отображению intellisense всех встроенных функций и констант.

Ответ 10

С небольшой работой вы можете перебирать пользовательские коллекции следующим образом:

' 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

Пользовательский код коллекции (в классе 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

Ответ 11

  • Сохраните 4 нажатия всего цепочки, набрав debug.? xxx вместо debug.print xxx.
  • Выключите его, добавив: enum foo: me=0: end enum в начало модуля, содержащего любой другой код.

Ответ 12

Поддержка локализованных версий, которые (по крайней мере в предыдущем веке) поддерживали выражения с использованием локализованных значений. Как "Правда" для Истины и Фалшиви (не слишком уверенная, но, по крайней мере, у нее была забавная L) для False на польском языке... На самом деле английская версия могла бы читать макросы на любом языке и конвертировать "на лету". Другие локализованные версии не справились бы с этим.

FAIL.

Ответ 13

Объектная модель VBE (Visual Basic Extensibility) является менее известной и/или недоиспользуемой. Он позволяет вам писать код VBA для управления кодом, модулями и проектами VBA. Однажды я написал проект Excel, который собирал другие проекты Excel из группы файлов модулей.

Объектная модель также работает с VBScript и HTAs. Я однажды написал HTA, чтобы помочь мне отслеживать большое количество проектов Word, Excel и Access. Многие из проектов будут использовать общие модули кода, а модули "просто" могут быть "расти" в одной системе и затем должны быть перенесены в другие системы. Мой HTA позволит мне экспортировать все модули в проект, сравнить их с версиями в общей папке и объединить обновленные подпрограммы (используя BeyondCompare), а затем reimport обновленные модули.

Объектная модель VBE работает немного по-разному между Word, Excel и Access и, к сожалению, вообще не работает с Outlook, но все же предоставляет отличные возможности для управления кодом.

Ответ 14

IsDate("13.50") возвращает True, но IsDate("12.25.2010") возвращает False

Это потому, что IsDate можно точнее назвать IsDateTime. И поскольку период (.) рассматривается как разделитель времени, а не разделитель дат. Подробнее см. .

Ответ 15

VBA поддерживает побитовые операторы для сравнения двоичных цифр (бит) двух значений. Например, выражение 4 И 7 оценивает битовые значения 4 (0100) и 7 (0111) и возвращает 4 (бит, который включен в обоих числах). Аналогично, выражение 4 или 8 оценивает битовые значения в 4 (0100 ) и 8 (1000) и возвращает 12 (1100), т.е. биты, где один из них истинен.

К сожалению, побитовые операторы имеют одинаковые имена у операторов логического сравнения: И, Eqv, Imp, Not, Or и Xor. Это может привести к двусмысленности и даже противоречивым результатам.

В качестве примера откройте окно Immediate (Ctrl + G) и введите:   ? (2 и 4) Это возвращает ноль, так как между 2 (0010) и 4 (0100) нет битов.

Ответ 16

Заявления о дефете

Эта функция существует, предположительно, для обратной совместимости. Или написать безнадежно обфусканный код спагетти. Ваш выбор.