?
Solved

Replace string in blob in Stream

Posted on 2011-03-11
9
Medium Priority
?
1,697 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

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

In our object-oriented world the class is a minimal unit, a brick for constructing our applications. It is an abstraction and we know well how to use it. In well-designed software we are not usually interested in knowing how objects look in memory. …
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
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…
The viewer will learn how to synchronize PHP projects with a remote server in NetBeans IDE 8.0 for Windows.
Suggested Courses
Course of the Month13 days, 23 hours left to enroll

801 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