Главная » Delphi » Работа с Word через объект VBA

0

К концу 90-х годоа был разработан диалект Visual Basic под названием VBA (Visual Basic for Appilications), который перекрыл в том числе и все функции Word Basic. Именно перекрыл, а не включил а себя, чтобы установить соответствие, следует воспользоваться справкой по Visual Basic, которая устанавливается вместе с MS Office (по умолчанию она отсутствует, если ее нет, то следует ее специально установить). Справка эта для Office 97 находится в папке .AMicrosoft Office\Office и называется vbawrd8.hlp, а для последующих версий она уже делалась в формате СНМ и раскидана по разным файлам (большинство из которых для Windows ХР находится в папке ..\Program Files\Common Files\Microsoft SharedWBA), так что удобнее ее вызывать изнутри самого Word. Любопытно, что для Office 97 справка была частично переведена на русский, а в последующих версиях это сделать поленились, поэтому удобнее раздобыть справку из Office 97 и пользоваться ею — в большинстве необходимых функций она ничем не отличается от более поздних версий. Можно и воспользоваться услугами сайта MSDN, где (на английском, естественно) воспроизведен тот же текст, что прилагается к Word ХР. В этой справке, в частности, есть раздел "Visual Basic Equivalents for WordBasic Commands", в котором и устанавливается соответствие между функциями и свойствами старого Word Basic и нового VBA.

Разберемся в "правильном" методе обращения с MS Office-объектами через VBA. Так как справка no VBA имеется, да еще и частично доступна на русском, все вроде бы просто — за исключением, правда, того, что вам придется вникать в непростую логику создателей VBA, которые не могли, конечно, создать простых функций для самых очевидных вещей. Например, как вы бы посчитали с точки зрения здравого смысла, должно ли быть у объекта под названием Document свойство Text? Да это самое основное его свойство! — подумаете вы. И ошибетесь — такого свойства у объекта Document нет вообще. На самом деле текст извлечь все же можно. Покажем общий принцмп создания объекта типа word в своей программе методом позднего связывания. Для этого в предложение uses надо вставить тот же самый модуль ComObj. и так же объявить переменную WordApp: OLEVariant. Основная процедура создания и уничтожения объекта будет выглядеть так:

try

WordApp := CreateOLEObject{‘Word.Application’); except

ShowMessage := ‘Word не найден.'; exit; end;

WordApp.Visible := False; {не показываем Word) WordApp.Documents.Open (<filename>); {открыли файл}

{чего-то с ним делаем! WordApp.Quit; {закрыли объект)

WordApp:=Unassigned; {и уничтожили саму память о нем/

Попробуем на этой основе переделать нашу демонстрационную программу WordTxt. Процедуру проверки через реестр оставим без изменений, хотя она в принципе и не нужна, а остальные наши процедуры будут выглядеть так (в комментарии я внес, как и ранее, описание соответствующих констант):

procedure TForml.ButtonlClick(Sender: TObject); var st:string;

wst:WideStr ing; begin (открываем документ, как объект VBA, читаем текст в строку и выводим в Memo} if not VarlsEmpty(WordApp) then

begin {если компонент уже был – закрываем без сохранения! WordApp.Quit(SaveCha nges:=0); WordApp:=Unassigned; : end;

Memol.Lines.Clear; if OpenDialogl.Execute then

begin

Forml.Caption := ExtractFileName(OpenDialogl.FileName); WordApp CreateOleObject(‘Word.Application"); if not VarlsEmpty(WordApp) then begin

WordApp.Visible:=False;

WordApp.Documents.Open(OpenDialogl.FileName,

ConfirmConversions:=False); wst:=WordApp.Act i veDocument.Content; st:=wst; Memol.Text:=st; end

else ShowMessage(‘MS Word не найден’); end; end;

procedure TForml.Button2Click(Sender: TObject); begin

{FileFormat. Can be one of the following constants:

wdFormatDocument = 0

udFormatDOS Text = 4

wdFormatD0STextLine3reaks = 5,

wdFormatRTF = 6

wdFormatTempi ate = 1,

wdFormatText = 2,

wdFormatTextLineBreaks = 3

or wdFormatUnicode Text.)

{сохраняем как текст с концами строк:) if not VarlsEmpty(WordApp) then begin

WordApp.ActiveDocument.SaveAS

(ChangeFileExt(OpenDialogl.FileName,’.txt’),FileFormat:=3); In просто закрываем:) WordApp.Quit; WordApp:=Unassigned; : Forml.Caption := ‘NS Word'; end

else ShowMessage(‘Текст MS Word не найден’); end;

proaedure TForml.FormDestroy(Sender: TObject); begin {при закрытии уничтожаем, если есть) [SaveChanges. Can be one of the following constants: wdDoNotSaveChanges = 0

wdPrawptToSaveChanges = SFFFFFFFE or wdSaveChanges = $FFFFFFFF) if not VarlsEmpty(WordApp) then begin

закрываем без сохранения)

WordApp.Quit(SaveChanges:=0);

WordApp:=Unassigned; end; end;

Попробовав поработать с той и другой программой, особенно с Office ХР, вы поймете, почему Microsoft рекомендует обращаться в VBA, а не использовать устаревшие функции Word Basic. Как видите, удалось даже легко обойти отсутствие свойства Text у Document, его вполне заменяет свойство ActiveDocument. Content, и выделять ничего не потребовалось. Только на всякий случай пришлось воспользоваться промежуточной "широкой" Unicode- строкой — опыт показал, что так надежнее’. Давать объяснения, почему иногда (например, при запуске в отладочном режиме) все отлично работает и без Unicode-строки, а в других случаях конверсия не работает, я не берусь — но это, кстати, точно так же происходит в других подобных случаях, необязательно связанных с серверами Office. Во всех случаях, когда есть подозрение, что читаемая строка содержит двухбайтные символы, следует использовать промежуточное преобразование ее через тип widestring.

Но главное, что удается закрыть программу без всяких предупреждений, используя параметр saveChanges. Кстати, приятно еще и то, что процедура открытия файла здесь сама по себе — в отличие от Word Basic — изящно обходит все возможные ошибки: я долго заставлял ее открывать различные файлы, включая даже бинарные, переименованные в DOC или RTF, и все их она исправно открывала, останавливаясь на первом встреченном символе с нулевым кодом, и извлекая текст из всего остального. Так что в принципе мы могли бы ей целенаправленно подсунуть и чисто текстовые файлы — если бы только она еще умела определять кодировку! Не сбило ее даже предложение открыть уже открытый в "настоящем" Word файл — он был обработан, как ни в чем не бывало. Сбой может случиться только в редчайшем случае, когда программе попадается испорченный DOC-файл (у меня такой имеется, и не один, и я их специально подсунул, чтобы посмотреть, что получится). Позже мы постараемся этот момент обойти, используя службу обработки исключений Delphi.

Для ускорения процесса иногда рекомендуют отключать проверку орфографии вот так:

WordApp.Opti опз.CheckSpellingAsYouType:=False; WordApp.Opt ions.CheckGrammarAsYouType: °=Fa1se;

Однако в нашем случае это занятие бессмысленное: мы ничего с текстом не делаем, и проверка орфографии все равно не должна работать. Если все же вам придется изобретать что-то в этом роде, то не забудьте, что обратно включать проверку тоже необходимо, иначе придется при первом же входе в Word делать это вручную.

Источник: Ревнч Ю. В.  Нестандартные приемы программирования на Delphi. — СПб.: БХВ-Петербург, 2005. — 560 е.: ил.

По теме:

  • Комментарии