открытие документа Winword

Slavaga

В БД (MSSQL) лежит документ word, который нужно открыть в ворде.
Как вариант, можно загрузить файл из БД, сохранить его на диск и потом открыть вордом. Что-то типа:
WordApp->Documents->Open( "файл.doc" );
Вопрос: можно ли каким-нибудь образом загрузить этот файл в Word, не сохраняя его на диске?

gopnik1994

можно через memory stream

stat7984215

А можно немножко поподробнее? Конкретно, интересует, как его в Word засунуть.

gopnik1994

ты среду скажи сначала...

ryshiy28

Тоже интересно, среда MS Visual C++ 6.0
До сих пор проблема решалась с помощью временного файла.

stat7984215

Delphi/С++ Builder, если это имеет значение. Word 2003, документ в WordML.
Вообще, интересует какой есть механизм в ворде для того, чтобы открыть документ не из
файла на диске.
Пробовал:

Application.Documents.Add;
Application.ActiveDocument.Content.InsertXML(..);

но результат получается немного не тот, что нужен (например, левый отступ на странице остается тот, что по умолчанию для создаваемого документа, а не тот, что во вставляемом документе)

ryshiy28

Класс MemoryStream определен только в .NET Framework Class Library (или ты имел ввиду другой memory stream?)

yolki

Попробуй покопать в сторону TStreamAdapter и IPersistStreamInit
Вордовский документ может наверное поддерживать и такой интерфейс.
Например, в TWebBrowser можно грузить из стрима:
(WB.Document as IPersistStreamInit).Load(AdStream);

stat7984215

Попробуй покопать в сторону TStreamAdapter и IPersistStreamInit
Вордовский документ может наверное поддерживать и такой интерфейс.
Попробовал, при запросе IPersistStreamInit Word.Document возвращает E_NOINTERFACE
Погуглив, нашел что Word.Document поддерживает IPersistStorage, и это возможно, единственный способ загрузить документ не из файла. Но у меня документ в XML, а его, как его запихнуть в IStorage я не представляю

gopnik1994

VCL - великая кладезь кода....
procedure TOleContainer.LoadFromStream(Stream: TStream);
var
DataHandle: HGlobal;
Buffer: Pointer;
Header: TStreamHeader;
begin
DestroyObject;
Stream.ReadBuffer(Header, SizeOf(Header;
if (Header.Signature <> StreamSignature) and not FOldStreamFormat then
raise EOleError.CreateRes(@SInvalidStreamFormat);
DataHandle := GlobalAlloc(GMEM_MOVEABLE, Header.DataSize);
if DataHandle = 0 then OutOfMemoryError;
try
Buffer := GlobalLock(DataHandle);
try
Stream.Read(Buffer^, Header.DataSize);
finally
GlobalUnlock(DataHandle);
end;
OleCheck(CreateILockBytesOnHGlobal(DataHandle, True, FLockBytes;
DataHandle := 0;
OleCheck(StgOpenStorageOnILockBytes(FLockBytes, nil, STGM_READWRITE or
STGM_SHARE_EXCLUSIVE, nil, 0, FStorage;
OleCheck(OleLoad(FStorage, IOleObject, Self, FOleObject;
FDrawAspect := Header.DrawAspect;
InitObject;
UpdateView;
except
if DataHandle <> 0 then GlobalFree(DataHandle);
DestroyObject;
raise;
end;
end;

портировать на VS предлагаю самостоятельно. API тот же...
суть кода - не надо пытаться заставить оле-объект загрузить что-то, надо его изначально создавать из потока, благо OLE позволяет...
Оставить комментарий
Имя или ник:
Комментарий: