Add an attachment to an Excel spreadsheet

Hi,

I use TMS Flexcel VCL to create the Excel spreadsheet, but to add an attachment to the created Excel spreadsheet I use Excel Automation in my Delphi code. This works on my computer, but not on the client computer due to security restrictions. As far as I can tell, I did not find a way to add an attachment using TMS Flexcel. Have I overlooked the possibility that it can be done using TMS Flexcel ? If so, I would like to know how? If not, can this be a new feature for TMS Flexcel. If this feature cannot be added, then, do you know of any Delphi component or library that can do this? I have searched and searched, but could not find it. So, this may be a unique feature to add.

Best regards,
Fons

Hi,
What do you refer to with adding an attachment to the Excel spreadsheet? What kind of attachment?
Can you send me a file showing what you want, or the VBA code you use to add it? If you prefer not to post the file here, you can send it to adrian@tmssoftware.com

Hi Adrian,

A picture probably explains it best. I am Dutch, but if you know Excel you will recognize it. For example, I want to enclose a PDF file as an object in Excel. I have SumatraPDF installed, but if I would have AcrobatReader than the familiar red icon would be shown instead of the SumutraPDF yellow icon.

So, with attachment I mean to enclose / embed a file object in Excel. Hope the example is clear. Other than with Excel Automation, which causes issues, I do not know how to do this without using Excel itself. I am looking for something that uses pure Delphi code.

Thanks in advance.

Fons

Screenshot

Ah, you were sepeaking about an embedded OLE object. Thanks for the screenshot, I hadn't realized it was about that.

Sadly as you've said we don't support embedding OLE objects with the API (we preserve them, but not add new ones), mostly because it is an undocumented binary blob. To be clear, what you have there is not a pdf document embedded in the document, but an OLE/COM object that is activated with a pdf reader.

I think the reader you have is fox, because of the icon? In my machine as my pdf reader is acrobat, I get an acrobat icon:

image

But well, this being OLE it is indeed prone to issues. Most of those come from the fact that you have 2 applications here: Excel and the PDF reader, both which must be installed in the machine. That's why you can't use this feature from Excel on the web, which in most aspects is a fully working Excel:

We don't have middle-term plans to support adding OLE objects, mostly because you need the other app too (in this case a pdf reader, but you might be inserting some Autocad ActiveX and we should know about Autocad too. We and Excel can't know about all possible apps that you might embed, so to support this correctly you would have to be able to call the embedded OLE host which is outside our scope.

I am not sure either of other options to do this, but since this is OLE after all, using OLE Automation is probably not the worse possibility if you really need to do it. When you call OLE, it will activate the PDF reader and embed the file, and while this is of course subject to lots of issues and hanged PDF readers in the host machine, I am not sure it can be done better.

Just a thing that probably doesn't help in this case, but one thing that is possible is the reverse: You can attach the xls/x file inside a pdf using FlexCel, and this is fully supported and works as it should, because a pdf file allows for attached files. Just in case it can be useful, there is an example here: Exporting to PDF/A (Delphi) | FlexCel Studio for VCL and FireMonkey documentation

Hi Adrian,

Thanks for the elaborate feedback. Much appreciated. It seems I am stuck with using OLE. Well, I got most of it working now. I understand the difficulties of implementing such feature in Flexcel. Probably the reason why none of the libraries or components have it.

One question though. Though I understand one need to have Excel (desktop) installed for me to use OLE, I don't quite understand why you need to have Acrobat Reader (or any other PDF app) installed to embed a PDF in an Excel sheet. Yes, in order to open the embedded PDF from within Excel, sure, you need to have a PDF reader installed. But, just to embed it in an Excel sheet, is it than also necessary to have a PDF reader installed? Please confirm and it would be great if you could explain why that is.

Best regards,
Fons

First of all, a big disclaimer: It has been years since I last looked at OLE internals, so I could say something wrong, and I hate speaking about stuff I am not 100% sure.

But the reason you need the pdf reader installed is the same reason you need Excel installed. You are using OLE to control Excel from Delphi, so you need Excel installed to control it from Delphi. Excel uses OLE to control the PDF reader from Excel, so it needs the PDF reader installed to control it.

Remember that what you are doing here is not attaching a file, but running one application inside another. It might be not clear in this particular case of pdf embedded as an icon, but imagine you embed a Word document, not as icon but as an actual Word document inside the Excel file. You can click inside the Word object and edit the Word document from Excel. It is kind of magic if you think about it, and it would be even better if it was reliable, but OLE has been out since windows 3 at least, and it has never been.

Now, there is a lot of interaction between Word and Excel document to make this magic happen. When you click inside the word doc, Excel passes some binary blob to Word, Word uses that blob to get the file it needs to edit, and then displays the file inside the running Excel instance. It handles the keystrokes, so when you insert a character in the word document, it goes to Word and not to Excel. When you click outside the word document, control goes back to Excel, and it asks Word for the modified blob so it can persist it in the file, and pass it again when the user re-clicks inside the word document.

So what we have is:

  1. User clicks in Word document: Excel gets some data it doesn't understand or care, and passes it to word. Word uses this data to open the document and display it.
  2. User modifies the Word document
  3. User exits the Word document, Excel asks Word for that modified data (which it still doesn't understand), and persists it in memory/the file.
  4. When user clicks again, Excel takes the blob it received in 3. and passes it to word, going back to 1.

The blob is responsibility of Word, not Excel. It has to have the doc/x file inside, but it is not necessary a plain doc/x file, and Excel is not aware of what it has. It just knows it has to pass it when asked by the guest app, and store it back when you exit the guest app.

In your case, you normally don't edit PDF files, so storing the blob back wouldn't be necessary. But you can edit pdf files (acrobat can do it). And even if embedded as an icon, if you double click that icon and acrobat launches, and you modify the pdf, when you close acrobat, those changes must go back to Excel and be stored inside the xlsx file. So you still need the full OLE mechanism here.

What matters from a FlexCel point of view, is that you never really store the pdf file: you have to store the blob the guest app uses to load and persist the data. And you can have infinite guest apps. We could reverse engineer what a PDF reader uses as blob to communicate with Excel. (it is likely the pdf file + some OLE headers). But then, you might want to insert a powerpoint file, and we now need to know what blob Powerpoint uses. It doesn't scale. At the end, the only solution to use that is to Automate the guest app (pdf reader in this case) and ask it for the blob. The main issue being that now you have 2 automations going on: Delphi to Excel and Excel to the PDF reader.

Hi Adrian,

Thank you very much. I know you add a disclaimer, but what you say does make sense. At least I can understand it and it certainly sounds logical. And it again makes clear why FlexCel or any other library for that matter stays miles away from incorporating such a feature.

For now, OLE works (most of the times) so it's okay.

Thanks again. It is much appreciated.

Best regards,
Fons

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.