+ Start a Discussion
ssousanssousan 

Syntax error saving fields to a CSV file

Im Trying to write a button that triggers the following code or page:

 

<apex:page standardController="Inquery__c" recordSetVar="accvar" contentType="text/csv#filename.csv" >
"First Name","Last Name","Email","Qualification"
<apex:repeat value="{!accvar}" var="a">
      {!IF((!a.Downloaded__c), ({!a.First_Name__c}, {!a.Last_Name__c}, {!a.Email__c}, {!a.Quilification__c}),'Do nothing')}
</apex:repeat>
</apex:page>

 

All this is suppose to do, is save the a.First_Name__c, a.Last_Name__c, a.Email__c, a.Quilification__c Fields to a CSV File,

IF the a.Downloaded__c CHECK box is checked( i.e. TRUE).

 

But the code above gives me a Syntax error,

 

Does anyone know what wrong with the code,

 

Thanks

Best Answer chosen by Admin (Salesforce Developers) 
sfdcfoxsfdcfox

I assume you are calling an "action" method on the page? If the records in the controller are updated before the page renders, then the page shows the new results. This means that the file will be blank. Instead, you'll have to cache those records into a separate list and render that separate list. I didn't even think about this, because your code doesn't show an action. Here's a solution:

 

public with sharing class accountCsv {
	ApexPages.StandardSetController controller;
	
	public Account[] accountCsv { get; set; }
	
	public accountCsv(ApexPages.StandardSetController controller) {
		this.controller = controller;
		accountCsv = new Account[0];
	}
	
	public void updateRecords() {
		Set<Id> recordIds = new Set<Id>();
		Boolean firstPage = true;
		do {
			if(!firstPage) {
				controller.next();
			}
			firstPage = false;
			Account[] temp = (Account[])controller.getRecords();
			for(Account record:temp) {
				if(!record.Download__c) {
					recordIds.add(record.Id);
					accountCsv.add(record);
				}
			}
		} while(controller.getHasNext());
		updateItems(recordIds);
	}
	
	@future public static void updateItems(Set<Id> recordIds) {
		Account[] records = new Account[0];
		for(Id recordId:recordIds) {
			records.add(new Account(Id=recordId,Download__c=true));
		}
		update records;
	}
}

 

<apex:page standardController="Account" extensions="accountCsv" action="{!updateRecords}" contentType="text/csv#file.csv" recordSetVar="accvar">"Name","Industry"
<apex:repeat value="{!accvar}" var="a" rendered="false">{!a.Download__c}{!a.Name}{!a.Industry}</apex:repeat>
<apex:repeat value="{!accountCsv}" var="a">
<apex:outputText rendered="{!NOT(a.Download__c)}">
"{!a.Name}","{!a.Industry}"
</apex:outputText>
</apex:repeat>
</apex:page>

 

All Answers

sfdcfoxsfdcfox
Your IF statement is incorrect. You'd have to write it like this:

{!IF(a.Downloaded__c, a.First_Name__c & "," & a.Last_Name__c & "," & a.Email__c & "," & a.Quailification__c, "Do Nothing")}

That looks pretty horrendous, doesn't it? You could instead write this elegantly as:

<apex:repeat value="{!accvar}" var="a">
<apex:outputText rendered="{!a.Downloaded__c}">
{!a.First_name__c}, {!a.Last_Name__c}, {!a.Email__c}, {!a.Quilification__c}
</apex:ouputText>
</apex:repeat>

This reduces the complexity of the code, and you won't have lines that read "Do nothing" in your CSV. Note that you may need to include quotes and escape internal quotes in the CSV file, or it might not be readable in your favorite program (it'll read incorrectly). Generating a CSV file is a lot harder than it looks at first blush.
ssousanssousan

The data is not saving in the CSV file,

 

I tried also

 

<apex:page standardController="Inquery__c" recordSetVar="accvar" contentType="text/csv#filename.csv" >
"First Name","Last Name","Email","Qualification"
<apex:repeat value="{!accvar}" var="a">
<apex:outputText rendered="NOT({!a.Downloaded__c})">
      {!a.First_Name__c}, {!a.Last_Name__c}, {!a.Email__c}, {!a.Quilification__c}
</apex:outputText>
</apex:repeat>
</apex:page>

 

Using NOT, but also no data is saved to the CSV except the header ("First Name","Last Name","Email","Qualification")

ssousanssousan

Ok, this works if the check box is checked (i.e. True)

Without using the NOT Function,

 

But when i use the NOT function nothing is in the CSV file,

Even if they are checked or Not,

Of course only the unchecked ones should be saved to the CSV file if im using the NOT function,

 

Any ideas why? 

sfdcfoxsfdcfox

I built an example code that I have verified works in my org:

 

<apex:page standardController="Account" contentType="text/csv#file.csv" recordSetVar="accvar">"Name","Industry"

<apex:repeat value="{!accvar}" var="a">
<apex:outputText rendered="{!a.Download__c}">
"{!a.Name}","{!a.Industry}"
</apex:outputText>
</apex:repeat>
</apex:page>

Pay careful attention to line breaks, as that will determine the success of rendering your file.

 

Also, you will need to use REPLACE to make sure that quotes are properly escaped.

ssousanssousan

Yes this will download all the records that have the {!a.Downloaded__c} checked,

But if i want to do the opposite using NOT it doesnt work!!

 

Basically i want to download the records that have not been checked to a CSV file,

