Getting data from Word

The Word Document object supports the IDataObject Interface. To get data from Word (RTF, text, structured storage etc) the IDataObject must be used. To get a pointer to the IDataObject Interface use QueryInterface. Word documents support the standard formats CF_TEXT and CF_METAFILEPICT as well as a number of other specific formats including RTF and structured storage. For the standard formats the constant values can be used for the value of cfFormat, but for the other formats the Document must be queried using the function EnumFormatEtc. This function will return a list of supported formats. The required format from this list is then passed to the GetData function of the IDataObject interface. It is important to note that the value of cfFormat for the proprietary formats (RTF etc.) is not constant between machines so it must always be found using EnumFormatEtc and not hard coded. For more information on IDataObject and its methods refer to the Win32 programming help files (included with Delphi 4, C++Builder, Visual C++ etc.).

Sample Code

uses
  Word_TLB;

  function GetRTFFormat(DataObject: IDataObject; var RTFFormat: TFormatEtc): Boolean;
  var
    Formats: IEnumFORMATETC;
    TempFormat: TFormatEtc;
    cfRTF: LongWord;
    Found: Boolean;
  begin
    try
      OleCheck(DataObject.EnumFormatEtc(DATADIR_GET, Formats));
      cfRTF := RegisterClipboardFormat('Rich Text Format');
      Found := False;
      while (not Found) and (Formats.Next(1, TempFormat, nil) = S_OK) do
        if (TempFormat.cfFormat = cfRTF) then
        begin
          RTFFormat := TempFormat;
          Found := True;
        end;
      Result := Found;
    except
      Result := False;
    end;
  end;

  procedure GetRTF(WordDoc: _Document);
  var
    DataObject: IDataObject;
    RTFFormat: TFormatEtc;
    ReturnData: TStgMedium;
    Buffer: PChar;
  begin
    if Assigned(WordDoc) then
    begin
      try
        WordDoc.QueryInterface(IDataObject, DataObject);
        if GetRTFFormat(DataObject, RTFFormat) then
        begin
          OleCheck(DataObject.GetData(RTFFormat, ReturnData));
          // RTF is passed through global memory
          Buffer := GlobalLock(ReturnData.hglobal);

          { Buffer is a pointer to the RTF text
            Insert code here to handle the RTF text (ie. save it, display it etc.) }
          GlobalUnlock(ReturnData.hglobal);
        end;
      except
        ShowMessage('Error while getting RTF');
      end;
    end;
  end;