Delphi XE2 - handling blob fields - delphi

We are trying to make our app unicode compatible and we are migrating from delphi 2007 to delphi xe2, we came across few issues and need suggestions regarding them
1) one change is to store blob data having unicode strings in database
We store huge xml data as blob in database, but in latest delphi version(xe2), blob is treated as an array of bytes. So what should be done to store blob data in database, have tried like converting Param.AsBlob := WideBytesOf(xml) but that doesn't seem to work.
2) Also we use HyperString from EFD systems for faster string manipulations, but now the unicode version of this library is not available, have compiled the code by changing the ansistring to string and tried to modify few assembly language instructions but was succesful with only few till now, so can any one suggest any alternative for faster string manipulations

I was searching the internet about half a year how to properly put a Blob in a Database and i found one sollution that worked for me perfectly maybe it will help you also:
Image - TcxImage component
MainQuery - TQuery component
MainQueryPicture - its a Blob field in from the database stored in the Query component through the Field Editor
ImagePath - String variable which hold the path to the image file
MainQuery.Edit;
if Image.Picture.Graphic <> nil then //if there is an image loaded to the component
begin
MainQueryPicture.LoadFromFile(ImagePath); //load the image to a blob field
end;
MainQuery.Post; //post any changes to the table
Hope it helps.

Related

Images in formatted text do not show in DBRichEdit

Using Delphi 11.1 and MySQL ver 8
When reading formatted text stored in a MySQL BLOB feild with TADOQuery and show it in a DBRichEdit the text shows but not the embedded images.
The text with images is saved to the database from a RichEdit via TStringStream to a blob field in the database.
If I use same data but a TStringStream
"MyText := TStringStream.Create(ADOQuery.FieldByName('MyBlobField').AsString);"
and load it to a TRichEdit with
"RichEdit1.Lines.LoadFromStream(MyText)"
the images are showing as they should.
Why is it not working when using TDBRichEdit directly connected to the field with a DataSource?
Regards
Dag

Setting DateTime format in Delphi with Firedac compatible with BDE Application

I am migrating my application from Delphi2007 and BDE to Delphi 10.4 and Firedac. The new application is in testing, the old app is still there for backup, in case the new application fails.
So, I have 2 applications talking to the same database, one with Firedac, the other with BDE.
The following happens:
As soon as Firedac saves a DateTime field (date + time), that record can no longer be changed in the BDE application. (I use TQuery->DatasetProvide->TClientDataset, updatemode WhereAll, no persistent fields in the TQuery)
Probably, Firedac stores the time-part in a format that confuses the BDE/Datasetprovider.
Is it possible to make Firedac store time in a format the BDE does understand?
I know, the solution could be : adding persistent fields (> 100 tables), and setting the providerflag to pfInkey for all primary keys, and adding datasetproviders with updatemode "whereKeyOnly", but I do not want to change that much and spend so much time on the (very big) old (and soon to be deprecated) application that uses BDE.
I tried mappingrules in Firedac. I added 2 rules:
DateTimeStamp-> DateTime, DateTime -> DateTime.
For both rules I tested with values of PrecMax of 4,6,8. I thought maybe this way the time-value is stored with less precision, but this had no effect. Maybe some other value or mapping?
ADDITION
Editing the field with a dbExpress TSQLCOnnection instead of BDE works.
The default persistent field with TQuery is TDateTime, with dbExpress: TsqlTimeStamp. It seems like the "TDateTime" field is incompattible with values stored as a timestamp. The error is raized when apllying updates. Fetching the data is no problem.

Save OLE Embedded documents in Outlook email to file

