PL> PL>
PL>MSWORD — созданный COM объект "WordApplication". PL>Может быть знаете конструции более эфективные?
Может стоит написать на VBA процедуру которая будет из например массива который ты ей передашь и формировать таблицу — а процедуру добавляй уже когда объект word — a создашь. Я думаю быстрее получится — но реализацию неспрашивай — я тебе только идею подкинул.
Re: Delphi to Word (оптимизация ?)
От:
Аноним
Дата:
16.08.02 12:00
Оценка:
Здравствуйте peter_login, Вы писали:
PL>Как ускорить формирование отчета в Word-е, особенно вывод в ячейки таблицы. PL>Использую конструкцию типа:
PL>
PL> PL>
PL>MSWORD — созданный COM объект "WordApplication". PL>Может быть знаете конструции более эфективные? :???:
Вот один приемчик. Создать длиииииннннууую строку, содержащую все ячейки твоей таблицы с первой по последнюю. Разделителем между ячейками нужно использовать что-то, что не попадется в содержимом ячеек (например, символ табуляции или '|').
Пример для таблицы 3 строки * 2 колонки:
Спасибо за совет, но скорее всего такой подход очень сложен,
так как таблица не однородная есть объединения и разделения
ячеек по ходу формирования последней.
Может будут еще предложения.
Здравствуйте peter_login, Вы писали:
PL>Как ускорить формирование отчета в Word-е, особенно вывод в ячейки таблицы.
Если речь о Ворде-2000, то можно отказаться от автоматизации.
Для него можно сгенерировать HTML, это довольно просто и работает быстро.
Для того, чтобы поглядеть, как сей HTML выглядит, в Ворде открой документ и нажми Alt+Shift+F11. Формат HTML в Ворде-2000 сохраняет практически все атрибуты оформления (в отличие от Ворда-97, где используется только HTML-совместимое подмножество).
Здравствуйте achp, Вы писали:
A>Здравствуйте peter_login, Вы писали:
PL>>Как ускорить формирование отчета в Word-е, особенно вывод в ячейки таблицы.
A>Если речь о Ворде-2000, то можно отказаться от автоматизации.
A>Для него можно сгенерировать HTML, это довольно просто и работает быстро.
A>Для того, чтобы поглядеть, как сей HTML выглядит, в Ворде открой документ и нажми Alt+Shift+F11. Формат HTML в Ворде-2000 сохраняет практически все атрибуты оформления (в отличие от Ворда-97, где используется только HTML-совместимое подмножество).
К сожелению гарантии, что у клиента будет 2000-й нет гарантии. А заставлять его переходить несолидно. :crash:
Меня тоже всегда интересовал вопрос почему экспорт в Word такой медленный. Многие говорили что это из-за IDispatch, многие из-за общего торможения Outprocess COM серверов.Но тем не менее другие программы здесь работают идеально, только Word & Excel тормозит.
Как то очень давно я услышал от одного человека такое мнение: "Зачем этот COM вообще нужен, ведь DDE работает быстрее, весь эффективный экспорт в офис должен быть на основе DDE, именно из-за этого его до сих пор поддерживают Word и Excel".
У меня этот тезис вызвал сильные сомнения, но я решил его проверить. Получилось естественно абсолютно такая же производительность. Но при этом я получил любопытный побочный эффект который и побудил меня написать данное сообщение.
При работе с DDE ты просто передаешь Word строку c синтаксисом WordBasic, а он ее выполняет. В принципе это логично сделать похожий синтаксис, но если например передать неправильную строку то будет интересная бага. Отладчик Word остановится внутри макроса состоящей из единственной строки — той которую ты передал. Т.е. получается следующее что ты передаешь строку по DDE, word ее парсит и выполняет, т.е. Parser включается при посылке каждой команды, тогда как в макросе Word парсер разбирает весь макрос в самом начале, естественно Word Basic работает быстрее.
И вот здесь у меня появилось подозрение: скорость экспорта на основе DDE была абсолютно такой же как и на основе COM. Сам макрос в списке не появляется, поэтому я не смог поймать Word за руку, но похоже при вызове по COM word просто генерит макрос, потом парсит его и выполняет.
Решение естественно кривое, но вспомните когда проявился Word. Если вы сейчас решите сделать что-то похожее, то вы сначала реализуете COM сервер, а потом на его основе сделаете скриптовый язык и все будет быстро и клево. Но Word старше технологий COM и DDE на несколько лет, поэтому там COM сервер врезался в готовое приложение. Притом
Word написан навярняка на голом C(т.к. он опять же старше C++) и в нем наверняка не применялся idl(по той же причине) который сам генерит IDispach, т.е. IDispath там реализован руками. Именно этим объясняется различие возможностей у IDispatch и библиотеки типов Word.
Вывод: для того чтобы быстро работать с Word надо поменьше вызывать его через COM. На прошлой работе у ныс было замечательное и быстрое решение когда на Word был написан макрос который делал обратный вызов к нашей программе и тащил данные из нее. Все было очень быстро. К сожалению данный способ вообщем-то мертв т.к. есть много
побочных эффектов.
Мне кажется что самый эффективный метод это генерация макроса Word целиком в вашей программе, а потом передача его Word-у. Большие табличные данные можно закатывать в Variant-ы или в ADO Recordset-ы.
Сейчас я вообще не занимаюсь этой темой, по причине того что больше не программирую на Delphi и BCB, и не занимаюсь экспортом в Word, но буду рад продолжить обсуждение этой темы.
Любая проблема дизайна может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев
Re: Delphi to Word (оптимизация ?)
От:
Аноним
Дата:
19.08.02 08:17
Оценка:
Здравствуйте peter_login, Вы писали:
PL>Как ускорить формирование отчета в Word-е, особенно вывод в ячейки таблицы. PL>Использую конструкцию типа:
PL>
PL> PL>
PL>MSWORD — созданный COM объект "WordApplication". PL>Может быть знаете конструции более эфективные? :???:
В свое время столкнулся с подобной траблой при экпорте данных в Excel.
Решение оказалось весьма неожиданным: формируется, что бы вы думали?, Clipboard строка и потом методом Insert вставляется в Excel... простенько и со вкусом... производительность — на два порядка выше... строки отделяются chr(13){Enter}, колонки — chr(10){Tab}...
может и здесь прокатит... пробуйте! :)
PL> PL>
PL>MSWORD — созданный COM объект "WordApplication". PL>Может быть знаете конструции более эфективные?
Прежде всего можно ускорить (и значительно)
ActDoc := MSWORD.ActiveDocument; — однократно
TMPRange := ActDoc.Tables(1).Cell(1,1).Range;
TMPRange.InsertAfter('текст');
В общем, все дело в том, что при вызове строки идут запросы значений свойств, сначала Application, потом ActiveDocement и тд.
Если сделать это однократно, скорость увеличится значительно
A>Небольшой измышлизм на тему subj + идея решения.
A>Меня тоже всегда интересовал вопрос почему экспорт в Word такой медленный. Многие говорили что это из-за IDispatch, многие из-за общего торможения Outprocess COM серверов.Но тем не менее другие программы здесь работают идеально, только Word & Excel тормозит.
A>Как то очень давно я услышал от одного человека такое мнение: "Зачем этот COM вообще нужен, ведь DDE работает быстрее, весь эффективный экспорт в офис должен быть на основе DDE, именно из-за этого его до сих пор поддерживают Word и Excel".
A>У меня этот тезис вызвал сильные сомнения, но я решил его проверить. Получилось естественно абсолютно такая же производительность. Но при этом я получил любопытный побочный эффект который и побудил меня написать данное сообщение.
A>При работе с DDE ты просто передаешь Word строку c синтаксисом WordBasic, а он ее выполняет. В принципе это логично сделать похожий синтаксис, но если например передать неправильную строку то будет интересная бага. Отладчик Word остановится внутри макроса состоящей из единственной строки — той которую ты передал. Т.е. получается следующее что ты передаешь строку по DDE, word ее парсит и выполняет, т.е. Parser включается при посылке каждой команды, тогда как в макросе Word парсер разбирает весь макрос в самом начале, естественно Word Basic работает быстрее.
A>И вот здесь у меня появилось подозрение: скорость экспорта на основе DDE была абсолютно такой же как и на основе COM. Сам макрос в списке не появляется, поэтому я не смог поймать Word за руку, но похоже при вызове по COM word просто генерит макрос, потом парсит его и выполняет.
A>Решение естественно кривое, но вспомните когда проявился Word. Если вы сейчас решите сделать что-то похожее, то вы сначала реализуете COM сервер, а потом на его основе сделаете скриптовый язык и все будет быстро и клево. Но Word старше технологий COM и DDE на несколько лет, поэтому там COM сервер врезался в готовое приложение. Притом A>Word написан навярняка на голом C(т.к. он опять же старше C++) и в нем наверняка не применялся idl(по той же причине) который сам генерит IDispach, т.е. IDispath там реализован руками. Именно этим объясняется различие возможностей у IDispatch и библиотеки типов Word.
A>Вывод: для того чтобы быстро работать с Word надо поменьше вызывать его через COM. На прошлой работе у ныс было замечательное и быстрое решение когда на Word был написан макрос который делал обратный вызов к нашей программе и тащил данные из нее. Все было очень быстро. К сожалению данный способ вообщем-то мертв т.к. есть много A>побочных эффектов.
A>Мне кажется что самый эффективный метод это генерация макроса Word целиком в вашей программе, а потом передача его Word-у. Большие табличные данные можно закатывать в Variant-ы или в ADO Recordset-ы.
A>Сейчас я вообще не занимаюсь этой темой, по причине того что больше не программирую на Delphi и BCB, и не занимаюсь экспортом в Word, но буду рад продолжить обсуждение этой темы.
Да я стобой обсалютно согласен и сразу написал как я думаю будед дыстрее —
A>Небольшой измышлизм на тему subj + идея решения.
A>Меня тоже всегда интересовал вопрос почему экспорт в Word такой медленный. Многие говорили что это из-за IDispatch, многие из-за общего торможения Outprocess COM серверов.Но тем не менее другие программы здесь работают идеально, только Word & Excel тормозит.
A>Как то очень давно я услышал от одного человека такое мнение: "Зачем этот COM вообще нужен, ведь DDE работает быстрее, весь эффективный экспорт в офис должен быть на основе DDE, именно из-за этого его до сих пор поддерживают Word и Excel".
A>У меня этот тезис вызвал сильные сомнения, но я решил его проверить. Получилось естественно абсолютно такая же производительность. Но при этом я получил любопытный побочный эффект который и побудил меня написать данное сообщение.
A>При работе с DDE ты просто передаешь Word строку c синтаксисом WordBasic, а он ее выполняет. В принципе это логично сделать похожий синтаксис, но если например передать неправильную строку то будет интересная бага. Отладчик Word остановится внутри макроса состоящей из единственной строки — той которую ты передал. Т.е. получается следующее что ты передаешь строку по DDE, word ее парсит и выполняет, т.е. Parser включается при посылке каждой команды, тогда как в макросе Word парсер разбирает весь макрос в самом начале, естественно Word Basic работает быстрее.
A>И вот здесь у меня появилось подозрение: скорость экспорта на основе DDE была абсолютно такой же как и на основе COM. Сам макрос в списке не появляется, поэтому я не смог поймать Word за руку, но похоже при вызове по COM word просто генерит макрос, потом парсит его и выполняет.
A>Решение естественно кривое, но вспомните когда проявился Word. Если вы сейчас решите сделать что-то похожее, то вы сначала реализуете COM сервер, а потом на его основе сделаете скриптовый язык и все будет быстро и клево. Но Word старше технологий COM и DDE на несколько лет, поэтому там COM сервер врезался в готовое приложение. Притом A>Word написан навярняка на голом C(т.к. он опять же старше C++) и в нем наверняка не применялся idl(по той же причине) который сам генерит IDispach, т.е. IDispath там реализован руками. Именно этим объясняется различие возможностей у IDispatch и библиотеки типов Word.
A>Вывод: для того чтобы быстро работать с Word надо поменьше вызывать его через COM. На прошлой работе у ныс было замечательное и быстрое решение когда на Word был написан макрос который делал обратный вызов к нашей программе и тащил данные из нее. Все было очень быстро. К сожалению данный способ вообщем-то мертв т.к. есть много A>побочных эффектов.
A>Мне кажется что самый эффективный метод это генерация макроса Word целиком в вашей программе, а потом передача его Word-у. Большие табличные данные можно закатывать в Variant-ы или в ADO Recordset-ы.
A>Сейчас я вообще не занимаюсь этой темой, по причине того что больше не программирую на Delphi и BCB, и не занимаюсь экспортом в Word, но буду рад продолжить обсуждение этой темы.
Идея понятна. У меня появилась мысль сгенерить полный код скрипта VB (в виде текста), и потом из Delphi его запустить, но я не знаю, как запихнуть этот текст в скрипт Word-а для его активизации. Подскажи ... :wow: :wow:
Здравствуйте peter_login, Вы писали:
PL>Здравствуйте Anatolix, Вы писали:
PL>Идея понятна. У меня появилась мысль сгенерить полный код скрипта VB (в виде текста), и потом из Delphi его запустить, но я не знаю, как запихнуть этот текст в скрипт Word-а для его активизации. Подскажи ...
У меня было вот так, код на C++ Builder но разберешься.
Работать надо обязательно через IDispatch т.е. с вариантами
т.к. код с использованием TypeLibrary не будет работать с
Microsoft Office Standart Edition, тогда как этот работает везде.
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR cmdline, int)
{
Variant WordApplication,macro;
AnsiString cmd=cmdline;
bool batchmode=cmd.UpperCase().Pos("/BATCH");
try
{
Application->Initialize();
Application->ShowMainForm=false;
Application->CreateForm(__classid(THiddenForm), &HiddenForm);
WordApplication=CreateOleObject("Word.Application");
int Count=WordApplication.OlePropertyGet("VBE").OlePropertyGet("ActiveVBProject").OlePropertyGet("VBComponents").OlePropertyGet("Count");
int num=0;
for(int i=1;i<=Count;i++)
{
AnsiString foo=WordApplication.OlePropertyGet("VBE").OlePropertyGet("ActiveVBProject").OlePropertyGet("VBComponents").OleFunction("Item",i).OlePropertyGet("Name");
if (foo=="NewMacros")
{
macro=WordApplication.OlePropertyGet("VBE").OlePropertyGet("ActiveVBProject").OlePropertyGet("VBComponents").OleFunction("Item",i);
num=i;
break;
}
}
if (macro.Type()!=varDispatch)
{
macro=WordApplication.OlePropertyGet("VBE").OlePropertyGet("ActiveVBProject").OlePropertyGet("VBComponents").OleFunction("Add",vbext_ct_StdModule);
num=Count+1;
HiddenForm->Memo1->Lines->Add("");
HiddenForm->Memo1->Lines->Add("Sub renameself()");
HiddenForm->Memo1->Lines->Add(AnsiString("VBE.ActiveVBProject.VBComponents.Item(")+num+").Name = \"NewMacros\"");
HiddenForm->Memo1->Lines->Add("End Sub");
macro.OlePropertyGet("CodeModule").OleProcedure("AddFromString",StringToOleStr(HiddenForm->Memo1->Text));
WordApplication.OleProcedure("Run",AnsiString(macro.OlePropertyGet("CodeModule").OlePropertyGet("Name"))+".renameself");
if (!batchmode) ShowMessage("Взаимодействие с Word настроено.");
}
else
{
if (!batchmode) ShowMessage("Взаимодействие с Word уже настроено.");
}
macro=Unassigned;
WordApplication.OleProcedure("Quit");
}
catch (Exception &exception)
{
if (!batchmode) ShowMessage("Взаимодействие с Microsoft Word не может быть настроено.\r\n Скорее всего Word на вашей машине не установлен.\r\n Установите Word и запустите WordConnect.exe");
}
Строка
int Count=WordApplication.OlePropertyGet("VBE").OlePropertyGet("ActiveVBProject").OlePropertyGet("VBComponents").OlePropertyGet("Count");
Любая проблема дизайна может быть решена введением дополнительного абстрактного слоя, за исключением проблемы слишком большого количества дополнительных абстрактных слоев
Здравствуйте Anatolix, Вы писали:
A>Здравствуйте peter_login, Вы писали:
PL>>Здравствуйте Anatolix, Вы писали:
PL>>Идея понятна. У меня появилась мысль сгенерить полный код скрипта VB (в виде текста), и потом из Delphi его запустить, но я не знаю, как запихнуть этот текст в скрипт Word-а для его активизации. Подскажи ... :wow: :wow:
A>У меня было вот так, код на C++ Builder но разберешься. A>Работать надо обязательно через IDispatch т.е. с вариантами A>т.к. код с использованием TypeLibrary не будет работать с A>Microsoft Office Standart Edition, тогда как этот работает везде.
A>
A>WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR cmdline, int)
A>{
A> Variant WordApplication,macro;
A> AnsiString cmd=cmdline;
A> bool batchmode=cmd.UpperCase().Pos("/BATCH");
A> try
A> {
A> Application->Initialize();
A> Application->ShowMainForm=false;
A> Application->CreateForm(__classid(THiddenForm), &HiddenForm);
A> WordApplication=CreateOleObject("Word.Application");
A> int Count=WordApplication.OlePropertyGet("VBE").OlePropertyGet("ActiveVBProject").OlePropertyGet("VBComponents").OlePropertyGet("Count");
A> int num=0;
A> for(int i=1;i<=Count;i++)
A> {
A> AnsiString foo=WordApplication.OlePropertyGet("VBE").OlePropertyGet("ActiveVBProject").OlePropertyGet("VBComponents").OleFunction("Item",i).OlePropertyGet("Name");
A> if (foo=="NewMacros")
A> {
A> macro=WordApplication.OlePropertyGet("VBE").OlePropertyGet("ActiveVBProject").OlePropertyGet("VBComponents").OleFunction("Item",i);
A> num=i;
A> break;
A> }
A> }
A> if (macro.Type()!=varDispatch)
A> {
A> macro=WordApplication.OlePropertyGet("VBE").OlePropertyGet("ActiveVBProject").OlePropertyGet("VBComponents").OleFunction("Add",vbext_ct_StdModule);
A> num=Count+1;
A> HiddenForm->Memo1->Lines->Add("");
A> HiddenForm->Memo1->Lines->Add("Sub renameself()");
A> HiddenForm->Memo1->Lines->Add(AnsiString("VBE.ActiveVBProject.VBComponents.Item(")+num+").Name = \"NewMacros\"");
A> HiddenForm->Memo1->Lines->Add("End Sub");
A> macro.OlePropertyGet("CodeModule").OleProcedure("AddFromString",StringToOleStr(HiddenForm->Memo1->Text));
A> WordApplication.OleProcedure("Run",AnsiString(macro.OlePropertyGet("CodeModule").OlePropertyGet("Name"))+".renameself");
A> if (!batchmode) ShowMessage("Взаимодействие с Word настроено.");
A> }
A> else
A> {
A> if (!batchmode) ShowMessage("Взаимодействие с Word уже настроено.");
A> }
A> macro=Unassigned;
A> WordApplication.OleProcedure("Quit");
A> }
A> catch (Exception &exception)
A> {
A> if (!batchmode) ShowMessage("Взаимодействие с Microsoft Word не может быть настроено.\r\n Скорее всего Word на вашей машине не установлен.\r\n Установите Word и запустите WordConnect.exe");
A> }
A>
A>Строка A>
A>int Count=WordApplication.OlePropertyGet("VBE").OlePropertyGet("ActiveVBProject").OlePropertyGet("VBComponents").OlePropertyGet("Count");
A>
A>на дельфи выглядит просто как
A>
A>WordApplication.VBE.ActiveVBProject.VBComponents.Count
A>
A>где WordApplication это Variant
Попробую разобраться.
Петр :maniac:
Re[7]: Быстрый экспорт в Word
От:
Аноним
Дата:
18.04.04 09:39
Оценка:
Здравствуйте, peter_login, Вы писали:
A>> WordApplication=CreateOleObject("Word.Application"); A>> int Count=WordApplication.OlePropertyGet("VBE").OlePropertyGet("ActiveVBProject").OlePropertyGet("VBComponents").OlePropertyGet("Count");
после выполнения последней строки вываливается Access Violation. Из-за чего это может быть?