I'm trying to create a VF page for reporting. I'm hardcoding the object for right now (Product2) but would like the column's values to be dynamically populated based on the environment in case the fields are different. My error is on the VF page stating Invalid field for SObject Product2. Here is my VF snippet with commented out, hardcoded columns that work.

    <apex:pageBlockSection title="Results" collapsible="false">
            <apex:pageBlockTable value="{!queryResultsList}" var="prod2">
                <apex:repeat value="{!fieldAPINames}" var="fieldAPIName">
                    <apex:column value="{!prod2.[fieldAPIName]}"/>
                <apex:column value="{!prod2.Name}"/>
                <apex:column value="{!prod2.Description}"/>
                <apex:column value="{!prod2.IsActive}"/>
                <apex:column value="{!prod2.ProductCode}"/>
                <apex:column value="{!prod2.Family}"/>

And here is the controller I'm calling. I'm very new to apex and controllers so feel free to question what I'm doing or if you could propose a better option that would be great!

public class ProductCatalogPageController {
    public List<Product2> queryResultsList{get;set;}
    public String query{get;set;}
    public String strOfStuff{get;set;}
    public Map<String, Schema.SObjectField> fieldAPINames{get;set;}

    public PageReference testAction(){
        String SobjectApiName = 'Product2';

        Map<String, Schema.SObjectType> schemaMap = Schema.getGlobalDescribe();
        Map<String, Schema.SObjectField> fieldMap = schemaMap.get(SobjectApiName).getDescribe().fields.getMap();

        String csvFields = '';
        for(String fieldName : fieldMap.keySet()){
            if(csvFields == null || csvFields == ''){
                csvFields = fieldName;
                csvFields = csvFields + ', ' + fieldName;
        query = 'select ' + csvFields + ' from ' + SobjectApiName;
        queryResultsList = Database.query(query);

        strOfStuff = 'Stuff goes here';

        return null;
  • Why do you need Apex in the first place? Why not use an actual Report? You can export it as .csv and it requires zero code.
    – Adrian Larson
    Jul 27, 2016 at 19:50
  • 1
    I'm trying to avoid having to jump into the parameters each time. Plus this is just something fun and a good learning experience for me.
    – Grant
    Jul 27, 2016 at 20:36
  • 1
    Gotcha. Yeah, look at using a Fieldset. You don't really want to pull every field, I would think.
    – Adrian Larson
    Jul 27, 2016 at 20:40
  • 1
    I'll do that. I appreciate the feedback!
    – Grant
    Jul 27, 2016 at 20:46

1 Answer 1


The problem is the dot in here making the page compiler expect a field name immediately after the dot:


Should work without that:


Fyi, here is a slimmer version of the code:

public class MyController {

    public Product2[] products {get; private set;}
    public String[] fields {get; private set;}

    public MyController() {
        String apiName = 'Product2';
        fields = new List<String>(Schema.getGlobalDescribe().get(apiName).getDescribe().fields.getMap().keySet());
        products = Database.query('select ' + String.join(fields, ',') + ' from ' + apiName + ' order by Name limit 100');

and page:

<apex:page controller="MyController">
        <apex:pageBlockSection title="Results" collapsible="false">
            <apex:pageBlockTable value="{!products}" var="p">
                <apex:repeat value="{!fields}" var="f">
                    <apex:column value="{!p[f]}"/>
  • Hmm, SELECT * notation...wouldn't it be better to use a Fieldset?
    – Adrian Larson
    Jul 27, 2016 at 19:51
  • @AdrianLarson Good point for the general case.
    – Keith C
    Jul 27, 2016 at 20:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .