![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Подскажите как правильно выводить отчет в Word
azamatufa © (2010-07-13 08:47:00)Есть шаблон в котором есть куски текста ключевые (#familia$ #otchestvo$)
Делаю так:
W := CreateOleObject('Word.Application');
W.Documents.Open('rep_blank.rtf');
.....ищу ключевые тексты, заменяю их данными....
W.ActiveDocumnt.SaveAs('rep_done.rtf')
W.Quit;
W.Free;
ShellExecute(handle,'open',pchar('rep_done'),'','',1);
Открывается Отчет. Далее еще раз жму кнопку отчет. Пытается сделать SaveAs - но файл занят. Выходит окно сохранить 'rep_blank.rtf' ? (ведь юзер может нажать Да и запороть шаблон).
Поделитесь опытом, Спасибо!
azamatufa (2010-07-13 15:31:00) [1]Удалено модератором
ixen (2010-07-13 15:21:00) [2]> расскажи о преимуществах...?
тебе уже написали в 12 и 13 посту
azamatufa (2010-07-13 15:12:00) [3]а что дает дот?
если я скажу W.OpenFile (dot)
что будет?
расскажи о преимуществах...?
ixen (2010-07-13 15:06:00) [4]> спасибо! действительно можно защититься при помощи расширения
> rt!
используй dot
azamatufa (2010-07-13 15:02:00) [5]
> ixen
спасибо за unassigned!
> Двенадцать
спасибо! действительно можно защититься при помощи расширения rt!
ixen (2010-07-13 15:00:00) [6]> W.Free;
его освобождают не с помощью free, а w:=unassigned;
Anatoly Podgoretsky (2010-07-13 14:56:00) [7]Я использую сервера с соответствующей закладки, это СОМ сервера, а не надшлепка в виде OLE
Anatoly Podgoretsky (2010-07-13 14:55:00) [8]Перейти на Ворд, с RTF, там ничего не надо сохранять для печати, кроме того Ворд поддерживает шаблоны *.dot как раз для того, что бы не испортить оригинал. Далее есть свойство подавления предупреждений. Кроме того очень легко запретить повторный запуск документа. Я правда с Вордом не работал, работал с Экселем, но ДОМ один и тот же.
ixen (2010-07-13 14:49:00) [9]> W.Documents.Open('rep_blank.rtf');
и почему у тебя шаблон в формате rtf ... есть специальный тип для шаблонов *.dot ... и этот файл пользователь не сможет пересохранить.. так как сформируется новый документ на основе dot файла..
ixen (2010-07-13 14:44:00) [10]> ShellExecute(handle,'open',pchar('rep_done'),'','',1);
Зачем документ открывать через ShellExecute? Не проще ли после того как он сформирован сделать:
w.visible:=true;
w.activate;
w:=unassigned;
Двенадцать (2010-07-13 13:40:00) [11]вариант еще
'rep_blank.rtf' держать как 'rep_blank.rt'
переименовывать в temp директорию как GetGUID+'rep_blank.rtf', и с ним работать
azamatufa (2010-07-13 13:27:00) [12]Юрий, а как бы "все" поместить в один perort.pas
чтоб из формы Form1 лишь вызывать..?
так, процедура ThreadTerminated(Sender: TObject); , помещенная в report.pas
ругается на не соответствие типов (method pointer vs simple procedure..)
да, не в ник я в ООП, видимо...
подумаю сделать по-тупому:
try
удалить файл "готовый_отчет.doc"
удалить файл "~готовый_отчет.doc" (ну на всякий пожарный..)
except
не могу удалить (файл занят) - закройте отчет...
exit;
end;
W.CreateOle Word
W.open шаблон
W. напихать данными
w,saveAs "готовый отчет"
W.Quit;
тоже вариант...?
Юрий Зотов (2010-07-13 10:27:00) [13]Ну да. Идея в том, чтобы не дать юзеру второй раз нажать кнопку, пока не закроет Word.
azamatufa (2010-07-13 10:18:00) [14]d:\temp\Doc.doc - это уже готовый файл?
т.е.
1. я создаю CreateOleObject(Word..) пихаю туда данные..
2. Save AS
3. W.Close; W.Free
и потом Вашим методом создаю поток и открываю готовый файл.... так?
(при этом дизаблю кнопку)
Юрий Зотов (2010-07-13 09:57:00) [15]И еще маленькая поправка, тоже для надежности:
CommandLine := '"' + String(Buff) + '" "' + DocFileName + '"';
Потому что имя файла документа тоже может содержать пробелы.
Юрий Зотов (2010-07-13 09:53:00) [16]И, для надежности - файл шаблона сделать Read-Only.
Юрий Зотов (2010-07-13 09:51:00) [17]Вот так получше будет:
Win32Check(FindExecutable(DocFileName, nil, Buff) > 32);
вместо
FindExecutable(DocFileName, nil, Buff);
Юрий Зотов (2010-07-13 09:43:00) [18]
uses
ShellAPI;
type
TMyThread = class(TThread)
protected
procedure Execute; override;
end;
{ TMyThread }
procedure TMyThread.Execute;
const
DocFileName = 'D:\Temp\Doc.doc';
var
Buff: array[0..MAX_PATH] of char;
CommandLine: string;
SI: TStartupInfo;
PI: TProcessInformation;
begin
ZeroMemory(@Buff, SizeOf(Buff));
FindExecutable(DocFileName, nil, Buff);
CommandLine := '"' + String(Buff) + '" ' + DocFileName;
ZeroMemory(@SI, SizeOf(SI));
SI.cb := SizeOf(SI);
Win32Check(CreateProcess(nil, PChar(CommandLine), nil, nil, False, 0, nil, nil, SI, PI));
CloseHandle(PI.hThread);
WaitForSingleObject(PI.hProcess, INFINITE);
CloseHandle(PI.hProcess)
end;
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
begin
Button1.Enabled := False;
with TMyThread.Create(True) do
begin
FreeOnTerminate := True;
OnTerminate := ThreadTerminated;
Resume
end
end;
procedure TForm1.ThreadTerminated(Sender: TObject);
begin
Button1.Enabled := True
end;
azamatufa (2010-07-13 09:12:00) [19]Я еще хотел донести мысль, что все что создавалось при помощи Create - должно иметь в конце Free (я про W).
Йо...... Юрий, а чууточку подробнее, а?
Благодарю!
Юрий Зотов (2010-07-13 08:58:00) [20]1. Создать второй поток, прописав ему FreeOnTerminate = True.
2. Вместо ShellExecute использовать CreateProcess, вставив этот вызов в метод Execute второго потока.
3. Там же, сразу после после CreateProcess сначала вызвать WaitForSingleObject, а потом 2 раза CloseHandle.
4. В обработчике нажатия на кнопку "Отчет" задизаблить ее.
5. В обработчике OnTerminate второго потока раздизаблить кнопку.