Over the weekend Aldo Fernandez (@aldoforce) asked the question “is there a way to get from apex code a PNG/JPG snapshot of a Salesforce Dashboard”.  Aldo was looking to use the dashboard chart in a dynamic visualforce page.

This week I have been playing with a very similar requirement of displaying a report or dashboard chart on a standard page layout.  My solution involves aligning an iframe within a DIV to display only the chart component of the report.  Aldo identified the UX issues of using an iframe “the ‘right click’ issue and any click will launch a request from within the iframe. Bad UX”.  At this point Daniel Hoechst (@dhoechst) shared that it is possible to “Grab the url of the dashboard component image to use. When you refresh dashboard, image gets updated.”.

This has lead me to identify the two known methods for showing a report or dashboard chart on a visualforce page.  Both of these methods are non-supported by Salesforce so are vulnerable to changes of the UI.

1. iFrame the report result page

Method one is to use a Visualforce component to help embed a standard report chart using an iFrame.  The iFrame is loaded within a DIV window.  The iFrame element is then positioned within the DIV window so only the chart can be seen.

Advantages: Criteria parameters can be passed to the component to make the chart output dynamic for the current page, e.g. Show all Opportunities or Cases for current Account.

Disadvantages: Requires an iFrame. Any changes to source chart will impact the layout.  As Aldo mentioned there are UX issues surrounding the use of an iFrame.

Find the component and example code on Bitbucket: http://bitbucket.org/tapply_andy/dynamic-report-chart-component

Chart in Standard Page Layout

2. Dashboard Image URL

Method two is from Daniel Hoechst (@dhoechst).  This method involves creating a dashboard chart and then referencing the image.  This method allows the developer to control the eventual output of the dashboard chart with the following table of URL parameters.  I haven’t figured out what every parameter does yet so if you know or can figure it out please leave a comment and I can update this table.

Advantages: Actual image in embedded into the page which will give the developer more control of where and how the chart image can be used.  The additional URL parameters provide further control to the developer.

Disadvantages: The chart component needs tone created on a dashboard.  Doesn’t offer the same flexibility in terms of report criteria as method one.

URL Param Purpose
rsid=0FL200000009AOw Dashboard Chart ID
ruid=005200000017TsH Run As User ID
did=01Z20000000XlMf Dashboard ID
s=7 Size of Chart 1,2,3,4,5,6,7
fs=10 Aixis FontSize
tfg=12 Title FintSize
c=bar chart type (e.g. bar, line, etc)
cs=0 chart sub type (stacked, split, stacked to 100%) 0,1,2,3
title=  chart title
fg=-16777216 axis font colour
bg1=-1 colour of bg from left side of chart
bg2=-1 colour of bg from right side of chart
bgdir=2  direction of fade from bg1 to bg2
dl1=Case+Owner Axis Label
sax=yes show axis labels (default no)
nc=0 rows to filter, integer is how many 0 is all
sd=1 sort direction 0,1,2,3,4
scv=no show values
vl0=Record+Count Axis Label

Often its required to embed a Visualforce page into either the Home tab or the left hand navigation.  This is not natively possible, however a common work around is to use a homepage component with an iFrame referencing your Visualforce page.

The next challenge is that the iFrame height is static as defined in the component.  Javascript hack to the rescue!

<apex:page id="hompage" title="Homepage Visualforce"
    controller="" showheader="false" sidebar="false" cache="false" standardStylesheets="false">
