I want to create csv files from lists and send an email attaching them, how to do that in a controller method?
2 Answers
Rob's link is interesting and worth considering, though it looks like you have to pull the report data by making HTTPS requests which apart from code involves setting up Remote Site Settings.
Assuming the volume of data is reasonably small (so governor limits don't get hit) below is some simple Apex code that will produce a CSV string that can be adapted to other SObjects (and have its format methods tweaked and added to). You can Google to find other similar code or code that works more generically (is not tied to a specific SObject or set of fields) if that is a requirement.
Documentation like this Creating an Email Attachment explains how to add the resulting data to an email (a file is never needed it can all be done in memory) and Blob.valueOf
converts a String to a Blob.
public class Csv {
public String generate(List<Contact> contacts) {
String s = line(new String[] {
format('First Name'),
format('Last Name'),
format('Birthdate'),
format('Email'),
format('Phone')
});
for (Contact c : contacts) {
s += line(new String[] {
format(c.FirstName),
format(c.LastName),
format(c.Birthdate),
format(c.Email),
format(c.Phone)
});
}
return s;
}
private String line(String[] cells) {
return String.join(cells, ',') + '\n';
}
private String format(Date d) {
return d != null ? '"' + d.format().escapeCsv() + '"' : '""';
}
private String format(String s) {
return s != null ? '"' + s.escapeCsv() + '"' : '""';
}
private String format(Decimal d, Integer scale) {
return d != null ? String.valueOf(d.setScale(scale)) : '';
}
private String format(Decimal d) {
return format(d, 2);
}
}
A test for it:
@isTest
private class CsvTest {
@isTest
static void generate() {
Contact[] contacts = new Contact[]{
new Contact(
FirstName = 'Jane',
LastName = 'Doe'
),
new Contact(
FirstName = 'John',
LastName = 'Smith',
Birthdate = Date.newInstance(1985, 2, 3),
Email = '[email protected]',
Phone = '222 444 55555'
)
};
insert contacts;
String expected = ''
+ '"First Name","Last Name","Birthdate","Email","Phone"\n'
+ '"Jane","Doe","","",""\n'
+ '"John","Smith","2/3/1985","[email protected]","222 444 55555"\n'
;
System.assertEquals(expected, new Csv().generate(contacts));
}
}
-
Isn't there a danger with the date.format() converting to the running users timezone?– Phil BMay 18, 2015 at 17:34
-
@PhilB Nice thing about Apex having a Date type is no timezone issues there. But fair point for DateTime values - care needed over which format method is used.– Keith CMay 18, 2015 at 17:43
I think this link will be useful in pulling the relevant data in .csv format. --- Can report data be accessed programatically?