Chart Export via AFL - OLE

I am trying to export a chart via AFL code but i can't do it. I want to send a copy of chart to alert email. can any one help me? I am very new to this system.

1 Like


it's possible to create an image:

1 Like

I have tried this. but its external code, found it on google. problems are..

  1. JS file so i have to execute manually
  2. it only creates chart of a security AA, doesn't create any other stock.
1 Like

@parthashah it is possible to use the OLE functionality also inside formulas.

Here is a raw code snippet, I just wrote, that shows how to export an image simply clicking on a GUI button (for this you need a recent beta version of AmiBroker)

_SECTION_BEGIN("Export Image PNG onClick");

Version (6.25);
exportPath = "C:\\Program Files (x86)\\AmiBroker\\ExportedImages\\";
fmkdir( exportPath ); // Create the path if it does not exists

pxHeight = Status("pxheight");
pxWidth = Status("pxwidth");
exportButtonID = 1973; // Try toi use a unique ID to avoid potential conflicts 
GuiButton( "Export", exportButtonID , pxWidth -64, 4, 60, 28, notifyClicked );
id = GuiGetEvent( 0, 0 );
notify = GuiGetEvent( 0, 1 );

if( id == exportButtonID AND notify == notifyClicked )
    AB = CreateObject("Broker.Application");
    AW = AB.ActiveWindow;
	AW.ExportImage( exportPath + Name() + ".png"); 


You should save this code as an .AFL file in the Custom subfolder of the Formulas folder (or in any other Formulas subfolder) to be used as a custom indicator. Give to the file a name that will help to identify it in the "chart" tree (something like "").

(Refresh the chart tree to see the newly created indicator).

Then you need to "overlay" it to any existing chart (if you are unsure how to do it, please, read this document).

