I need to count how many fields were populated in a lead, every time a Lead is created.

I'm using the count() statement, to query the fields that need to be counted.

In the trigger, the following code is giving me an error, of illegal type assignment(List to List):

for (Lead ld : Trigger.new){
    List<Lead> Fields = new List<Lead>();       
    Fields  = [SELECT COUNT (FirstName), COUNT (LastName), COUNT(Email), COUNT(Phone), COUNT(Website), COUNT(Title) FROM Lead WHERE id = :Trigger.new];

Why is this error is happening?

Thanks in advance!!


Depending on where you get/see/view the error, Salesforce can have a hard time displaying the entire message (because < and > are what xml/html use, and rendering html based on user input all willy-nilly is not a good idea).

I suspect the more complete error message is

Illegal assignment from List<AggregateResult> to List<Lead>

When you start using aggregate functions (AVG(), COUNT(), MAX(), etc...), your query will return a List<AggregateResult>, which cannot be cast to a List<Lead> (or any other list of a concrete SObject type). Since the types are incompatible, you get this error.

Before you get too much further though

There are exceedingly few situations where a query in a loop is a good idea, and this is not one of those situations. This trigger will run into the SOQL query governor limit if you (or someone else) inserts >= 101 leads at once.

You should instead use getPopulatedFieldsAsMap(). Looking at the size of the Map<String, Object> you get in return will tell you how many fields were populated with non-null values. Whatever keys are missing are fields you know were not populated.

A brief example

Set<String> targetFields = new Set<String>{'Name', 'OwnerId', 'BillingStreet', 'Phone', 'Fax'};

for(Account acct :[SELECT Name, OwnerId, BillingStreet, Phone, Fax FROM Account]){
    // This gives you the total number of populated fields

    // If you want to know which fields are/aren't populated, use retainAll()/removeAll()
    //   respectively
    // Before that, though, we need to clone our targetFields set so we don't destroy 
    //   its data
    Set<String> tempFields = targetFields.clone();

    // print out the unpopulated fields (unpopulated since we used removeAll())

I am unsure of how this behaves when you have a default value defined for a field.

| improve this answer | |
  • Thanks for the awesome response Derek :) – Growred Oct 12 at 23:51

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.