Казалось бы, вопрос глупый и провокационный — сколько угодно. Но в VB/VBA вы не сможете сделать это, больше чем 32 тысячи раз с копейками И причина не в undo-history.
Причина этого в том, что внутри IDE все идентификаторы (имена переменных, констант, процедур, типов, меток, DLL-файлов, модулей, проектов) хранятся в специальном объекте-словаре. Каждый загруженный проект имеет собственный экземпляр этого объекта-хранилища.
Вся соль в том, что единожды попав в хранилище, идентификатор оттуда не удаляется. Если в коде впервые где-то всплывает идентификатор, то он сразу же заносится в словарь. При этом нет механизма, который бы следил и удалял идентификаторы, которые полностью исчезают из кода. Поэтому и сам словарь предполагает только добавление в него новых идентификаторов и не предполагает удаление. Сам словарь содержит только уникальные идентификаторы, и создатели VB предположили, что ограничение в 32 тысячи уникальных идентификаторов в коде на один проект вряд ли кого-то затронет.
Однако, если постоянно переименовывать сущности, то даже делая это много раз с одной сущностью можно упереться в лимит, и тогда IDE просто не даст вам написать ни одной новой строки, использующей новый идентификатор (то есть даст написать Exit Sub, но не даст GoTo new_label) — будет выдана ошибка «Out of memory» и правка будет отменена. Чтобы продолжить работу придётся или перезапустить IDE, или просто выгрузить и загрузить заново проект.
На самом деле, проблема вовсе не в отсутствующей памяти — ограничение обусловлено вовсе не тем, что под хранение всех идентификаторов отведён какой-то лимитированный объём памяти. Ограничение вызвано тем, что каждому идентификатору в этом словаре-хранилище выделяется особый 16-битный порядковый номер, используемый в компактном бинарном представлении кода.
Напомню ещё раз на всякий случай, что VB/VBA является, пожалуй, уникальным примером IDE, которая исходный код, загруженный в неё, вообще не хранит внутри себя в виде собственно исходного текста. Компиляция кода, если можно так сказать, начинается в момент его набора: сразу в момент после ввода каждой новой строки* кода эта строка анализируется, разбирается и трансформируется из текста (последовательности символов) в ряд бинарных структур. Весь код всех модулей проектов внутри IDE содержится уже в предварительно обработанном бинарном виде, и превращается обратно в текст лишь в 3 случаях: при сохранении в файл, при осуществлении поиска по коду или в момент отрисовки кода (при этом в текст превращается только та часть кода, которая в данный момент непосредственно видна пользователю и должна быть отрисована). Одна из таких форм бинарного представления кода — представление в виде компактной цепочки 16-битных элементов. Именно этот вариант представления используется превращении «обработанного» кода обратно в текст (например при отрисовке), при этом не надо думать что элементы цепочки соответствуют ключевым словами или токенам — элементы соответствуют скорее логическим сущностям из кода.
Так, например, вот такой statement: On Local Error GoTo error_handler
представляется как 10C9 xxxx (где xxxx — как раз 16-битный номер идентификатора «error_handler»).
А вот такой statement: On Error Resume Next — как 04С9 0000.
Именно исчерпанием диапазона этих 16-битных номеров для идентификаторов и объясняется ограничение.
Примечания:
- строки* — имелась в виду «суперстрока», то есть либо 1 горизонтальный ряд символов, если возможность переноса строки не использовалась, либо несколько горизонтальных рядов, объединённых символов переноса строки в конце всех рядов, кроме последнего.
- Внимательный читатель заметил, что 16-битные номера имели бы ограничение в 65536 идентификаторов, а здесь говорится о 32 тысячах с копейками. На самом деле, хотя значения номеров 16-битные, используется в значениях только левые 15 бит и нумерация начинается с 1, а не с нуля.
- 32 тысячи с копейками — это не 32767, и не потому, что нумерация начинается с единицы, а потому, что встроенные в VB ключевые слова заносятся в этот словарь-хранилище изначально, съедая около 200 свободных номеров для пользовательских идентификаторов.