UnDiUdin
UnDiUdin

Reputation: 15404

Insert rtf text in a word document

I am using OLE Search Replace to replace "placeholder tags" with content stored in db fields into a Word docuemnt. I use a technique similar to what disussed here.

THis works but of course it doesn't for rtf fields. I have db fields containing rtf data and if a do search replace I will get the full rtf code, so instead of seeing

Hello World

I see something like

{\rtf1\ansi\ansicpg1252\deff0\deflang1040 \viewkind4\uc1\pard\sa200\sl276\slmult1\lang16\b\f0\fs22 Hello \i World\b0\i0\par }

Did anyone already solved the problem? Searching on StackOverflow I found a trick that uses the clipboard. Note: I don't use bookmarks, this example uses bookmarks, I simply have my tags defined as plain text like '' and when I find '' in my search and replace loop I replace the text.

UPDATE: Do you see any prolem in this clipboard trick?

Do you have other ideas and can suggest other solutions?

Upvotes: 3

Views: 3666

Answers (2)

Ken White
Ken White

Reputation: 125757

Here's a post I saved from ages ago. It was posted by Dr. Peter Below of TeamB to the old Borland Delphi newsgroups, but it's still applicable today. It shows how to use the EM_STREAMIN and EM_STREAMOUT messages and related callback to put RTF text into and copy out of a TRichEdit.

Uses RichEdit;

Type
  TEditStreamCallBack = function (dwCookie: Longint; pbBuff: PByte;
    cb: Longint; var pcb: Longint): DWORD; stdcall;

  TEditStream = record
    dwCookie: Longint;
    dwError: Longint;
    pfnCallback: TEditStreamCallBack;
  end;

function EditStreamInCallback(dwCookie: Longint; pbBuff: PByte;
 cb: Longint; var pcb: Longint): DWORD; Stdcall;
var
  theStream: TStream;
  dataAvail: LongInt;
begin
  theStream := TStream(dwCookie);
  with theStream do begin
    dataAvail := Size - Position;
    Result := 0; {assume everything is ok}
    if dataAvail <= cb then begin 
      pcb := Read(pbBuff^, dataAvail); 
      if pcb <> dataAvail then  //couldn't read req. amount of bytes
        result := E_FAIL; 
    end 
    else begin
      pcb := Read(pbBuff^, cb); 
      if pcb <> cb then 
        result := E_FAIL; 
    end;
  end;
end;


Function EditStreamOutCallback(dwCookie: Longint; pbBuff: PByte;
    cb: Longint; var pcb: Longint): DWORD; stdcall;
 var
   theStream: TStream;
 begin
   theStream := TStream(dwCookie);

   with theStream do begin
     If cb > 0 Then 
       pcb := Write(pbBuff^, cb);
     Result := 0;
   end;
 end;

Procedure GetRTFSelection( aRichEdit: TRichEdit; intoStream: TStream );
Var
  editstream: TEditStream;
Begin
  With editstream Do Begin
    dwCookie:= Longint(intoStream);
    dwError:= 0;
    pfnCallback:= EditStreamOutCallBack;
  end;
  aRichedit.Perform( EM_STREAMOUT, SF_RTF or SFF_SELECTION, longint(@editstream));
End;

Procedure PutRTFSelection( aRichEdit: TRichEdit; sourceStream: TStream );
Var
  editstream: TEditStream;
Begin
  With editstream Do Begin
    dwCookie:= Longint(sourceStream);
    dwError:= 0;
    pfnCallback:= EditStreamInCallBack;
  end;
  aRichedit.Perform( EM_STREAMIN, SF_RTF or SFF_SELECTION, longint(@editstream));
End;

Upvotes: 0

Andreas
Andreas

Reputation: 1364

I would suggest to use the Selection.InsertFile instead. Here is an example that shoud do what you want, it finds "placeholder" and inserts a rtf file. Save your rtf to a temp-file before...

 procedure TForm1.Button1Click(Sender: TObject);
var
  Fword,FDocument,FFindObject:OleVariant;
  Filename:String;

begin
   Filename := 'C:\temp\test.doc';
   Fword := CreateOleObject('Word.Application');
   FDocument := Fword.Documents.Add(Filename);
   FFindObject := FDocument.ActiveWindow.Selection.Find;
   Fword.visible := true;
   FFindObject.ClearFormatting;
   FFindObject.Replacement.ClearFormatting;
   FFindObject.Text := 'placeholder';
   FFindObject.Forward := True;
   FFindObject.Replacement.Text := '';
   FFindObject.Wrap := 1;
   FFindObject.MatchCase := False;
   FFindObject.MatchWholeWord := False;
   FFindObject.MatchWildcards := False;
   FFindObject.MatchSoundsLike := False;
   FFindObject.MatchAllWordForms := False;

   if FFindObject.Execute() then Fword.selection.InsertFile('C:\temp\test.rtf')   
end; 

Upvotes: 1

Related Questions