In this blog, I will share well known process of sending a chart from an Oracle APEX application as an email attachment. This feature can be especially useful for sharing data visualizations directly from your application with team members or stakeholders. We will cover the steps to create a chart, add a button to trigger the email, and use both JavaScript and PL/SQL to send the chart as an attachment.
Step 1: Create a Chart
To begin, we need to create a chart in our Oracle APEX application. For this demonstration, let's create a chart with a static ID reg_dept_emp_chart
.
Instructions:
- In your Oracle APEX application, create a new chart region.
- Set the Static ID of the chart region to
reg_dept_emp_chart
.
Step 2: Add a Button
Next, we will add a button to trigger the process of sending the chart as an email attachment.
Step 3: JavaScript Function to Save the Chart
Now, we will create a JavaScript function called saveJETChart
. This function captures the chart as an image and sends it to a PL/SQL process for further handling.
function saveJETChart(regionId) {
console.log("Inside saveJETChart");
var svg = document.querySelector('#' + regionId + '_jet > svg');
if (!svg) {
console.error("SVG element not found!");
return;
}
var svgString = new XMLSerializer().serializeToString(svg);
var chartTitle = $('#' + regionId + '_heading').text();
let { width, height } = svg.getBBox();
// Create a canvas
var canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");
ctx.fillStyle = "#ffffff"; // Fill background with white
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Create a blob image
var img = new Image();
var svgBlob = new Blob([svgString], { type: "image/svg+xml;charset=utf-8" });
var svgBlobURL = URL.createObjectURL(svgBlob);
img.onload = function () {
ctx.drawImage(img, 0, 0);
var jpg = canvas.toDataURL('image/jpeg', 1.0);
// Call an AJAX callback passing the base64 string
apex.server.process('SEND_CHART', {
p_clob_01: jpg.replace('data:image/jpeg;base64,', ''),
x01: chartTitle
}, {
success: function (data) {
if (data.result == 'fail') {
apex.message.showErrors({
type: "error",
location: "page",
message: "Error saving image",
});
} else if (data.result == 'success') {
apex.message.showPageSuccess("Chart sent as an email attachment!");
}
}
});
};
img.onerror = function () {
console.error("Image failed to load. Check for cross-origin issues.");
};
img.src = svgBlobURL;
}
Step 4: PL/SQL Process to Handle the Image
We will now create a PL/SQL process called SEND_CHART
. This process handles the base64 image string, converts it to a BLOB, and sends it as an email attachment.
declare
l_photo_clob clob;
l_photo_blob blob;
l_id number;
begin
l_photo_clob := apex_application.g_clob_01;
-- Convert base64 string to BLOB
l_photo_blob := apex_web_service.clobbase642blob(p_clob => l_photo_clob);
-- Send email with the chart as attachment
l_id := APEX_MAIL.SEND(
p_to => 'abc@gmail.com',
p_from => 'ABC',
p_subj => 'Chart Image as Attachment',
p_body => 'Please review the attachment.',
p_body_html => '<b>Please</b> review the attachment.'
);
APEX_MAIL.ADD_ATTACHMENT(
p_mail_id => l_id,
p_attachment => l_photo_blob,
p_filename => apex_application.g_x01 || '.jpg',
p_mime_type => 'image/jpg'
);
apex_json.open_object;
apex_json.write(p_name => 'result', p_value => 'success');
apex_json.close_object;
exception
when others then
apex_json.open_object;
apex_json.write(p_name => 'result', p_value => 'fail');
apex_json.close_object;
end;
Testing and Conclusion
After following these steps, you can run your Oracle APEX application and click the "Send Chart as Attachment" button to test the functionality. If everything is set up correctly, an email will be sent with the chart image attached.
This solution has been tested on Google Chrome and Microsoft Edge and works seamlessly on both browsers.
By implementing this feature, you can enhance the capability of your Oracle APEX applications to share visual data insights efficiently via email.
Acknowledgment: A special thanks to my ex-colleague, Santosh, for his invaluable support and assistance throughout this process.