Then CHECK the  {!a.Downloaded__c} field for those records, 

sfdcfoxsfdcfox

I assume you are calling an "action" method on the page? If the records in the controller are updated before the page renders, then the page shows the new results. This means that the file will be blank. Instead, you'll have to cache those records into a separate list and render that separate list. I didn't even think about this, because your code doesn't show an action. Here's a solution:

 

public with sharing class accountCsv {
	ApexPages.StandardSetController controller;
	
	public Account[] accountCsv { get; set; }
	
	public accountCsv(ApexPages.StandardSetController controller) {
		this.controller = controller;
		accountCsv = new Account[0];
	}
	
	public void updateRecords() {
		Set<Id> recordIds = new Set<Id>();
		Boolean firstPage = true;
		do {
			if(!firstPage) {
				controller.next();
			}
			firstPage = false;
			Account[] temp = (Account[])controller.getRecords();
			for(Account record:temp) {
				if(!record.Download__c) {
					recordIds.add(record.Id);
					accountCsv.add(record);
				}
			}
		} while(controller.getHasNext());
		updateItems(recordIds);
	}
	
	@future public static void updateItems(Set<Id> recordIds) {
		Account[] records = new Account[0];
		for(Id recordId:recordIds) {
			records.add(new Account(Id=recordId,Download__c=true));
		}
		update records;
	}
}

 

<apex:page standardController="Account" extensions="accountCsv" action="{!updateRecords}" contentType="text/csv#file.csv" recordSetVar="accvar">"Name","Industry"
<apex:repeat value="{!accvar}" var="a" rendered="false">{!a.Download__c}{!a.Name}{!a.Industry}</apex:repeat>
<apex:repeat value="{!accountCsv}" var="a">
<apex:outputText rendered="{!NOT(a.Download__c)}">
"{!a.Name}","{!a.Industry}"
</apex:outputText>
</apex:repeat>
</apex:page>

 

This was selected as the best answer
ssousanssousan

To start with,

Thank you very much for the code,

I appreciate it,

 

This does check all the {!a.Download__c} fields for all the records that are unchecked,

Whcih is what i need,

 

But it does not download any of the data into the CSV file,

Only the header shows!! 

And all the field were unchecked to start with,

 

Best

ssousanssousan

If i remove the NOT,

And i have all the records Checked,

Then all the fields are saved to the CSV file,

 

So basically the class will change all the records to checked,

The the visualforce will see them as checked and download them,

 

Im not sure why the NOT function is not working for me

 

ssousanssousan

Ok NOT is working exactally as it should,

But the code changes all the Unchecked fields to checked first,

So when it looks for checked records to download, they dont exist anymore and nothing is saved to the CSV file,

How can i get the controller to work after i download the data to the CSV file?

 

Thanks

sfdcfoxsfdcfox
That's what my previous example doors. Try it out first.
ssousanssousan

Do you mean the example with the VF page and the extension controller?

 

Thats what i am currently using,

 

When i take out: extensions="accountCsv" action="{!updateRecords}"

 

The code saves the unchecked records in the CSV file,

When i put back this line: extensions="accountCsv" action="{!updateRecords}"

 

All the unchecked records are checked and nothing is saved to the CSV file,

So im guessing the extenssion is updating everything first,

 

I think it might be the way im excuting the VF code,

I dont have a trigger or a button yet,

Im just pressing save on the VF page to excute the code,

 

I tried creating a New Button using the visualforce page as Content Source,

But no content appears, which is strange,

I do have a standard controller,

 

Any ideas why?

ssousanssousan

Here is how my code looks like now:

 

public with sharing class accountCsv {
    ApexPages.StandardSetController controller;
   
    public Inquery__c[] accountCsv { get; set; }
   
    public accountCsv(ApexPages.StandardSetController controller) {
        this.controller = controller;
        accountCsv = new Inquery__c[0];
    }
   
    public void updateRecords() {
        Set<Id> recordIds = new Set<Id>();
        Boolean firstPage = true;
        do {
            if(!firstPage) {
                controller.next();
            }
            firstPage = false;
            Inquery__c[] temp = (Inquery__c[])controller.getRecords();
            for(Inquery__c record:temp) {
                if(!record.Download__c) {
                    recordIds.add(record.Id);
                    accountCsv.add(record);
                }
            }
        } while(controller.getHasNext());
        updateItems(recordIds);
    }
   
    @future public static void updateItems(Set<Id> recordIds) {
        Inquery__c[] records = new Inquery__c[0];
        for(Id recordId:recordIds) {
            records.add(new Inquery__c(Id=recordId,Download__c=true));
        }
        update records;
    }
}

 

And

 

<apex:page standardController="Inquery__c"  extensions="accountCsv" action="{!updateRecords}" recordSetVar="accvar" contentType="text/csv#filename.csv" >
"First Name","Last Name","Email","Qualification"
<apex:repeat value="{!accvar}" var="a" rendered="false">{!a.Download__c}{!a.First_Name__c}, {!a.Last_Name__c}, {!a.Email__c}, {!a.Quilification__c}</apex:repeat>
<apex:repeat value="{!accountCsv}" var="a">
<apex:outputText rendered="{!NOT(a.Download__c)}">
      {!a.First_Name__c}, {!a.Last_Name__c}, {!a.Email__c}, {!a.Quilification__c}
</apex:outputText>
</apex:repeat>
</apex:page>