2

i am trying to create a csv and succeeded in that except with a new empty row has been added on the top of the csv. The following is the visualforce page code for the generation.

Also, i need to use the same page to create csv's for 2 to 3 custom list which are more or less have similar structure. What i used is nested if's to identify which content i need to output as csv and also to create headers. Is that a right approach using nested if's to handle different csv header structures in a single page?

Any best approaches to create and download CSV?

Is there any other best approaches available to generate and download csv's apart from the one simple method given below? Experts please advice.

     <apex:page StandardController="Account" extensions="OpenDocumentsController" contentType="text/csv#OSO_{!CustNo}.csv" showHeader="false" sidebar="false" standardStylesheets="false">
            {!(If(CSVTab=='OSO','Order #, Document Date, Purchase Order #, Sales Org, Amount,Currency,Products',If(CSVTab=='OD','abcd','test')))}
         <apex:repeat value="{!OpenSalesOrders}" var="oso" rendered="true">
            {!oso.OrderNo},"{!oso.DocumentDateCSV}","{!oso.PurchaseOrderNo}","{!oso.SalesOrg}","{!oso.Amount}","{!oso.Curren}","{!oso.Product}"
         </apex:repeat>
    </apex:page>

Screen shot with empty line at the top:

enter image description here

3
  • 3
    On the white space, eliminate the line breaks in your Visualforce. Won't look pretty but should eliminate the spurious blank line.
    – Keith C
    May 13, 2014 at 14:45
  • You should make that an answer, Keith. May 13, 2014 at 16:09
  • 1
    @JeremyNottingham Was put off by there being several other questions posed too - hopefully someone will write an answer that covers those.
    – Keith C
    May 13, 2014 at 16:57

1 Answer 1

7

i am trying to create a csv and succeeded in that except with a new empty row has been added on the top of the csv. The following is the visualforce page code for the generation.

You need to make sure there's no intervening space between the opening page tag and the next tag:

<apex:page ...>{!output}</apex:page>

Also, i need to use the same page to create csv's for 2 to 3 custom list which are more or less have similar structure. What i used is nested if's to identify which content i need to output as csv and also to create headers. Is that a right approach using nested if's to handle different csv header structures in a single page?

You're doing this in Visualforce expressions, which can be problematic, as larger files will take forever to export and may run into Visualforce runtime exceptions. I would recommend simply emitting a string directly, as in the prior example above:

public String getOutput() {
    String result = '';
    // Build csv headers and values
    return result;
}

Also, I've noticed you're probably not escaping the fields correctly (quotes within a field need to be double-quoted, as in """Bob's"" Bar-B-Que" for "Bob's" Bar-B-Que).

You might be able to use a polymorphic method to generate your code to make the code easier to follow:

abstract class CSVBuilder {
    abstract String buildCSV(SObject[] records);
}

class OSOCSVBuilder extends CSVBuilder {
    override String buildCSV(SObject[] records) {
        // implementation 1;
    }
}

class ODCSVBuilder extends CSVBuilder {
    override String buildCSV(SObject[] records) {
        // implementation 2;
    }
}

Then, you can change your "getOutput" method:

public String getOutput() {
    SObject[] data = loadData(); // Some function that gets the data to output
    Map<String, Type> dispatch = new Map<String, Type> {
        'ODO' => ODOCSVBuilder.class,
        'OD' => ODCSVBuilder.class
    };
    return ((CSVBuilder)dispatch.get(CSVTab).newInstance()).buildCSV(data);
}

You can add new implementations by adding a mapping to the dispatch table, and implementing the subclass, as desired. You can source from some other data point if you like; it doesn't have to be a list of SObject records.

The base abstract class can also provide some utility functions, such as the proper escaping of field values, etc; you can use those those functions common to both classes directly using that manner.

1
  • Thanks @sfdcfox. This is excellent notes and everyone should keep in their library as reference.
    – Bforce
    May 13, 2014 at 19:46

You must log in to answer this question.

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