I'm building a trigger that everytime a Campaign Member is added , Salesforce sends an email to the Owner of the Account where the Contact Lives that a Campaign Member is added.

Due to Salesforce governor limits I can query my way through the data, so I'm storing the data on Lists of Ids, Contacts, Accounts and Users.

I want now to create, based from that Data, a List that would look like a table with Rows and Columns. Something like these:

Info[0]='Contact Id', 'Account Id' ,'UserId','User Email'

Info[1]='Contact Id', 'Account Id' ,'UserId','User Email'

Info[2]='Contact Id', 'Account Id' ,'UserId','User Email'

Info[3]='Contact Id', 'Account Id' ,'UserId','User Email'

Right now I'm using this:

List<List<string>> lists = new List<List<string>>();

And thought(Incorrectly) that I could just add the info like this:

lists[0][0] = ContactId;
lists[0][1] = AccountId;

Using this method I'm getting the error: List index out of bounds: 0

Hope you can help me.

  • Made a typo. It should said 'I want NOW to create' insted of 'I want not to create'
    – ErFran
    Apr 17 '19 at 6:27
  • If you want to aggregate data like that a wrapper class is normally a good way to go, any reason you haven't used one?
    – Girbot
    Apr 17 '19 at 7:21

To resolve your issue you simply need to ensure that you have actually created the lists themselves. Remember that a list is just another type of object, so is held by reference, and that reference can be null.

You need to do something like:

if (lists == null) {
    lists = new List<List<String>>();

lists.add(new List<String> {
        ContactId, AccountId, UserId, UserEmail

I would, however, suggest you actually manage a list of object instances. You can declare yourself a nested class like:

public class TheMainClass {
    public class EmailDetail {
        public Id contactId { get; set; }
        public Id accountId { get; set; }
        public Id userId { get; set; }
        public String userEmail { get; set; }

        public EmailDetail(Id contactId, Id accountId, Id userId, String userEmail) {
            this.contactId = contactId;
            this.accountId = accountId;
            this.userId = userId;
            this.userEmail = userEmail;

Your list would be like:

List<TheMainClass.EmailDetail> emailDetails = new List<TheMainClass.EmailDetail>();

Then later in your code you can add new entries to your list:

emailDetails.add(new TheMainClass.EmailDetail(contactId, accountId, userId, userEmail));

The big benefits here are that:

  1. Accessing the data is like emailDetails[n].contactId rather than lists[n][0]
  2. The various properties are strongly typed, so you can only put an Id in the ID values

I might even take it a step further and consider using a map, indexed by target user ID, of slightly different details if I wanted to ensure that a given user only received a single email with the detail of the contacts across all relevant accounts.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.