3

我正在使用 Delphi 7 尝试将 Word 文档加载到 OLEContainer 中。该程序在终端服务 (Windows 2003) 环境中运行。

以下代码为某些用户生成错误:

procedure TForm1.Button1Click(Sender: TObject);
begin
  OleContainer1.CreateObjectFromFile('c:\tmp\test.doc', false);
end;

它是一个简单的应用程序,带有一个 OLEContainer 和一个窗体上的按钮。c:\tmp\test.doc 是 Word 2003 文档。

对于某些用户,此代码会生成错误

无效的 FORMATETC 结构。

对于其他人则不然。所有用户都在同一台终端服务器上运行,因此运行同一程序访问同一 Word 文档。此外,所有用户都是使用脚本创建的,因此它们具有完全相同的设置,当然除了用户名等。

我尝试让所有用户成为管理员,但这并没有改变行为。

任何人都知道问题可能是什么?

4

2 回答 2

0

我相信 Word 自动化支持 IPersistFile,这应该提供另一种加载文件的方法。在这里查看更多。

于 2012-11-29T17:13:37.893 回答
0

经过一些测试,我发现 TOleContainer.LoadFromStream 方法始终有效。问题是这个方法需要一个 OLE 流,而不是一个包含 word 文档的流。我对 OLE 流的格式进行了逆向工程,并通过编写页眉、word 文档和页脚手动创建了一个。看起来,页脚由偶数 256 字节的 ASCII-0 组成。

以下是创建 OLE 流的代码:

function OLEStreamFromDoc(const inDocFileName : String) : TMemoryStream;
var
  aFileStream : TMemoryStream;
  aPadding    : Array[1..256] of byte;
  aHeader     : Array[1..12] of byte;
  aSize       : int64;
  i           : integer;
begin
  for i := low(aHeader) to High(aHeader) do
    aHeader[i] := 0;

  for i := low(aPadding) to High(aPadding) do
    aPadding[i] := 0;

  Result := TMemoryStream.Create;
  aFileStream := TMemoryStream.Create;
  try
    aFileStream.LoadFromFile(inDocFileName);
    aFileStream.Seek(0,0);
    aSize := aFileStream.Size + SizeOf(aPadding);

    aHeader[1] := Ord('B');
    aHeader[2] := Ord('D');
    aHeader[3] := Ord('O');
    aHeader[4] := Ord('C');
    aHeader[5] := 1;
    aHeader[9]  := aSize and 255;
    aHeader[10] := (aSize shr 8) and 255;
    aHeader[11] := (aSize shr 16) and 255;
    aHeader[12] := (aSize shr 24) and 255;
    Result.Write(aHeader, SizeOf(aHeader));
    aFileStream.SaveToStream(Result);
    Result.Write(aPadding, sizeof(aPadding));
    Result.Seek(0,0);
  finally
    aFileStream.Free;
  end;
end;
于 2012-12-03T07:43:21.560 回答