Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 20.10.2012, 01:12   #1
spamer
Software Developer
Старожил
 
Аватар для spamer
 
Регистрация: 19.12.2008
Сообщений: 2,070
По умолчанию Конвертация RichText To PlainText через Word интерфейсы. Ошибка.

Всем привет.
Суть задачи - конвертировать *rtf и *doc документы в обычный текст. Все бы ничего, если бы подобных документов было немного, а их около 50 000.
Конвертацию делаю в отдельном потоке, вот код:

Код:

    FMsWord: WordApplication;

...

procedure TRichToPlainConverterThread.InitializeWordApp;
begin
  CoInitialize(nil);
  FMsWord := CoWordApplication.Create;
  try
    MsWord.Visible := False;
    MsWord.DisplayAlerts := wdAlertsNone;
  except
    FinalizationWordApp;
  end;
end;

procedure TRichToPlainConverterThread.FinalizationWordApp;
begin
  if MsWord = nil then
    Exit;
  try
    MsWord.Quit(wdDoNotSaveChanges, EmptyParam, EmptyParam);
  finally
    FMsWord := nil;
    CoUninitialize;
  end;
end;

procedure TRichToPlainConverterThread.Execute;
var
  i: Integer;
begin
  i := 0;
  try
    InitializeWordApp;
    while (not Terminated) and (i < RichTextFiles.Count) do
    begin
      try
        CurrentRichTextFile := RichTextFiles[i];
        CurrentPlainTextFile := DestinationPath + ChangeFileExt(ExtractFileName(CurrentRichTextFile), '.txt');

        MsWord.Documents.Open(CurrentRichTextFile, EmptyParam, EmptyParam, EmptyParam,
          EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
          EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam);
        MsWord.ActiveDocument.SaveAs(CurrentPlainTextFile, wdFormatUnicodeText, EmptyParam,
          EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam,
          EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam, EmptyParam);
        PlainTextFiles.Add(CurrentPlainTextFile);
      finally
        MsWord.ActiveDocument.Close(wdDoNotSaveChanges, EmptyParam, EmptyParam);
        if not Terminated then
          Synchronize(DoConvertProgress);
        Inc(i);
      end;
    end;
  finally
    FinalizationWordApp;
    if not Terminated then
      Synchronize(DoConvertComplete);
    if not Terminated then
      PostMessage(MessageWindow, WM_RICH_TO_PLAIN_CONVERTER_THREAD_DONE, 0, 0);
  end;
end;
Вроде как и работает, но приложение приблизительно после 15 сконвертированных документов падает либо на методе открытия документа, либо на методе сохранения, с ошибкой "EOleException - Недостаточно памяти чтобы закончить операцию.".
Возможно у кого-то есть домыслы с чем может быть связана подобная ошибка?
Будь проще и люди к тебе потянутся

Последний раз редактировалось spamer; 20.10.2012 в 01:28.
spamer вне форума Ответить с цитированием
Старый 20.10.2012, 10:51   #2
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Эти компоненты полны глюков. Попробуйте напрямую через CreateOLEObject('Word.Application') .
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 20.10.2012, 14:23   #3
spamer
Software Developer
Старожил
 
Аватар для spamer
 
Регистрация: 19.12.2008
Сообщений: 2,070
По умолчанию

Цитата:
Эти компоненты полны глюков.
О каких компонентах идет речь? Я же извлек заголовки библиотеки типов и теперь использую стандартные интерфейсы Word.

Цитата:
Попробуйте напрямую через CreateOLEObject('Word.Application') .
Кстати и так пробовал, все равно та же ошибка.
У кого еще какие есть идеи как избавиться от данной ошибки или хотя бы узнать ее причину?
Будь проще и люди к тебе потянутся
spamer вне форума Ответить с цитированием
Старый 20.10.2012, 20:16   #4
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Цитата:
О каких компонентах идет речь?
Возможно я не правильно понял, но они таки есть ...\Delphi7\Ocx\Servers\WordXP.pas. Servers в палитре компонент

Кстати интересная ссыль http://wordexpert.ru/page/u-menya-po...tochno-pamyati
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 20.10.2012, 23:34   #5
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Код:
procedure TRichToPlainConverterThread.FinalizationWordApp;
begin
  if MsWord = nil then
    Exit;
  try
    MsWord.Quit(wdDoNotSaveChanges, EmptyParam, EmptyParam);
  finally
    FMsWord := nil;
    CoUninitialize;
  end;
end;
Сюда бы Try Except для верности.....
А ещё попробуйте MadExcept(freeware), там автор сделал не плохой детектор утечек в памяти.

Последний раз редактировалось Человек_Борща; 20.10.2012 в 23:37.
Человек_Борща вне форума Ответить с цитированием
Старый 21.10.2012, 17:10   #6
spamer
Software Developer
Старожил
 
Аватар для spamer
 
Регистрация: 19.12.2008
Сообщений: 2,070
По умолчанию