I am using late binding to connect to MS Outlook and to open and extract info from outlook emails using the MailItemobject.
I am trying to save attachments to file. This is fairly straightforward in most instances using the Attachment object and its SaveAsFile method.
However, it does not work where the Attachment Type is olOLE. I believe this only relates to documents embedded in emails created in RTF format (hopefully few and far between nowadays).
Via the Attachment object it is possible to access MAPI properties not exposed by the object model using its PropertyAccessor.
The relevant MAPI property for OLE objects is PR_ATTACH_DATA_OBJ, which can be accessed using the PropertyInspector as in the following example:
Function SaveOLEAttachmentToFile(Attachment:Variant; fn:String): boolean;
var
OPA, PropName : Variant;
begin
Result := false;
OPA := Attachment.PropertyAccessor;
PropName := 'http://schemas.microsoft.com/mapi/proptag/0x3701000D '; //PR_ATTACH_DATA_OBJ
?????? := OPA.GetProperty(PropName);
end;
I am stuck at this point as I can't know work out what Delphi type to save the data to and I am not even sure this is possible having read the MS documentation (Click here). PR_ATTACH_DATA_OBJ returns a PT_OBJECT. I am hoping that this object contains the raw data which (if I could work out how to access it in Delphi) can be simply saved to a file. However, the documentation suggests it may not be that simple and it's possible I may have to work with Extended MAPI. I have spent a few hours researching the latter with no concrete result other than a headache. I appreciate I could use Redemption, but I don't want to use a third party tool for something which is fairly minor in the round.
If anyone can advise as to a data type to hold the PT_OBJECT from which it can be simply saved to file that would be my route one.
Failing that, if I need to dig deeper into MAPI, I would be grateful if anyone could clarify/amplify my research so far. I have the following steps:
Initialize MAPI.
Get an IMAPIPROP interface. I think I should be getting the interface from my Attachment object and the following seems to work (ie compiles and executes without problems): MAPIPROP := IUnknown(Attachment.MAPIObject) as IMAPIPROP. Failing that, I would have to cast the parent MailItem to IMAPIPROP interface and work my way down to the attachment via GetAttachmentTable.
Load the attachment data into an IStream: if Succeeded(MAPIPROP.OpenProperty(PR_ATTACH_DATA_OBJ, IStream, STGM_READ, 0, IUnknown(SourceStream)) then
Extract the data from the IStream and save to file
I have failed to get as far as point 3 as something would seem to be wrong with my initial casting to IMAPIPROP albeit it does not cause any violations. I have tried reading a single property from the MailItem cast to IMAPIPROP using the following code:
if (Succeeded(HrGetOneProp(MAPIPROP, PR_SUBJECT, Prop))) then
And I get an access violation. Likewise if I cast the Attachment object and query an attachment property I also get a violation. I don't think the problem lies with the call to HrGetOneProp, I think it has to be the casting to IMAPIPROP.
Any pointers re the above would be greatly appreciated.
Not quite an answer to my question, but I have thought of an alternative solution. What I am ultimately trying to do is convert a msg email as a pdf. To do that I need to extract the body and then somehow insert the embedded images. With an html email this seemed pretty straightforward ((1) extract all the attachments to a folder, (2) parse the html body for references to SRC IMG and update the location of the image to reference the saved files and (3) save the edited html body to file and open it in Word and save as PDF).
RTF emails cannot be handled in this way. However, for my specific problem there is a much easier way to achieve what I need for all email types using Outtlook and Word.
Use the MailItem.SaveAs function and save the email in either html format or mthml. The former format will save all embedded images to a sub-folder (in png and jpg formats) should you need them for any other reason. once you have your html file, open it with Word and save to PDF.
If Office is not a solution then you need to figure Istorage or use one of the Extended MAPI solutions such as Redemption.
For Delphi users there are also the following commercial offerings that I have come across in my recent travels:
IMIBO
Scalabium
Rapware
I did come across one more solution which I can't find at the moment! Will post an update if I do.
PropertyAccessor (and the Outlook Object Model in general) does not handle PT_OBJECT type properties.
What you need to do is open the PR_ATTACH_DATA_OBJ property as IStorage, and then extract the data from there (it depends on the actual type of the attachment). You can see the data in the streams in OutlookSpy (I am its author) - select the message, click IMessage button on the OutlookSpy rubbon, go to the GetAttachmentTable tab, double click on the attachment to open it, select the PR_ATTACH_DATA_OBJ property, right click, select IMAPIProp::OpenProperty, then IStorage.
If using Redemption (I am also its author) is an option, its version of RDOAttachment.SaveAsFile handles OLE attachment for the most popular formats (Word, Excel, bitmap, Power Point, Adobe PDF, etc.) - create an instance of the RDOSession object (using either CrealeOleObject or RedemptionLoader) and use RDOSession.GetRDOObjectFromOutlookObject method (pass either Attachment or MailItem object) to get back RDOMail or RDOAttachment object respectively.

AnyDAC (FireDAC) - Open transaction after TBlobField.GetAsString

at the moment we are migrating the database component of our Delphi7 application from the BDE components to the AnyDAC (FireDAC) Version 8.0.5 components.
The following prerequisites are given:
On our form we have one TADConnection, one TADQuery and one TADTable. The TADQuery is the MasterSource for the TADTable. No special changes have been made to the settings of the AnyDAC components, so the AutoCommit mode is active.
Furhtermore we have one TDBMemo on our form which is linked to an ftMemo field of the TADTable (Firebird FieldType = Blob / Size = 240 / Subtype = Text)
During the loading of the blob text field content (TBlobField.GetAsString) the TADTable starts automatically an transaction which would not committed.
Is this behavior normal? Do we have any possiblity to avoid this open transaction?
Please note, deactivating of the AutoCommit is no option at the moment.
Any help appreciated.
Yes, that is a normal behavior. So long you are not fetching BLOB data along with the detail tuple, AnyDAC starts an implicit transaction for fetching those BLOB data.

Delphi and attachment files in MS access database

I search many times in Google, SO, and I can't find anything about working with attachment via delphi, so I decide to write this question.
I have a table in .accdb database called Files with those fields:
IDFile PK AutoIncField,
FileName WideStringField,
FilesAttached WideMemoFiled.
How can I save/load files to/from attachment fields using delphi?
Attach files and graphics to the records in your database
The problem here, in delphi the datatype of FilesAttached is TWideMemoField,
when I write ShowMessage(FDTable1FilesAttached.Value); it give just the name of the attachment.
I don't know how to Insert/save files to/from that field using delphi.
It didn't seem that hard to find VBA/C# examples of working with .accdb Attachment fields which should translate fairly easily into Delphi. However, it turned out to be more difficult than I imagined to find something that a) hadn't misunderstood what Attachment fields actually are and b) actually works. Skip to the update section below.
For example, googling
accdb create attachment in vba
gives numerous hits including this one
http://sourcedaddy.com/ms-access/working-with-attachment-fields.html
which you might try as a starting point. It uses MS DAO objects, and includes straightforward code for storing files to Attachment fields and for accessing them. You would need to create a Delphi wrapper unit for the DAO type library, if you don't already have one, using the IDE's Import Type Library
If you would prefer something ADO-based, you might take a look at
https://www.codeproject.com/Questions/843001/Handling-fields-of-Attachment-type-in-MS-Access-us
Update See the function OpenFirstAttachmentAsTempFile in the post by "aspen" (date = 4/11/2012 07:18 am) in this thread
https://access-programmers.co.uk/forums/showthread.php?t=224112&page=2
which shows an apparently successful attempt to extract a file from an attachment field (the thread also contains several other attempts at coding this function).
Note in particular this line
Set rstChild = rstCurrent.Fields(strFieldName).Value ' the .Value for a complex field returns the underlying recordset
which implies that the Value of the attachment field can return a recordset which contains the attached file(s).
Presumably, importing a recent version of the DAO type library into Delphi would allow
a Delphi app to do the same thing, and then one could reverse-engineer the rstChild recordset to see how to populate this field in code. I haven't done that yet, though.

Resources