Improve company productivity with a Business Account.Sign Up

x
?
Solved

Replace string in blob in Stream

Posted on 2011-03-11
9
Medium Priority
?
1,853 Views
Last Modified: 2013-11-23
Hi
I have a .doc file stored in Oracle DB as Blob field. From Delphi I fetch it and store in
a BlobStream ... example :
    Field := OracleDataSet.FieldByName('FIELD');
    Stream := OracleDataSet.CreateBlobStream(Field, bmRead);
In the .doc file I have strings like ... #NAME#. I want to replace that with real value.
How can I do that without writing the .doc file to my hard drive.
Later I can open my Stream using OleContainer, but first I want to replace some strings.
Best regards:
Albert Elisson
0
Comment
Question by:Programm
  • 5
  • 4
9 Comments
 
LVL 25

Expert Comment

by:epasquier
ID: 35108687
you can't do that directly, you will have to load your stream into a string first, then replace your #NAME# with your value, and put it back in a TMemoryStream to open it in the OleContainer

Procedure ReplaceAndLoadStream( Stream : TBlobStream ; OleContainer:TOleContainer );
Var
 BlobTxt:ANSIString;
 MemStream:TMemoryStream;
begin
 SetSize(BlobTxt,Stream.Size);
 Stream.ReadBuffer(BlobTxt[1],Stream.Size);
 BlobTxt:=StringReplace(BlobTxt,'#NAME#', 'NewName' , [rfReplaceAll]);
 MemStream:=TMemoryStream.Create;
 MemStream.WriteBuffer(BlobTxt[1],Length(BlobTxt));
 OleContainer.LoadFromStream(MemStream);
 MemStream.Free;
end;

Open in new window

0
 

Author Comment

by:Programm
ID: 35137832
Hi epasquier
Sorry for my late response. I have been so busy in other assignments.
I couldn't get this to work for me.
1. I couldn't find the function SetSize... only SetLength. Was than then function you meant?
2. When I reach OleContainer.LoadFromStream(MemStream) I get an 'Stream read error' error. It crashes on the  'Stream.ReadBuffer(Header, SizeOf(Header));' line in the OleContainer class.
Any ideas?

Best regards:
Albert.
0
 
LVL 25

Expert Comment

by:epasquier
ID: 35140527
yes, that is setLength

you need also to reset the position of the stream before reading from it :

 MemStream:=TMemoryStream.Create;
 MemStream.WriteBuffer(BlobTxt[1],Length(BlobTxt));
MemStream.Position:=0;
 OleContainer.LoadFromStream(MemStream);
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 

Author Comment

by:Programm
ID: 35148347
Hi epasquier
Now I get the error 'Invalid stream format' when I call OleContainer.LoadFromStream(MemStream).

I got this working with call to a new custom function in TOleContainerP whitch is a custom .pas file from another question I posted here and you solved with me brilliantly ( http://www.experts-exchange.com/Programming/Editors_IDEs/Delphi/Q_26861235.html ).
My code is:

 
procedure TfrmAttachmentsDOAStraumur.OpnaStraumEftirSnidmati(qry : TOracleDataSet);
var
  Stream : TStream;
  Field : TField;
  iSizeBefore : integer;
  BlobTxt:ANSIString;
  MemStream:TMemoryStream;
begin
  try

    m_qry := qry;
    Field := qry.FieldByName('BLOB_SNIDMAT');
    Stream := qry.CreateBlobStream(Field, bmRead);
    SetLength(BlobTxt,Stream.Size);
    Stream.ReadBuffer(BlobTxt[1],Stream.Size);
    BlobTxt := StringReplaceP(BlobTxt,'#ATVRNAFN#', 'NewName' , [rfReplaceAll]);
    MemStream := TMemoryStream.Create;
    MemStream.WriteBuffer(BlobTxt[1],Length(BlobTxt));
    MemStream.Position := 0;
    //OleContainerP1.LoadFromStream(MemStream);
    OleContainerP1.CreateObjectFromStream(MemStream);
    OleContainerP1.DoVerb(ovShow);
    Self.ShowModal;
  finally
    FreeAndNil(Stream);
    MemStream.Free;
  end;
end;

Open in new window


I had to customize the function StringReplace. It uses this line ' Offset := AnsiPos(Patt, SearchStr); ' whitch always returns 0. If I used  ' Offset := Pos(Patt, SearchStr); ' ... it worked.


This works great when the replacement string is equal in size to the original string, but if the replacement string is shorter than the original string I get the error:
'The doc file has been corrupted'.
What can I do? We are so close.....

Best regards:
Albert.
0
 

Author Comment

by:Programm
ID: 35150198
Hi epasquier
I got you mixed up with ewangoya in my recent comment who solved my other question with me an I apologize for that.
0
 
LVL 25

Expert Comment

by:epasquier
ID: 35152636
Hi, I think that working on the Doc stream is not a good idea. You would need the complete specification of .DOC file format, if obviously it has some length control of some data structures.

The better idea would be then to load the Doc as it is in the blob field, and use OLE automation to do a Word search & replace in the document
0
 

Author Comment

by:Programm
ID: 35155413
Hi , that is my method today. But it is causing a problem for me because I then have to write my blob field to disk and read it from there. When I close the OleContainer the WINWORD.EXE process is still alive unless i kill it with quit(0). If I have other word documents open at the same time, they get shut down as well without save!!
This is the reason I am trying to open, edit and save my documents without writing them to hard disk.

I have my .doc files stored in blob field in the db as templates. In these templates I have some variables with ## at each side like #NAME#, #ADDRESS# etc.
I replace them with real values.
There must be some way to to this without writing the .doc files to hard disk.
0
 
LVL 25

Accepted Solution

by:
epasquier earned 750 total points
ID: 35156330
if your problem is mainly of closing Word process only if there is no other open document, there is probably a way to check that before calling Quit

I'm about sure that Ole automation, while being a bit of a pain on some details like that, is still the best way of doing things with Office documents.
0
 

Author Closing Comment

by:Programm
ID: 35293123
I did not get a soloution for my problem. That is why I select grade B. Maybe it is a bit harsh on my behalf if it is not possible to solve.
0

Featured Post

Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
The viewer will learn how to use and create keystrokes in Netbeans IDE 8.0 for Windows.
The viewer will learn how to use and create new code templates in NetBeans IDE 8.0 for Windows.

606 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question