Какие особенности языка VBA либо плохо документированы, либо просто не часто используются?
Скрытые особенности VBA
Ответ 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
Эта функция существует, предположительно, для обратной совместимости. Или написать безнадежно обфусканный код спагетти. Ваш выбор.