Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > Оптимизация VBA-кода > Строковые функции


Автор: Old Bat 30.04.05, 15:58
Используйте LEN() для проверки нулевой длины строк

Сравнение строки с нулем происходит значительно быстрее, чем при сравнении с "". VBA хранит строки в формате BSTR, т.е. в начале каждой строки существует 4 байта, где хранится длина текущей строки. Таким образом, LEN() не вычисляет длину строки, а считывает уже существующее значение. К тому же пустую строку ("") еще надо создать, на что и уходит часть времени.

Для инициализации строк вместо "" используйте константу vbNullString

Когда Вы пишете "MyString = vbNullString"
VBA не создает новую строку, вместо этого он использует свой внутренний указатель на нее, что существенно экономит время.

Не увлекайтесь излишней конкатенацией

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

Используйте IsCharAlphaNumeric вместо ASCII-значений

Если Вам приходится проверять, является ли некоторый символ буквенно-цифровым (то есть входит ли он в диапазон A-Z, a-z, А-Я, а-я, 0-9). – используйте API-функцию IsCharAlphaNumeric. Кроме того, можно воспользоваться еще одной похожей функцией Windows API, IsCharAlpha, определяющей, является ли символ с переданным ей кодом буквой. Дополнительным преимуществом функций Windows API является то, что они интернационализированы. Ведь если вам нужно, чтобы программа работала с текстом, написанным на разных языках, недостаточно сравнить код буквы с границами определенных диапазонов: вы рискуете пропустить те буквы, которые в эти диапазоны не входят. И наконец, функции Windows API работают быстрее функции сравнения кодов.

Можем написать так:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    Const cFirstChar = 65
    Const cLastChar = 90
    Const cFirstDigit = 48
    Const cLastDigit = 57
     
    intC = Asc(UCase(strC))
    If (intC = cFirstChar And _
    intC <= cLastChar) _
    Or (intC >= cFirstDigit And _
    intC <= cLastDigit) Then
      ' Это буква или цифра.
      'Делаем то, что нужно в этом случае.
    End If

А можем так:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    Private Declare Function IsCharAlphaNumeric _
     Lib "user32" Alias "IsCharAlphaNumericA" _
    (ByVal cChar As Byte) As Long
    ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' '
    If IsCharAlphaNumeric(Asc(strC)) Then
     ' Это буква или цифра.
     ' Делаем то, что нужно в этом случае.
    End If


Сравнивайте строки с помощью StrComp,
не преобразуя их к верхнему регистру с помощью UCase


VBA сравнивает строки с учетом опции Option Compare. По умолчанию VBA использует опцию Option Compare Binary, при которой результаты сравнения зависят от регистра символов.В противном случае объявите Option Compare Text в начале модуля.
Если необходимо указать способ сравнения на уровне отдельной процедуры, то используйте функцию StrComp. Она позволяет задать две строки и константу, указывающую, как их сравнивать: vbUseCompareOption (использовать текущую установку Option Compare), vbBinaryCompare (осуществлять сравнение с учетом регистра), vbTextCompare (сравнивать без учета регистра) или vbDatabaseCompare (использовать режим сравнения, заданный для базы данных). Функция StrComp возвращает 0, если строки равны, -1, если первая строка меньше второй, и +1, если первая строка больше второй. Для сравнения двух строк без учета регистра можно написать одну из двух строк кода:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    If UCase(strValuel) = UCase(strValue2) Then

или
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    If (StrCompCstrValuel, strvalue2, vbTextCompare) = 0 Then

Короткие строки быстрее обрабатываются функцией StrComp, однако при существенном увеличении их длины становится практически все равно, каким образом их сравнивать.

Используйте оператор LIKE, а не сравнивайте символы по отдельности

Допустим, требуется проверить значение некой переменной, состоящей из букв и цифр, стоящих в определенной последовательности: например - "W5TGQ". Сделать это можно так: перебрать в цикле все символы строки и проверить каждый на соответствие определенным условиям. Если условия для очередного символа не выполнены, цикл прекращается:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    blnMatch = True
    For j - 1 То 5
     intCh = Asc(Mid$(strTest , j , 1))
     Select Case j
     Case 1, 3, 4, 5
       If (IsCharAlpha(intCh) = 0) Then
        blnMatch = False
       End If
     Case 2
       If (IsCharAlpha(intCh) = 0) Then
        blnMatch = False
       End If
     End Select
     If Not blnMatch Then Exit For
    Next j

Приведенный выше код можно заменить строкой:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    blnMatch = strTest Like "[A-Z]#[A-Z][A-Z][A-Z]"

Здесь "[A-Z]" соответствует любому символу из диапазона от А до Z (для всех языков с латинским алфавитом), а "#" — любой цифре (0-9). И хотя возможности оператора Like ограниченны, иногда он может оказаться весьма полезным.

Пользуйтесь $-функциями

Функция Left возвращает значение типа Variant, а функция Left$ — String. Если вы помещаете возвращаемое значение в переменную типа Variant, то имеет смысл использовать функцию Left. Однако чаще строки присваиваются строковым переменным, и в этом случае вызов Left заставит VBA выполнить дополнительное преобразование типов.

По возможности используйте целочисленное деление

В VBA имеются два оператора деления: обычный «/», для операций с плавающей точкой, и целочисленный - «\». Для выполнения деления плавающей точкой VBA должен преобразовать оба операнда к этому типу данных. Поэтому, если дробная часть частного вам не нужна, можно сэкономить время, воспользовавшись оператором целочисленного деления.


Использованы материалы: "From Access 2002 Desktop Developer's Handbook"
Litwin, Getz, and Gunderloy. (Sybex, 2001)

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)