<script type="text/javascript">
    function resizeFrame() {
	var parentIFrame = parent.document.getElementById('homepageComponentiFrameId');
            if ( parentIFrame != null ) {
                 if ( document.body.clientHeight != null && document.body.clientHeight > 0 )
                      parentIFrame.height = document.body.clientHeight;
                  else {
                       parentIFrame.height = document.height+"px";
     <body onload="resizeFrame();">
your page contents here...

This simple example Visualforce page calls a simple Javascript method onload.  The resizeiFrame method could also be called by a chunk of Javascript loaded at the end of the page to save adding the body tags, which may break the markup.

You then need your homepage component which looks like this:

<iframe id="homepageComponentiFrameId" src="/apex/yourVisualforcePage"
width="100%" height="5px" frameborder="0" scrolling="no"> </iframe>

The important part here is to make the id of the iFrame the same as the value in the parent.document.getElementById line in the Javascript in the Visualforce page.

You will find the page load in the frame and then resize, the resize is sometimes noticable if your browser is slower at rendering the page and executing Javascript.

Let me know if this works for you, I have used this many times in an emea org.

UPDATE Sunday 3rd February 2013: The solution discussed in this post is no longer viable .  This is due to Visualforce now being delivered from a different domain and therefore causing xdomain issues interacting with the iFrame.  Two new solutions are discussed in a new post, ‘Two methods for embedding a Report or Dashboard Chart in Visualforce or Standard Pagelayout’

More than once I have wanted to display a report within my application. Unfortunatly there is not a Visualforce component for displaying a report directly on a custom Visualforce page. I used to fall back on linking to the report as a compromise. It is just that, a compromise, so I decided to break a cardinal sin of modern web design and decided to use an iframe.

This is the report I want to display in my visualforce page. By simply load this URL into an iframe however, I will get all the fluff that surrounds the report. The Headers with global search, the report title, the tag bar, the filter options etc. To remove these I will need to employ javascript.

Report to show inline

The following code is for the Visualforce page to display a simple iframe. The smart bit is in the Javascript. The Javascript displays the report in the iframe whilst hiding the fluff around the report making the whole experience that little bit nicer.

   <script type="text/javascript">
    function renderReportFrame(myIframe, reportId, hideHeader, hideTitle, hideProgressIndicator, hideFilters, hideTagbar) {
        if (myIframe != null) {
            myIframe = myIframe.childNodes[0];

            if (myIframe != null) {
                myIframe.onload = function() {

                    var phHeader = this.contentWindow.document.getElementById("phHeader");
                    var tabNavigation = this.contentWindow.document.getElementById("tabNavigation");
                    var section_header = this.contentWindow.document.getElementById("section_header");
                    var progressIndicator = null;
                    var progressIndicatorList = this.contentWindow.document.getElementsByClassName("progressIndicator");
                    if (progressIndicatorList!=null) progressIndicator = progressIndicatorList[0];

                    var bFilterReport = null;
                    var bFilterReportList = this.contentWindow.document.getElementsByClassName("bFilterReport");
                    if (bFilterReportList!=null) bFilterReport = bFilterReportList[0];

                    var bPageTitle = null;
                    var bPageTitleList = this.contentWindow.document.getElementsByClassName("bPageTitle");
                    if (bPageTitleList!=null) bPageTitle = bPageTitleList[0];

                    if (hideHeader!=null && hideHeader==true) {
                        phHeader.style.cssText = "display: none;";
                        tabNavigation.style.cssText = "display: none;";
                    if (hideTitle!=null && hideTitle==true) {
                        bPageTitle.style.cssText = "display: none;";
                    if (hideProgressIndicator!=null && hideProgressIndicator==true) {
                        progressIndicator.style.cssText = "display: none;";
                    if (hideFilters!=null && hideFilters==true) {
                        bFilterReport.style.cssText = "display: none;";
                    if (hideTagbar!=null && hideTagbar==true) {
                        section_header.style.cssText = "display: none;";

            myIframe.src = "/" + reportId + "?pv1=var1";

  <apex:outputPanel id="theReportPanel" layout="block">
    <apex:iframe id="theReportFrame" scrolling="true" />

  <script type="text/javascript">
      renderReportFrame(document.getElementById("{!$Component.theReportPanel}"), "00OR0000000gr45", true, true, true, true, true, true);

Update 12/10/2011: Vanessen Munisamy has just provided a better solution. Salesforce already provides a hidden URL parameter to handle much of the JacaScript from this post.

A simple thing you could have done is to append the parameter ?isdtp=mn to the url in the iframe source, the report will appear without headers. ex. /00OG0000004AIHR?isdtp=mn

This is great and should mean the solution is future better future proofreader against report output facelifts. However, I believe use of ‘hidden’ URL parameters is generally considered unsupported so is not guaranteed.

Today I wanted to use the standard interface components pageBlock & pageBlockSection whilst adding a bit if colour to differentiate sections. As there is no style class attribute for pageBlockSection it’s not so straight forward.

Seems a shame to have to rebuild this functionality that comes for free with a pageBlockSection so I looked to JavaScript to solve this problem. The following function takes the pageBlockSection and the desired colour then adds that colour to HTML element as a background-color.

function colorPageBlock(pageblock, color) {
if (pageblock != null) pageblock.firstChild.style.cssText = "background-color: " + color + ";";

This is the result:

and here is the full code:

<apex:page standardController="Account">

function colorPageBlock(pageblock, color) {
if (pageblock != null) pageblock.firstChild.style.cssText = “background-color: ” + color + “;”;



<apex:pageBlock title="My Content" mode="detail">
<apex:pageBlockSection id="redSection" title="My Content Section" columns="2">
<apex:inputField value="{!account.name}"/>
<apex:inputField value="{!account.site}"/>
<script>colorPageBlock(document.getElementById("{!$Component.redSection}"), "red");</script>

<apex:pageBlockSection id="greenSection" title="My Content Section" columns="2">
<apex:inputField value="{!account.name}"/>
<apex:inputField value="{!account.site}"/>
<script>colorPageBlock(document.getElementById("{!$Component.greenSection}"), "green");</script>

<apex:pageBlockSection id="orangeSection" title="My Content Section" columns="2">
<apex:inputField value="{!account.name}"/>
<apex:inputField value="{!account.site}"/>
<script>colorPageBlock(document.getElementById("{!$Component.orangeSection}"), "orange");</script>




<span>%d</span> bloggers like this: