Главная » Delphi » Доработка программы Trace пример работы с DOC- и RTF-файлами

0

И тут мы вспомним про нашу программу Trace, которую я не без умысла довел до некоторого логического конца, и только теперь обратился к теме чтения DOC- и RTF-файлов. Можно ли включить функцию чтения этих форматов в нее и что из этого выйдет? Для этого нам придется сначала еще раз обратиться к демонстрационной программе WordTxt и погонять ее под различными версиями Office, Тогда мы увидим, что на OfTice ХР наше указание WordApp.visibie:=False действует очень своеобразно: при создании объекта Word ХР действительно не виден, но вот в процессе выполнения процедуры загрузки документа он появляется на экране, причем еще и норовит вылезти "on top". Word 97 ведет себя куда скромнее и действительно работает в фоновом режиме, как мы указали. По этой причине довести таким образом Trace до ума во всех вариантах не удастся — все время открытый (и тем более то появляющийся, то пропадающий) в процессе поиска Word нам не нужен совершенно. Так что версия программы Trace, которую мы сделаем, будет работать на поиск DOC- и RTF-файлов только в присутствии Word 97. Вполне вероятно, что нормальная работа возможна и в других отличных от Office ХР версиях, но я этого проверить не смог — читатель, несомненно, при желании сделает это без труда.

Для того чтобы сделать все корректно, нам надо как-то узнать, установлен ли Word 97 в системе. Это можно сделать через реестр, причем в двух местах:

HKEY_LCCAL_MACHINE\Software\Microso?t\MS Office 97 HKEY_CURRENT JJSER\SOFTWARE\Micxosoft\Office\8.ONWord

Если эти ключи имеются, то можно предполагать, что в системе установлен именно Word 97. Неясно, правда, что будет, если установить сразу два Office, но это все же ситуация редчайшая — они явно будут мешать друг другу. Если вы все же желаете и такую ситуацию предусмотреть, то можно попробовать вместо объекта Word.Application вызывать объект Word.Application.8 (если

Word только один, то это одно и то же), но поможет ли это — не знаю, не проверял. Мы будем действовать старым способом, причем для проверки воспользуемся вторым ключом — он внушает больше доверия.

Перенесем последний вариант проекта Trace (папка Glaval6\l) в новую папку (Glaval 8\3) и придадим программе для начала новый номер версии 1.20 (исправить надо в двух местах, в проекте и в заголовке формы, автоматически здесь в заголовок ничего не выводится). INI-файл переносить не будем, пусть он создастся заново. Удаляем в модуле poisk.pas из константы stDefExt расширения doc и rtf. В дальнейшем, если при первом обращении в этим форматам мы не найдем в системе Word 97, выведем предупреждение и тогда добавим " .doc . rtf" к строке st Ext, которая у нас несет текущие значения расширений для исключаемых файлов. В предложение usee добавляем модули Registry и ComObj, В var— переменную WordApp: OLEVariaat, и пишем следующую отдельную функцию DocRtfRead, которую располагаем выше имеющейся функции ReadFileFormat

function DocRt fRead(fname:string; var s t:string):boolean; stdcall; var Reg: TRegistry;

wst:WideString; begin

if VarlsEmpty(WordApp) then Iесли Word еще не создан) begin

Reg :=TReg.i s try. Create;

with Reg do

begin

RootKey := HKEY_OJRRENT_USER;

if not KeyExists(‘SOFTWARFAMicrosoftXOfficeNS.OXWord’)

then begin Result:=False; Free; exit; end;

Free;

end;

WordApp := CreateOleObject (‘Word.Application’); ‘.

Iсоздаем объект Word)

end;

result:=True;

if not VarlsEmpty(WordApp) then fecmi он сознался) begin

I открываем мокумент и читаем в строку:)

WordApp.Visible:=False;

try

WordApp. Documents.Open (fnanie, Conf irmConversions:=False) ; except st: =’ ‘;

exit; end;

wst:=WordApp.Act i veDocument.Content; st:wst;

WordApp. Documents.Close(SaveChanges: =0) ;

/закрываем без сохранеш-л}

end

else result:=False; /если нет, возвра;мгм ошибкуi end;

А ниже В функции ReadKileFormat Строку С оператором result: =ReadMapFile заменяем на следующий текст:

if (Extract FtleExt(ANSIUpperCase(fname)) = ‘.DOC) or (ExtractFileExt(ANSIUpperCase(fname))=’.RTF*) then (если это документы Word) begin

if not DocRtfReadffname,stFiie) then begin

st:=’B системе не найден MS Word.’+

it 10+’Исключить файлы .doc . rtf из поиска?';

if Application.MessageBox (Pchar (st), ‘Ошибка’ ,mb_OKCANCEL) –idOK then stExt:=’.doc .rtf ‘+stExt; result:=False; exit; end;

if stFile=" then begin result:=False; exit; end; (кодировку определять не надо:} if (ExtractFiieExt(ANSIUpperCase(fname))=’.DOC’) then st:=’ MS Word DOC’ else st:=’ RTF';

result:=FindString; Iпоиск строки) exit;

end else result:=ReadMapFile; (в stFiie – содержимое файла)

При отсутствии Word 97, а также— предположительно— в случае ошибок открытия файла функция DocRtfRead вернет значение False, и программа предложит исключить расширения doc и rtf из поиска на дальнейшее (при закрытии программы это зафиксируется в INI-файле). Отдельно создаем процедуру закрытия Word:

prooedure CloseWord; Iзакрытие Word) begin

if not VarlsEmpty(WordApp) then (если он вообще есть) begin I закрываем )

