Версия 4.37 - 15.11.18


Программы и компьютеры
   VBA  |   |  Наверх  

Visual Basic for Applications (VBA) - опыт использования

Недавно я начал кодировать на Visual Basic for Applications (VBA) - меня попросили помочь решить задачу для большой библиотеки, которая заключалась в дописывании дескрипторов из иерархического Предметного указателя (ПУ) в Библиографические описания (БО) в соответствии со ссылками на номера этих БО. Это было нужно для конвертирования печатных библиографических указателей из формата документов MS Word в формат поисковой БД. Необходимо было обработать таким образом более 30 довольно больших файлов (60-100 стр.), в каждом из которых были сами БО, Авторские указатели, Предметные указатели и еще много всего другого. В результате должен был получиться чистый файл из одних БО с дописанными к каждому БО дескрипторами.

Хотя, я не кодировал уже почти 20 лет, но, изучив вопрос, решил взяться за эту задачу и написать всё это на новом для меня языке VBA так как для бывшего системного программиста, который сам когда-то разрабатывал новые языки и писал для них компиляторы и интерпретаторы, одним языком меньше, одним больше - не существенно. Вообще, я всегда любил писать на Си так как на нём мне удобно думать, но писать на чистом Си эту задачу, как мне казалось, было бы труднее, так как пришлось бы работать с файлами, в которых кроме текстов содержится огромное количество всякой всячины, записанной туда самим Вордом. Правда, уже в процессе написания программы на VBA я понял, что на самом деле, можно было программировать и на Си потому что все операции с текстом документов MS Word производятся с помощью объектной модели Word, доступной и в Си, но было уже поздно "менять лошадей на переправе". К тому же, для работы с VBA не требовалось устанавливать Visual Studio - её компонента для написания программ на Visual Basic встроена в сам Офис.

Итак, я стал писать программу массовой обработки документов Word на VBA для Офиса 2010...

Начать изложение впечатлений от этого процесса надо с того, что несмотря на название "Вижуал Бэйсик", язык этот с обычным Бейсиком имеет мало общего. По возможностям и выразительным средствам он значительно превосходит свой прототип, но всё равно по сравнению с Си вызывает чувство неудовлетворения и противоестественности. Но не это самое неприятное - объектная модель Ворда, которой он пользуется, производит просто удручающее впечатление. С одной стороны она невероятно громоздкая и избыточная, а с другой стороны - очень скудно и неполно документированная. Штатный хелп, который идёт в комплекте, описывает далеко не всё, что требуется, не говоря уже о том, что найти в этом хелпе что-нибудь нужное бывает весьма затруднительно в силу того, что поисковый движок в нём не понимает ничего, кроме запросов, состоящих строго из одного слова.

Документация, справочники и статьи, которые удалось найти в Сети, тоже были неполноценны. В результате постоянно приходилось писать небольшие тестовые программки чтобы выяснить как тот или иной метод или функция работают на самом деле.

Но опять-таки не это самое неприятное. Самым неприятным оказалось то, что интерпретатор этого Вижуал Бэйсика работал странно - те части кода, которые исправно делали то, что им положено при однократном выполнении, начинали неправильно работать оказавшись в цикле многократного исполнения того же самого кода! Причем, никаких обращений к дискам, замедляющих выполнение программы, в это время не происходило - программа и документы, с которыми она работала, находились целиком в оперативной памяти.

Выйдя из ступора от осознания этого невероятного факта, я начал специально вставлять в циклы программные задержки, обращаясь к своей собственной подпрограмме WaitMe(), которая, в свою очередь, принудительно отдавала управление ОС для того, чтобы та могла, в свою очередь, передать управление другим задачам и процессам, в том числе, процессам того же самого Word, файлы которого в данный момент обрабатывались.

Можно было предположить, что эти ошибки связаны с тем, что Word не успевает перерисовывать экран, передвигаясь по разным частям документа в слишком быстром для него темпе (в том числе, даже при обычном скроллинге), но это оказалось не так. Использовав метод отключения перерисовки экрана, я убедился, что и с отключенной перерисовкой задержки всё равно необходимы. С ними всё работает правильно, а без них - нет! Мало того, в режиме запрета обновления экрана Word всё равно изредка выводил на экран какой-нибудь мусор, полностью избавиться от которого мне так и не удалось, несмотря на различные ухищрения с принудительной перерисовкой экрана в отдельных местах программы и использованием некоторых других приёмов. Правда, на работу программы всё это, к счастью, совершенно не влияло.