Цитата:
Кстати интересная ссыль
Вариант с вирусом отпадает - пробовал на нескольких разных машинах, та же проблема возникает...
Компоненты из поставки Delphi я не использовал...Работаю напрямую...
Цитата:
Сюда бы Try Except для верности
Для какой верности? Как раз таки try-finally и стоит для верности...
Насчет MadExcept - так ведь ошибка, насколько я понимаю, возникает на стороне Word'а, как он мне сможет помочь?
Просто странно как-то, неужели я первый кто столкнулся с подобной проблемой?
Будь проще и люди к тебе потянутся

Последний раз редактировалось spamer; 21.10.2012 в 17:14.
spamer вне форума Ответить с цитированием
Старый 21.10.2012, 18:35   #7
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Цитата:
Для какой верности? Как раз таки try-finally и стоит для верности...
Может лог какой прикрутить?
Возможно, финализация происходит в какой-то момент, где её не должно быть...

Цитата:
Насчет MadExcept - так ведь ошибка, насколько я понимаю
Особых проблем подключения и отключения MadExcept не составляет. Отчет об ошибке и утечках памяти, дадут вам более ясную картину того, где происходит утечка.

Вообще, есть вариант, что система не успевает освобождать память от предыдущих документов. Проверьте рост памяти каким-нибудь диспетчером процессов.
Человек_Борща вне форума Ответить с цитированием
Старый 21.10.2012, 19:32   #8
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Попробовал у себя, поток правда не делал, проблем не наблюдал (Win 7 (64), D7, Office 2003)
Код:
procedure TForm1.Button2Click(Sender: TObject);
const wdDoNotSaveChanges = 0;
      wdFormatUnicodeText =7;
var WordApplication: OLEVariant;
    i: Integer;
begin
  WordApplication:=CreateOLEObject('Word.Application');
  WordApplication.Visible:=False;
  for i:=1 to 100 do begin
    WordApplication.Documents.Open('E:\Otladka.doc');
    WordApplication.ActiveDocument.SaveAs(Format('E:\Otladka\Otladka%d.txt',[i]),wdFormatUnicodeText);
    WordApplication.ActiveDocument.Close(wdDoNotSaveChanges);
  end;
  WordApplication.Quit;
  WordApplication:=Unassigned;
end;
и так (чтобы файлы разные были)
Код:
procedure TForm1.Button3Click(Sender: TObject);
var i: Integer;
begin
  for i:=1 to 100 do
    CopyFile('E:\Otladka.doc',PChar(Format('E:\In\Otladka%d.doc',[i])),True);
end;

procedure TForm1.Button4Click(Sender: TObject);
const wdDoNotSaveChanges = 0;
      wdFormatUnicodeText =7;
var WordApplication: OLEVariant;
    i: Integer;
begin
  WordApplication:=CreateOLEObject('Word.Application');
  WordApplication.Visible:=False;
  for i:=1 to 100 do begin
    WordApplication.Documents.Open(Format('E:\In\Otladka%d.doc',[i]));
    WordApplication.ActiveDocument.SaveAs(Format('E:\Otladka\Otladka%d.txt',[i]),wdFormatUnicodeText);
    WordApplication.ActiveDocument.Close(wdDoNotSaveChanges);
  end;
  WordApplication.Quit;
  WordApplication:=Unassigned;
end;
Только очень медленно. Утечек памяти не заметил. Исходный doc чуть больше 3,5 Mb
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 22.10.2012, 00:58   #9
spamer
Software Developer
Старожил
 
Аватар для spamer
 
Регистрация: 19.12.2008
Сообщений: 2,070
По умолчанию

Парни, спасибо за советы.
Вроде разобрался с проблемой. Та и проблема-то, как оказалось, была вовсе не в моем коде, а все из-за поврежденного/ых doc файла/ов.
Хотя странную ошибку Word райзит...Казалось бы, при чем тут - недостаточно памяти...
Решил просто try-except'ом ловить exception'ы и делать Continue циклу...
Насчет скорости - да, не быстро конечно, но в целом для меня пока это не критично...
И да, таки добавлю логирование...
Будь проще и люди к тебе потянутся

Последний раз редактировалось spamer; 22.10.2012 в 01:12.
spamer вне форума Ответить с цитированием
Старый 22.10.2012, 01:23   #10
eval
Подтвердите свой е-майл
 
Регистрация: 29.08.2012
Сообщений: 4,011
По умолчанию

Цитата:
if not Terminated then
Synchronize(DoConvertComplete);
if not Terminated then
PostMessage(MessageWindow, WM_RICH_TO_PLAIN_CONVERTER_THREAD_D ONE, 0, 0);
фиерично .
eval вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
База данных. Word через Excel. doublek Microsoft Office Excel 2 09.12.2011 16:02
Word через Delphi Valera Помощь студентам 0 06.05.2011 11:52
Работа с Word через Delphi Ele Помощь студентам 0 16.05.2010 20:21
COM-интерфейсы MS Word mitryz Общие вопросы C/C++ 0 04.11.2009 11:18
Файл word через delphi dagarik Общие вопросы Delphi 6 28.11.2007 21:07