В продолжение темы от марта 2018 года Как реализовать автоматический импорт-экспорт макросов в книге. Проблема уменьшилась но не исчезла. Не всегда удается автоматически импортировать модули из файлов. Проявляется это как фатальная ошибка загрузки Excel в целом. А при следующем запуске он пытается восстановить "потерянные данные". Есть серьезные подозрения, что в момент импорта Excel чем-то занят и ставит процедуру импорта в очередь. Но не понятен порядок формирования и продвижения этой очереди. Закономерности возникновения ошибок выявить не удалось. Установка разных "остановщиков" и "перераспределителей ресурсов" типа DoEvents ни к чему не приводят. По этому поводу у меня только одна версия. В момент старта Excel формирует "Программу запуска" в которую включает и процедуры типа Workbook_Open, а затем пошагово эту Программу исполняет. И у меня ощущение, что процесс формирования Программы достаточно "гибкий" (другими словами: "как карта ляжет"). А т.к. импорт модулей запускается сразу при открытии книги, то эта операция иногда выполняется тогда, когда Excel к этому еще не готов. Одним из доводов в пользу этой версии является то, что при ручном запуске импорта модулей, после полной загрузки, ошибок ни разу не было. Правда, статистика не большая.
Отсюда вопросы. Как можно: 1. Программно получить список исполняющихся макросов? 2. Программно отследить, что при открытии книги Excel уже "полностью загрузился"?И еще один вопрос, хочу и этот способ испытать: есть ли возможность запустить процедуру "параллельно" на подобии как загрузить форму в модальном режиме? Например (гипотетически) вот так:
Код
sub Workbook_Open()
...
modal(ImportModules, 0)
...
end sub
А может кто подскажет где можно почитать документацию на эту тему? Возможно, что я тупо (во всех смыслах) нарушаю все правила, а хочу нормальный результат.
DoEvents я пробовал. Доходило до абсурда - через строку. Не помогает.
Предложенный цикл работает. Но тоже есть проблемы. Он примерно в 50% случаев уходит в бесконечность. Приходится в ручную прерывать работу макроса. Я решил дождаться когда-же он достигнет предела. Меня хватило минут на 5.
Но обнаружил пару особенностей. 1. Макрос "Импорт" работает параллельно с остальными. Т.е. Excel не ждет, когда этот макрос отработает а продолжает работать параллельно. Я это обнаружил, когда после загрузки Excel полез редактировать код другого модуля и увидел, что Excel находится в режиме выполнения макроса. Когда приостановил выполнение то оказалось, что текущее действие и есть как раз этот цикл.
2. Иногда после прерывания цикла, модуль сам удаляется. Т.е. прервал макрос "Импорт", что-то сделал в коде другого модуля, а потом увидел, что импортируемого модуля нет.
Такое ощущение, что задача ставится в очередь, только вот как эта очередь движется и чем ее можно протолкнуть не понятно.
Set objTmpVBComp = objVBProjTo.VBComponents.Import(sFullName)
With objVBComp.CodeModule
.DeleteLines 1, .CountOfLines
sModuleCode = objTmpVBComp.CodeModule.Lines(1, objTmpVBComp.CodeModule.CountOfLines)
.InsertLines 1, sModuleCode
End With
objVBProjTo.VBComponents.Remove objTmpVBComp
Изменено: Евгений Попович - 30.03.2018 16:41:33(Добавил решение)
В продолжение разговора. За основу взял решение, предложенное Дмитриев Щербаковым, за что ему отдельное спасибо.
Для импорта модуля написал функцию, которую расположил в personal.xlsb:
Код
Public Function ImportModule(ByVal ImpModuleName As String, wb As Object, ByVal FolderName As String ) As Boolean
...
Set objVBProjTo = wb.VBProject
Set objVBComp = objVBProjTo.VBComponents(ImpModuleName)
If objVBComp Is Nothing Then
... 'такого модуля нет
Else
... 'такой модуль есть и я его удаляю
With objVBProjTo.VBComponents
.Remove .Item(ImpModuleName )
End With
...
endif
objVBProjTo.VBComponents.Import Filename:=sFullFileName
...
Но тут возникла загвоздка. Существующие модули не всегда удаляются или удаляются не сразу. Причем по какому закону не понятно . В результате, например при необходимости импортировать модуль "m" и абсолютно равных прочих условиях, у меня может получиться: 1. Один модуль с именем "m" (т.е. все хорошо) 2. Два модуля с именами "m" и "m1" (т.е. старый модуль не удалился а новый переименовался) 3. Один модуль с именем "m1" (т.е. старый модуль удалился после того как импортировался новый )
Есть три параллельных проекта. В этих проектах есть задачи, которые решаются одинаковыми методами. Для реализации этих "универсальных" методов я (пока) выделил 8 модулей , которые используются в разных комбинациях, но должны быть одинаковы во всех проектах. Эти модули постоянно дорабатываются. И чтобы многкртано не писать один и тот-же код, сейчас я в ручную синхронизирую все модули (в конце работы - экспорт в файлы, в начале работы - импорт). Хранить все модули в личной книге макросов - не вариант по двум причинам: 1. Все проекты реализуются на разных компах. 2. После завершения проект должен быть полностью автономен: клиент будет тягать его с собой на флешке и работать где придется. (Проблема работоспособности на Excel разных версий это отдельный геморрой ).
Сам процесс "импорт-экспорт" - это тупя, нудная, длительная и неудобная работа, критичная к ошибкам. Я пару раз забывал экспортировать один или два модуля, в результате - день на смарку (писать дубликат кода не хочется). Вопрос: как автоматизировать это процесс - написать макрос, который бы: - при открытии книги переименовал текущий модуль, импортировал его последнюю версию из файла, удалил переименованный модуль; - при закрытии книги удалил файл с модулем и экспортировал текущий? Т.е. мне нужен макрос для управления модулями. Спасибо.
Пользовательскую (собственную) функцию, в принципе, я делать умею. У меня вопрос вот какой. Когда используешь стандартные функции то (у меня офис 2007) под строкой выскакивает подсказка о количестве и типах необходимых аргументов. Возможно ли организовать такой сервис для пользовательских функций? И второй вопрос а возможно ли подключить к ней Help?
Проблема в следующем: в одной книге, иногда на одном иногда на разных листах, есть несколько таблиц. Логика обработки данных в этих таблицах весьма затейлива. Поэтом я в каждой таблице завел строку адресов-ссылок на ячейку со следующим значением, что-то вроде ФАТа, и макрос, который это все обсчитывает. Но когда начали менять размерности таблиц, все это рассыпалось. Вопрос как мне отслеживать перемещение-изменение адреса конкретной ячейки, ведь Excel это умеет делать. Например, в "Лист1!R1C1" хранится адрес ячейки "Лист2!R17C25". По какой-то причине эта ячейка переместилась на позицию "Лист2!R17C35". Что мне нужно сделать, чтобы это перемещение автоматически отслеживалось и приводило к соответствующим изменениям значений в "Лист1!R1C1".