Здесь надо добавить, что Офис 2010, с которым я работал, ставился с оригинального дистрибутива Майкрософт, активировался штатным корпоративным ключом и набирал все положенные ему актуальные апдейты. Кроме того, всё проверялось на двух компах под Win 7 64х - одном физическом с 4-х ядерным Квадом 3 ГГц, а втором - виртуальном (ВМ под VMware) на хосте с i7 3.5 ГГц. Обе Win 7 были тоже совершенно легальны, штатно активированы и с актуальными апдейтами. Результаты работы программы на них были идентичны за исключением скорости выполнения.

Обнаружились и некоторые другие странности самого интерпретатора языка. Например, в оригинальном коде, который я писал, использовались глобальные константы (Public Const), но когда я захотел перенести код программы на другой компьютер просто скопировав текст программы копи-пастой, VBA длинно и страшно выругался, заявив, что глобальные константы недопустимы и вместо них надо использовать специальные функции их инициализации (с весьма невнятным описанием). Вбить строки с Public Const вручную тоже не удавалось из-за той же диагностики. Однако, просто перенеся на другой комп файл Normal.dot, в котором хранилась моя программа, я добился желаемого. Надо сказать, что при этом все доступные настройки рабочего Normal.dot и Normal.dot только что установленного Офиса на виртуальной машине для которой я пытался скопировать код копи-пастой полностью совпадали. Почему же тогда VBA не ругался, когда я впервые успешно использовал глобальные константы? - Странно, не правда ли?

Эта вопрос не давал мне покоя и уже позже, завершив написание и отладку программы, я стал разбираться с ним более детально. В результате экспериментов выяснилось, что если в коде уже содержится хотя бы одна подрограмма Sub или Function, пусть даже и пустая, то глобальные константы использовать можно. Если же подпрограмм ещё нет - то нельзя. Вот такая причуда интерпретатора. Или его разработчиков?

Другой странностью было то, что в некоторых частях одного и того же кода я мог написать, например, просто WaitMe(), а в других требовалось писать явно Call WaitMe, иначе VBA не воспринимал WaitMe() как вызов подпрограммы. Как такое, вообще, может быть?? Разный синтаксис внутри одной и той же программы??

Код программы в результате содержал 780 строк и исправно работал, но чего мне это стоило!!! Я никак не ожидал такого и с подобным поведением программ и интерпретаторов никогда раньше не сталкивался. В общем, я убил почти половину срока из полутора месяцев на войну с этой двуглавой свиньёй - VBA + объектная модель Ворда.

Тем не менее, освоив это Средство, я придумал как его использовать "в мирных целях". Когда-то очень давно, еще на MSX , я написал программу на Си для составления рифмовников с использованием сортировок по реверсивной записи слов. Но в те времена стихов в виде файлов практически не было и я вручную вбивал рифмы из сборников Есенина и некоторых современных поэтов - это было довольно трудоёмкое занятие. Эти рифмовники, составленные в 1995 г., у меня сохранились до сих пор и я даже иногда в них заглядываю в особо затруднительных случаях, но сама программа для их составления, к сожалению, утеряна.

Однако, в настоящее время в Сети очень много любых стихов и в формате Word, и в HTML. Поэтому я подумал - а не написать ли мне снова подобную программу, но уже на современном уровне? Чтобы она сама анализировала готовые стихи, выбирала из них рифмы и составляла бы рифмовники. Можно было бы составлять рифмовники колоссального размера и любого стиля как по отдельным поэтам, так и по разным поэтам вместе взятым. Например, все рифмы Вознесенского, Рождественского, Евтушенко... Или все рифмы Пушкина!

Это, заодно, могло бы стать темой для интересной лингвистической диссертации, которую я писать, конечно, не буду и не соберусь написать никогда. Всё-таки основные профессии у меня совсем другие...

* * *

Загрузить рифмовники "Сергей Есенин" и "Лирика" 1995 г." (RAR 66 KB)




Рейтинг@Mail.ru

Версия 4.37 - 15.11.18
(сайт адаптирован для прослушивания и просмотра на смартфонах без флэш-плеера)