Solved

Replace string in blob in Stream

Posted on 2011-03-11
9
1,624 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: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say 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 250 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

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

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.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Update (December 2011): Since this article was published, the things have changed for good for Android native developers. The Sequoyah Project (http://www.eclipse.org/sequoyah/) automates most of the tasks discussed in this article. You can even fin…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.
The viewer will learn how to use NetBeans IDE 8.0 for Windows to connect to a MySQL database. Open Services Panel: Create a new connection using New Connection Wizard: Create a test database called eetutorial: Create a new test tabel called ee…

856 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