try

WordApp.Quit(SaveChanges:=0); WordApp:=Unassigned; except Application.MessageBox

(‘He могу закрыть MS Word.’,’Ошибка’,mb_OK); end; end; end;

Вставляем ее вызов в процедуру поиска SearchFile по окончании основного цикла:

FindClose(sf); /конец поиска/ CatDir.Free;

CloseWord; {закрытие Word/

В самом цикле мы немного изменим вывод в Label2, теперь мы в него будем выводить полное имя файла, и его придется вставить уже после отсеивания запрещенных файлов:

if pos(ExtractFileExt(ANSIUpperCase(fname)),ANSIUpperCase(stExt)}<>0 then continue;

{если расширение совпадает с запрещенным, то на выход/ Forml.Label2.Caption:=fname;

Application.ProcessMessages; {чтобы все прокрутилось}

Запустите программу и проверьте — все отлично ищется, но скорость… Конечно, файлов мы просматриваем намного больше, но назвать ее высокой язык не поворачивается, хотя она все же втрое выше, чем когда мы файлы читали допотопными DOS-методами. Поиск в моей "испытательной" папке (C:\DOK с почти 20 ООО файлов) занял примерно 15 минут, сравните с результатами в главе 14. Загрузка всех 512 Мбайт физической памяти при этом — на 100% (напомню, что мы читаем файлы не более 500 Кбайт).

Медленная скорость и то, что вся эта система не работает, как надо, с Word ХР— еще не единственные ее недостатки. Несмотря на обработку исключений, все сбои Word отследить не удается. Это касается в первую очередь некоторых испорченных DOC-файлов, но, кроме того, также и случаев самопроизвольного "падения" Word в процессе работы. Во втором случае программу можно просто закрыть, а в первом случае Trace "виснет", и ее приходится принудительно прерывать (через <Ctrl>+<Alt>+<Del>), при этом также следует удалить тем же способом запущенный в качестве сервера экземпляр Winword. Лучше всего найти и поудалять файлы, которые могут вызвать сбои, и именно для облегчения этой задачи мы стали выводить полное имя файла, а не только папку, как ранее. Параллельно (но заранее!) запущенный "обычный" Word чаще всего на работу никакого влияния не оказывает, только загрузить в него файл во время запущенного поиска обычным "ассоциативным" путем (через Проводник) не удастся. Все это я честно отразил в справке (см. папку Glaval8\3 на диске). Добавлю, что именно эту версию программы я использовал при составлении указателя-FAQ к данной книге и такой опыт ее использования позволил исправить некоторые отмеченные ранее недостатки.

Заметки на полях

Не думаю, что нам следует сильно упрекать разработчиков этих новомодных технологий за рассмотренные "глюки". Они асе делали, как им заказывали, и никто, конечно, не виноват, что мы используем OLE не совсем по назначению — нам вызов приложения и не нужен, нам нужны его функции, а вот этого нам отдельно не предоставляют. Безусловно, все эти технологии очень полезны, когда возникает задача удаленного управления неким приложением, типичный случай вы асе видите, когда, например, Acrobat Reader загружается в окне Internet Explorer или другого браузера. А на естественный вопрос: почему бы заодно и не написать нормвльный набор API в стандартной форме — функции- то эти уже итак есть? — ответ вы знаете сами: когда компаниями руководят профессиональные маркетологи, то цель деятельности в виде создания некоего продукта подменяется целью заработать нв нем как можно больше денег. Они считают, что так всем будет лучше — можете попробовать с ними поспорить.

Единственное, что я могу посоветовать для ускорения программы и избавления от всех этих "глюков" — забыть про OLE и читать эти форматы самостоятельно, примерно как мы читали Unicode в главе 8. Форматов достаточно много — есть эта самая Unicode-версия, которую мы уже читали в главе 8, есть Word б "родной" (однобайтная версия), есть Word 6.0/RTF, есть, наконец, просто RTF. Для сведения укажу, как можно надежно отличать форматы DOC от других: "настоящий" DOC-файл всегда начинается с сигнатуры

chr ($d0) + chr ($CF) + chr ($11) + chr($E0) +chr (SA1), у RTF В тех же ПЯТИ

первых символах стоит f\rtf •. Далее в файле должна обязательно встретиться где-то строка Word.Document.8 (ДЛЯ Unicode-версии) ИЛИ Word.Document.б (для однобайтной версии Word 6.0).

RTF-формат общедоступен, его описание имеется на сайте MSDN, можно найти в Сети и пример реализации "читалки" на С (она входит в MS Software Development Kit). Описание достаточно запутанное, поэтому, чтобы сделать корректную процедуру чтения самому, придется очень постараться— правда. для приблизительной "читалки" в стиле той, что мы употребляли для Unicode, отсеивать весь мусор и не требуется. Почти ничем от стандартного RTF не отличается и формат Word 6.0/RTF, в котором сохраняются файлы при обращении из более старших версий к пункту Сохранить как | Word 6.0/95. Для RTF можно попробован, использовать упоминавшийся прием чтения через невидимый RichEdic — вряд ли это будет более "криво", чем вызывать Word для такой цели. Конечно, всегда можно поискать специально предназначенные компоненты или библиотеки, только они обычно платные (см.. например, http://www.xkee.com/business/cz-doc2txt-com/). и/или требуют дополнительных самодельных модулей, из-за чего слишком сложны в использовании (http://mvw.torry.net/vcl/vcltools/text/msconv.zip). В общем, чго-ю придумать можно.

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

По теме:

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