When you click on the "export" GUI button (that is found on the upper right corner of the pane where you overlayed this 'pseudo' custom indicator, AmiBroker will save the entire current chart image in the "exportPath" folder (before using the code, if needed, change such path).

If you need to use a similar functionality in a non-interactive mode (It is not clear to me how you plan to use it to send e-mails) you'll probably need to take extra care to avoid any potential issue (OLE is not multithread safe).


As usual, you are always helpful @beppe thanks for the useful and universal code idea which is important for educational and review purposes ., keep good working.

I have try this code , but getting error.

Which version of AB are you running ?

I think that error is related to your Amibroker version "it is old one"

@hirenvyas Is it difficult to understand plain and simple sentence that says (taken from your screenshot)


Are you registered user? If you are you should change the email on this forum to registered one. You need to be registered user to get version 6.25 or higher.

@beppe thanks for your response, I want to use this when i receive an alert from AB on my email. I have configured my email on AB, so when there is an alert, AB sends an email to me. I need to attach a chart with this email i will have more clear idea.

@parthashah, in such a case you should trigger the OLE methods each time in your code there is a condition that at present will invoke the e-mail message sending (typically employing the AlertIf() or SendEMail() functions).

You should then replace the AmiBroker native method to send the mail with something similar to what I explained in this thread.
Probably, instead of using an AmiBroker batch job like I did in that example, you should handle the "send mail with attachment" action within your code via ShellExecute() to launch a Windows/Dos batch/script.

As an alternative, if you have Outlook on your PC (I mean the Windows executable Office application), you can use its Automation methods to create and send the email with an attachment, doing it entirely from AFL without the need to invoke external scripts.

Here is an example of Outlook automation calls from AFL:

// Some Outlook Automation predefined Constants
// See a full list, for example, here:

olMailItem = 0;
olTo = 1;
olCC = 2;
olFormatPlain = 1;
olFormatHTML = 2;

oOutlook = CreateObject( "Outlook.Application" );

if( typeof( oOutlook ) == "object" )
    _TRACE( "Outlook Automation Object created." );
    oMail = oOutlook.CreateItem( olMailItem );
    oMail.Subject = "HTML e-mail from AmiBroker with chart attachment";

    // Specify recipient address (optionally repeat to "add" further recipients)
    oRecipients = oMail.Recipients;

    oRecipient = oRecipients.Add( "" );  
    oRecipient.Type = olTo;
    oRecipient = oRecipients.Add( "" );
    oRecipient.Type = olCC;

    // Specify the file to attach (you can repeat the command to "add" multiple files)
    oAttachments = oMail.Attachments;
    oAttachments.Add( "C:\\Temp\\OLE_Exported_Chart.png" );

    // Create the actual e-mail message  
    // To send as plain text uncomemnt this and comment out the HTML part
    // oMail.BodyFormat = olFormatPlain;
    // oMail.Body = Name() +  - " + FullName() + " - " + Now( 0 );

    // The body of this message need to be specified in valid HTML
    oMail.BodyFormat = olFormatHTML;
    oMail.HTMLBody = "<HTML>" +
                     "<BODY>" +
                     "<H2>" + Name() + "</H2>" +
                     "<H3>" + FullName() + "</H3>" +
                     "<H4>" + Now( 0 ) + "</H4>" +
                     "<p><small>" + "Chart/Signals commentary:" + "</small></p>" +
                     "<p><strong>" + "BUY NEXT BAR at OPEN." + "</strong></p>" +
                     "</BODY>" +

    // Send the e-mail

    _TRACE( "Outlook Automation Object - Message sent. OLE done." );
    // See also Microsoft documentation about the eventual use of the Quit method (normally IS NOT required)
    // The OLE object is released automatically at the end of the formula; no explicit freeing is necessary 

Before using the above sample, change the recipients' addresses and the path/filename of the image to attach.

Search with Google "Send email with Outlook automation" to find further examples. You'll get results mainly in VBA, but looking at the above sample, you should be able to adapt them to AFL.

In any case, keep in mind that using OLE from AFL may impact on the performance of your tasks and generate the following message:

Warning 503. Using OLE / CreateObject / CreateStaticObject is not multi-threading friendly.

See the AmiBroker help to get the full explanation of it. Here below, for your convenience, I'm quoting the main points:

Your formula contains CreateObject and/or CreateStatic object calls. While they are still supported, the performance of OLE in multi-threaded applications is poor. ...
OLE was developed by Microsoft back in 1990's in the 16-bit days it is old technology, and it effectively prevents threads from running at full speed as all OLE calls must be served by one and only user-interface thread. ....
For this reason, if only possible you should strictly avoid using OLE / CreateObject in your formulas. ...
If you fail to do so, the performance will suffer. Any call to OLE from a worker thread causes posting a message to OLE hidden window and waiting for the main application UI thread to handle the request. If multiple threads do the same, the performance would easily degrade to single-thread level, because all OLE calls are handled by main UI thread anyway. ...


FWIW, compared to Outlook, OLE itself is fast.

1 Like

@Tomasz, I think that to get rid of all these alternative methods, it would be better to have a native AFL function to export the images of charts (or ideally of single panes) and also a version of SendEmail () that can optionally include an attachment.

But considering the large number of pending features entries in the Feedback Center, I wonder if it's worth making a formal request.

1 Like

While I can code in C++, I like to use C# for coding quick tasks and to automate some things. One large wish list item would be the ability to use C# (non-ole, non-late binding) with AB and not thru some third party solution either. For whatever reason, accessing the symbol data via a ole c# solution is so so slow.

C# is much faster than previously thought once the programmer takes manual control over GC.

As I wrote, OLE is not "slow" in the sense of seconds. It is slow in a sense of single millisecond. Outlook is slow in a sense of (fraction of) a second. We are talking about different orders of magnitude. OLE mechanisms are 1000x faster than Outlook, so using OLE to control Outlook is not really something you should be worried about.

So as far as "automation" goes OLE is adequate.

Using it for something requiring millions of function calls is completely different story, though.

1 Like

No I know, what I mean is that OLE thru C# seems very very slow, even as compared to Windows Script. Maybe it's my code? :open_mouth:



Hope all is well with you, many many months since I sent any mail to u.

Coding is not really my cup of tea, so sticking to using basic Amibroker facilities.

Came across this thread " Chart Export via AFL - OLE"

during routine week end - going through the forum !!

Have noticed that when the chart is exported THE GUI BUTTON does not print .

Just for curiosity sake -- is there any way this may be done - no specific reason !

well, bye for now, warm regards, take care.

@JEETU, you are right. Native Gui controls do not appear in exported images.
I suppose that this is because AB implements double buffering techniques and what is exported comes from some hidden canvas, but @Tomasz only can provide a qualified answer.

I'm sorry to hear that you gave up studying AFL programming, but maybe you started with a project that was a bit too ambitious (I refer to the Fibonacci retracements formula).

The only suggestion I can give you when you are ready to try again, is to start slowly, moving from the simplest examples that are available in the documentation to the more elaborate ones explained in the KB articles.

I am convinced that, given the necessary time, everyone can learn to program.

When learning something new seems too difficult to me, I remember a phrase I read many years ago in a French course: "Avec de la patience, on arrive à tout."


In Windows, all controls (buttons, edits, checkboxes, radio, tree, list views) are actually windows (hence the name of OS). So native GUI controls are separate windows that are not really part of chart - they live on "top" of chart.
The only way to "print" it with buttons and other GUIs is making a screenshot.


i want to export Image From ProfiT Chart But Its Show me error Msg ,

1 Like