Solved

Replace string in blob in Stream

Posted on 2011-03-11
9
1,612 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
Comprehensive Backup Solutions for Microsoft

Acronis protects the complete Microsoft technology stack: Windows Server, Windows PC, laptop and Surface data; Microsoft business applications; Microsoft Hyper-V; Azure VMs; Microsoft Windows Server 2016; Microsoft Exchange 2016 and SQL Server 2016.

 

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

Optimizing Cloud Backup for Low Bandwidth

With cloud storage prices going down a growing number of SMBs start to use it for backup storage. Unfortunately, business data volume rarely fits the average Internet speed. This article provides an overview of main Internet speed challenges and reveals backup best practices.

Question has a verified solution.

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

Suggested Solutions

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
How to install Selenium IDE and loops for quick automated testing. Get Selenium IDE from http://seleniumhq.org Go to that link and select download selenium in the right hand columnThat will then direct you to their download page.From that page s…
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…

803 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