Скрытые возможности VBA

matches(); не буферизует, а find() - буферы. find() сначала выполняет поиск в конце строки, индексирует результат и возвращает логическое значение и соответствующий индекс.

Вот почему, когда у вас есть такой код, как

1:Pattern.compile("[a-z]");

2:Pattern.matcher("0a1b1c3d4");

3:int count = 0;

4:while(matcher.find()){

5:count++: }

В 4: механизм регулярных выражений с использованием структуры шаблонов будет читать весь ваш код (индекс для индексации, как указано regex[single character], чтобы найти хотя бы одно совпадение. Если такое совпадение найдено, оно будет проиндексировано, тогда цикл будет выполняться на основе индексированного результата else, если он не выполнил вычисления, как matches(); Оператор while никогда не будет выполняться, так как первый символ совпадающей строки не является алфавитом.

29
задан 3 revs, 3 users 50% 18 December 2009 в 07:44
поделиться

14 ответов

  • Сохраните 4 полных нажатия клавиш, набрав debug.? xxx вместо debug.print xxx.
  • Сбой, добавив: enum foo: me=0: end enum в начало модуля, содержащего любой другой код.
4
ответ дан Alex K. 18 December 2009 в 07:44
поделиться

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

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

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

2
ответ дан Todd 18 December 2009 в 07:44
поделиться

Этот трюк работает только в 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

Octal & amp; Шестнадцатеричные литералы на самом деле являются беззнаковыми типами, они оба будут выводить -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

«Mid» также является оператором. Используя его, вы перезаписываете определенные части строк без общеизвестно медленной конкатенации строк 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
ответ дан 3 revs 18 December 2009 в 07:44
поделиться

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

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

7
ответ дан DaveParillo 18 December 2009 в 07:44
поделиться

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

6
ответ дан guillermooo 18 December 2009 в 07:44
поделиться

Если вы наберете VBA., появится список всех встроенных функций и констант.

5
ответ дан CtrlDot 18 December 2009 в 07:44
поделиться

Это не функция, а то, что я много раз видел неправильно в VBA (и VB6): в вызовы методов добавлены скобки, где это изменит семантику:

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 18 December 2009 в 07:44
поделиться

Есть важная, но почти всегда пропущенная особенность оператора 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'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

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

  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
ответ дан 2 revs 18 December 2009 в 07:44
поделиться

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

' 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
4
ответ дан 28 November 2019 в 00:36
поделиться

Поддержка локализованных версий, которые (по крайней мере, в прошлом веке) поддерживали выражения с использованием локализованных значений. Например, Pravda для True и Fałszywy (не совсем уверен, но, по крайней мере, у него был забавный L) для False на польском ... На самом деле английская версия могла читать макросы на любом языке и конвертировать на лету. Однако другие локализованные версии не справятся с этим.

ОТКАЗ.

3
ответ дан 28 November 2019 в 00:36
поделиться

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

  1. Хотя это «Базовый», вы можете использовать ООП - классы и объекты
  2. Вы можете выполнять вызовы API
7
ответ дан 28 November 2019 в 00:36
поделиться

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

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

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

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

15
ответ дан 28 November 2019 в 00:36
поделиться

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

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

Scripting Runtime также предоставляет вам FileSystemObject, который также очень рекомендуется.

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

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

6
ответ дан 28 November 2019 в 00:36
поделиться

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

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

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

1
ответ дан 28 November 2019 в 00:36
поделиться