I am trying to create a dynamic query to csv class that will take any query and convert it to a csv and send it back to the caller. I would like to use keith-c's format logic because it's way cool and needed. BUT sobject.get('fieldname') returns back an Object.

I either need to cast it to the correct datatype or deal with it some how.

Any thoughts would be great, I don't want to create classes for every sobject type.


public class ConvertToCsv {

public static Blob convert(CustomQuery.CustomQueryResult pResult) {

String csvFile;
List<String> tmpFieldList = new List<String>();
List<String> tmpRow = new List<String>();

for (String field :pResult.getFields()) {

csvFile = ConvertToCsv.line(tmpFieldList);

for (sObject row :pResult.getResults) {
  for (String fieldKey :pResult.getFields()) {
  csvFile += ConvertToCsv.line(tmpRow);
  tmpRow = new List<String>();

return Blob.valueOf(csvFile);

private static String line(String[] cells) {
return String.join(cells, ',') + '\n';
private static String format(Date d)    {
return d != null ? '"' + d.format().escapeCsv() + '"' : '""';
private static String format(String s) {
return s != null ? '"' + s.escapeCsv() + '"' : '""';
private static String format(Decimal d, Integer scale) {
return d != null ? String.valueOf(d.setScale(scale)) : '';
private static String format(Decimal d) {
 return format(d, 2);
  • doesn't instanceOf help you here? As in if (row.get(fieldKey) instanceOf Date) tmpRow.add(ConvertToCsv((Date)row.get(fieldKey)) else if(row.get(fieldKey instanceOf Decimal) ...
    – cropredy
    Nov 6, 2015 at 1:43
  • I've done this before, but ended up using field describes to get the datatype, and then running an if/else tree on the field/data type to return the string representation in the desired format. I couldn't figure a better way than to convert them the way I wanted the file to be created. I can dig up my solution if you want me to post it as an answer?
    – Ben Naylor
    Nov 6, 2015 at 2:57

1 Answer 1


Decided I should just post my transformation tree. This could be better as a function, doing early returning, all that sort of stuff, but I was coding lazily at the time:

for (String field : this.fields) {

    //we only add it if there is a value, and we need to augment the output value based on the data type
    String fieldType = this.fieldTypes.get(field);
    if (s.get(field) != null) {
        if (fieldType == 'STRING' || fieldType == 'EMAIL' || fieldType == 'PICKLIST' || fieldType == 'REFERENCE' || fieldType == 'BASE64' || fieldType == 'TEXTAREA' || fieldType == 'ID' || fieldType == 'PHONE' || fieldType == 'URL') line += '"' + (String)s.get(field) + '"';
        if (fieldType == 'BOOLEAN') line += (((Boolean)s.get(field))?'true':'false');
        if (fieldType == 'DATE') line += Datetime.newInstance((Date)s.get(field), Time.newInstance(0,0,0,0)).format('yyyy-MM-dd');
        if (fieldType == 'DATETIME') line += ((Datetime)s.get(field)).format('yyyy-MM-dd hh:mm:ss');
        if (fieldType == 'INTEGER') line += (Integer)s.get(field);
        if (fieldType == 'DECIMAL' || fieldType == 'PERCENT' || fieldType == 'CURRENCY' || fieldType == 'DOUBLE') line += (Decimal)s.get(field);
    line += ',';

this.fields is a List of all the fields in the object (Account.getDescribe().fields.getMap().keyset() should do it I think).

this.fieldTypes is a Map of fieldname to datatype. This was created by looping through the fields.getMap() result, and calling .getType() on each field (returns a string used in the IF above).

As a utility class it could work, but theres a bunch of logic in there that might take a bit of processing time that could be optimised out.

You must log in to answer this question.

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