Быстрая обработка документов WinWord (*.doc)

yolki

Итак, есть стопка из 20.000 вордовских документов. Необходимо их обработать БЫСТРО. => COM не подходит.
Теми темпами, какими сейчас ворд открывает один документ, анализирует, закрывает.. обработка пачки занимает ~ 11 часов.
Вот у меня сейчас документ на 1.5Мб, тыща параграфов и блин уже минут 10 над ним фурычит.
Если бы документы были в формате RTF, можно было бы воспользоваться простым разборщиком RTF, без участия ворда, благо опыт в етом деле есть.
Есть ли какие-нибудь компоненты, умеющие работать с *.DOC в обход ворда?

Helga87

Что в себя включает понятие обработать?

yolki

почти тривиальная конвертация в html
В зависимости от Doc.Paragraphs[i].Style лёгкое исправление стиля текста. заголовки в содержание, цитаты так оформить, спец. параграфы сяк оформить.
документы имеют одинаковую структуру и используются одинаковые стили (почти всегда)

Helga87

У меня есть две идеи:
1. Посмотреть, возможно, тормозит не ворд, а сама обрабатывающая программа. И попробовать написать таким образом, чтобы не тормозило.
2. Взять какую-нибудь утилиту doc2rtf или doc2xml.

Dasar

Сохрани как word-ml, дальше разберешься

yolki

подозреваю, что сохранить пачку в word-ml займёт столько же времени...

Dasar

Грузить и сохранять он побыстрее должен, чем грузить, обрабатывать и сохранять.
Запусти сразу десяток процессов

Dasar

Да. загрузка и save - это секунды, а не десятки минут.

yolki

там документик был на 1.7 МБ.
сейчас засеку, сколько времени он его 10 раз сохранит в xml

bastii

А как прога написана, через automation? И на чем?

yolki

на дельфи. выглядит примерно так:

for i:=1 to Doc.Paragraphs.Count do
begin
Text:= Doc.Paragraphs[i].Range.Text;
StyleName:=Doc.Paragraphs[i].Get_Style;
// Дальше небольшой перебор по десятку стилей
// Выясняем, стиль - заголовок, или параграф
// выясняется так: Headers.Find(StyleName,N Paragraphs.Find(StyleName,N)
// Headers, Paragraphs - sorted TStringList
// классификация параграфа - ParaClass
// Если заголовок - добавляется в содержание.
// HTML - TStringList
HTML.Add(Format('<P class="%s">%s</P>',[ParaClass,Text];
end;

Automation - это как?
Импортнул библиотеку типов, CreateComObject(......

bastii

Короче давно очень я этими вещами занимался, не помню ничего толком. На сколько я понял, ты это делаешь через automation. Нужно проверить, что Appkication.ScreenUpdating=false, в этом случае на порядок быстрее. Затем можно сделать твою процедуру как addin, тогда все будет происходить в одном процессе. Еще не мешает проверить, что Дельфя работает не через IDispatch (уверен, что у Ворда дуальные интерфейсы).

yolki

ScreenUpdate стоял в yes. исправлю.
Что смотреть про IDispatch?
используемые объекты:

_Application = interface(IDispatch)
['{00020970-0000-0000-C000-000000000046}']
_Document = interface(IDispatch)
['{0002096B-0000-0000-C000-000000000046}']
Paragraphs = interface(IDispatch)
['{00020958-0000-0000-C000-000000000046}']

все IDispatch. что, можно цеплятся с другой стороны?

yolki

Есть такие штучки:

_ApplicationDisp = dispinterface
['{00020970-0000-0000-C000-000000000046}']
_DocumentDisp = dispinterface
['{0002096B-0000-0000-C000-000000000046}']
RangeDisp = dispinterface
['{0002095E-0000-0000-C000-000000000046}']
// *********************************************************************//
// Interface: Paragraphs
// Flags: (4544) Dual NonExtensible OleAutomation Dispatchable
// GUID: {00020958-0000-0000-C000-000000000046}
// *********************************************************************//
ParagraphsDisp = dispinterface
['{00020958-0000-0000-C000-000000000046}']

Неужели через них гораздо быстрее?

bastii

Исправь, а на IDispatch забей, ты все равно из другого процесса лезешь, мало поможет. Если после отключения ScreenUpdate будет все равно медленно, то имеет смысл написать все это как плагин. Потом уже имеет смысл отказываться от IDispatch (если так можно в Ворде, не знаю).

yolki

Она у меня на ночь в лабе оставлена. если к утру не справится - остановлю (благо процесс прерываем исправлю и пущу продолжать.
Я в этих тонкостях не силён - что изменится, если я буду использовать dispinterface вместо interface(IDispatch) ?

bastii

Не знаю, это наверно терминология Дельфей, хотя dispinterface вроде тоже обозначает, что через IDispatch. Просто в СОМ можно считать, что интерфейсы -- это С++ классы с виртуальными методами. IDispatch -- это интерфейс, где есть методы типа Invoke, его можно используют для позднего связывания, например в VBScript. В твоем случае работает маршалинг (т.е. идет взаимодейстие из разных процессов который довольно эффективно реализован для IDispatch (говорят, что маршалинг IDispatch даже быстрее). В случае плагина, когда вызовы будут в одном процессе (в одном апартменте раздница между простыми С++ виртуальными вызовами и извратными через IDispatch будет существенной (на порядок или два).
Оставить комментарий
Имя или ник:
Комментарий: