function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Chad RitchieChad Ritchie 

Visualforce Page for Filtering Reports

I'm trying to embed a Visualforce Page onto my home page that allows users to select a report and filter it right there. 

When running I seem to be getting the following error:
caused by: System.NullPointerException: Attempt to de-reference a null object

Class.AnalyticsController.getSelectedFilters: line 69, column 1
Class.AnalyticsController.getChartFilter: line 64, column 1


Can anyone identify what's causing this issue? I notice this code was written for API Ver 29, while I'm on 48. 

Visualforce Page: 

<apex:page controller="AnalyticsController">
<style>
label {
    font-weight: bold;
}
#filters {
    overflow: hidden;
    width: 100%
}
#filterBox {
    float: left;
    align: center;
    padding: 5px 5px 5px 0px;
}
</style>
<apex:form >
    <apex:outputLabel value="Select Report"/> 
    <apex:selectList value="{!reportId}" multiselect="false" size="1">
        <apex:selectOptions value="{!availableReports}"/>
    </apex:selectList>
    <apex:commandButton action="{!getReportInfo}" value="Get Report Filters" reRender="report"/><br/>

    <apex:outputPanel id="report" layout="block">
        <apex:outputPanel rendered="{!reportId != null}">
            <div id="filters">
                <apex:repeat value="{!availableColumnFilters}" var="colFilter">
                    <div id="filterBox">
                        <apex:outputLabel >{!colFilter.label}</apex:outputLabel><br/>
                        <apex:selectList value="{!colFilter.operator}" size="1" multiselect="false" style="width: 100px;">
                            <apex:selectOption itemLabel="--None--" itemValue=""/>
                            <apex:selectOptions value="{!availableDataTypeFilterOperators[colFilter.dataType]}"/>
                        </apex:selectList>
                        <apex:inputText value="{!colFilter.value}"/>
                    </div>   
                </apex:repeat>
            </div>

            <apex:commandButton value="Get Chart with Filters" reRender="chart"/><br/>

            <apex:outputPanel layout="block" id="chart">
                <analytics:reportChart reportId="{!reportId}" filter="{!chartFilter}"/>
            </apex:outputPanel>
        </apex:outputPanel>
    </apex:outputPanel>
</apex:form>
</apex:page>

Controller:
 
public with sharing class AnalyticsController{
 
    public List<SelectOption> availableReports { get; set; }
    public Id reportId { get; set; }
    public Map<String, List<SelectOption>> availableDataTypeFilterOperators { get; set; }
    public List<ColumnFilter> availableColumnFilters { get; set; }
 
    public AnalyticsController() {
        availableReports = retrieveAvailableReports();
        availableDataTypeFilterOperators = retrieveAvailableDataTypeFilterOperators();
    }
 
    public List<SelectOption> retrieveAvailableReports() {
        List<SelectOption> reptOpts = new List<SelectOption>();
        for (Report r : [
             Select Id, Name
             From Report
             Where Format In ('Summary','Matrix')
             Order By Name
        ]) {
            reptOpts.add(new SelectOption(r.Id, r.Name));
        }
        return reptOpts;
    }
 
    public Map<String, List<SelectOption>> retrieveAvailableDataTypeFilterOperators() {
        Map<String, List<SelectOption>> dataTypeFilterOpts = new Map<String, List<SelectOption>>();
        Map<String, List<Reports.FilterOperator>> filterOperatorMap = Reports.ReportManager.getDataTypeFilterOperatorMap();
 
        for (String dataType : filterOperatorMap.keySet()) {
            List<SelectOption> operators = new List<SelectOption>();
 
            // Append _DATA to match ColumnDataType from ReportTypeColumn
            dataTypeFilterOpts.put(dataType.toUpperCase() + '_DATA', operators);
 
            for (Reports.FilterOperator fo : filterOperatorMap.get(dataType)) {
                operators.add(new SelectOption(fo.getName(), fo.getLabel()));
            }
        }        
        return dataTypeFilterOpts;
    }
 
    public PageReference getReportInfo() {
        Reports.ReportDescribeResult descRes = Reports.ReportManager.describeReport(reportId);
 
        availableColumnFilters = new List<ColumnFilter>();
 
        for (Reports.ReportTypeColumnCategory category : descRes.getReportTypeMetadata().getCategories()) {
            for (Reports.ReportTypeColumn col : category.getColumns().values()) {
                if (col.getFilterable()) {
                    ColumnFilter cf = new ColumnFilter(
                        col.getLabel(),
                        col.getName(),
                        col.getDataType().name()
                    );
                    availableColumnFilters.add(cf);
                }
            }
        }
        return null;
    }
 
    public String getChartFilter() {
        return JSON.serialize(getSelectedFilters());
    }
 
    private List<ColumnFilter> getSelectedFilters() {
        List<ColumnFilter> selectedFilters = new List<ColumnFilter>();
        for (ColumnFilter cf : availableColumnFilters) {
            if (String.isNotBlank(cf.operator)) {
                selectedFilters.add(cf);
            }
        }
        return selectedFilters;
    }
 
    public class ColumnFilter {
        public ColumnFilter(String lab, String col, String dt) {
            label = lab;
            column = col;
            dataType = dt;
        }
 
        // Values needed for apex:analytics component
        public String column { get; set; }
        public String operator { get; set; }
        public String value { get; set; }
 
        // Values need for display and operator select list
        public String label { get; set; }
        public String dataType { get; set; }
 
    }
}

Thanks for the help!! 
Best Answer chosen by Chad Ritchie
GauravGargGauravGarg
Hi Chad,

I test your page on my development org and found the issue is NULL Pointer Exception because of the List: availableColumnFilters is empty.

Please add a NULL check on Line 69 and it will work. See below code change I have made:
private List<ColumnFilter> getSelectedFilters() {
        List<ColumnFilter> selectedFilters = new List<ColumnFilter>();
       // NULL Check
        if(availableColumnFilters != NULL){
            for (ColumnFilter cf : availableColumnFilters) {
                if (String.isNotBlank(cf.operator)) {
                    selectedFilters.add(cf);
                }
            }
        	return selectedFilters;
        }
        return null;
        
    }

Result displayed on page.

Please update the code and check. 

Thanks, 
Gaurav
Skype: gaurav62990
Email: gauravgarg.nmims@gmail.com

All Answers

GauravGargGauravGarg
Hi Chad,

I test your page on my development org and found the issue is NULL Pointer Exception because of the List: availableColumnFilters is empty.

Please add a NULL check on Line 69 and it will work. See below code change I have made:
private List<ColumnFilter> getSelectedFilters() {
        List<ColumnFilter> selectedFilters = new List<ColumnFilter>();
       // NULL Check
        if(availableColumnFilters != NULL){
            for (ColumnFilter cf : availableColumnFilters) {
                if (String.isNotBlank(cf.operator)) {
                    selectedFilters.add(cf);
                }
            }
        	return selectedFilters;
        }
        return null;
        
    }

Result displayed on page.

Please update the code and check. 

Thanks, 
Gaurav
Skype: gaurav62990
Email: gauravgarg.nmims@gmail.com
This was selected as the best answer
Chad RitchieChad Ritchie
Hey GauravGarg, 

Thanks for the help!
That code adjustment worked. Now all of the filters and the report chart are loading. 

I'm curious if on your end you were able to get any of the filters to work, I seem to be having issues with the JSON syntax?

Thanks again. 


 
GauravGargGauravGarg
Hi Chad,

Yes, I am also faced the same issue. Initially, I thought this is my dev which might be able to pick Standard report, however, the result was the same with Custom reports too. 

 
Chad RitchieChad Ritchie
Hey GauravGarg, 

Oh okay. Well it's good to know it's not just my Salesforce instance. 

Thanks again for your help!