colonel32
colonel32

Reputation: 43

Loading the output from TOleContainer.SaveAsDocument

I have an existing database with blobs contain OLE compound files. I have a requirement to read these OLE compound files and open them in the Delphi 7 TOleContainer control.

Note that I don't have the source of the app that reads and write to the database. The database remains in active use, so my solution will be used on an ongoing basis, not just for a one-off data extraction.

TOleContainer has a SaveAsDocument method, and by experimentation I have found that, for a given file, this method produces OLE compound files which are identical to those created in the database when that file is added.

However, TOleContainer does NOT have a corresponding LoadFromDocument method. It has other Load* and Create* methods, but none seem capable or suitable for loading the output from SaveAsDocument.

The delphi 7 implementation of SaveAsDocument is this, from the OleCtnrs.pas module:

procedure TOleContainer.SaveAsDocument(const FileName: string);
var
  TempStorage: IStorage;
  PersistStorage: IPersistStorage;
begin
  CheckObject;
  if FModSinceSave then SaveObject;
  FOleObject.QueryInterface(IPersistStorage, PersistStorage);
  if PersistStorage <> nil then
  begin
    OleCheck(StgCreateDocFile(PWideChar(WideString(Filename)), STGM_READWRITE
      or STGM_SHARE_EXCLUSIVE or STGM_CREATE, 0, TempStorage));
    OleCheck(OleSave(PersistStorage, TempStorage, False));
    PersistStorage.SaveCompleted(nil);
  end;
end;

Please provide an implementation of LoadFromDocument which is capable of loading the output from SaveToDocument, and which I can use to patch OleCtnrs.pas. Or else point me to an existing solution.

Thanks!

Upvotes: 1

Views: 2494

Answers (2)

The_Fox
The_Fox

Reputation: 7062

You have to load the file by using TOleContainer.CreateObjectFromFile. Do not use TOleContainer.LoadFromStream/File, that only works with files that are saved with TOleContainer.SaveToStream/File. Files saved that way get a Delphi specific header containing a four byte code (BDOC) and size (and maybe something more).

Upvotes: 1

Ken White
Ken White

Reputation: 125620

According to the documentation for Delphi 2007 (should be the same for ), you can use 'TOleContainer.LoadFromStream'. From the Delphi 7 help file (emphasis mine):

Call LoadFromStream to load an OLE object from a stream. If OldStreamFormat is true, LoadFromStream loads OLE objects saved by a TOleContainer object as well as OLE objects saved using the current format; if OldStreamFormat is false, LoadFromStream will not load OLE objects saved by the library. If there's already an OLE object in the container, it is destroyed and any changes the user made to it are discarded.

Upvotes: 0

Related Questions