5

I'm trying to schedule an apex class to run once every month to reset a number field on all Accounts to 0.

global class updateMonthlyActivityCount Implements Schedulable{
public list<Account> updatedList ;

global void execute(SchedulableContext sc) {
    updateAcc();
}

@future 
public static void updateAcc(){
    List<Account> updatedList = new List<Account>();
    List<Account> accList = [SELECT Id, Monthly_Activity_Count__c FROM Account WHERE Monthly_Activity_Count__c = null OR Monthly_Activity_Count__c > 0];
    for(Account a:accList){
        a.Monthly_Activity_Count__c = 0;
        updatedList.add(a);
    }
        update updatedList;
    }
}

Since this is running on all Accounts, I also have a number of processes / flows on Accounts that get triggered when created / edited, which is what I suspect the issue is by getting the error Too many DML rows: 10001

I also noticed it says First error: Apex CPU time limit exceeded on method updateAcc when I look at the status under Apex Jobs.

Any idea how I can get around this? Thanks!

6
  • Have you looked into Batches? Apr 8, 2016 at 20:34
  • @SebastianKessel Looking into that right now actually, I'm a bit new to SF and Apex coding, not sure exactly how to take my current class and turn that into batch class and run once per month?
    – AJK
    Apr 8, 2016 at 20:36
  • I'm getting a sample ready for you... hold a sec Apr 8, 2016 at 20:36
  • 2
    @SebastianKessel Sorry... I just saw the comment. Didn't mean to steal your thunder.
    – sfdcfox
    Apr 8, 2016 at 20:42
  • Ouch. I just posted it, too. :) Code looks nearly identical to yours Apr 8, 2016 at 20:42

2 Answers 2

4

AJ,

This code should get you going. It allows you to schedule and batch....

global class updateMonthlyActivityCount Implements Schedulable,  Database.Batchable<sObject> {

    global void execute(SchedulableContext sc) {
        Database.executeBatch(this, 200); //You can change the "200" number for anything else
    }

    global Database.QueryLocator start(Database.BatchableContext BC) {
        string query = 'SELECT Id, Monthly_Activity_Count__c FROM Account WHERE Monthly_Activity_Count__c = null OR Monthly_Activity_Count__c > 0';

        return new Database.getQueryLocator(query);

    }

    global void execute(Database.BatchableContext BC, List<sObject> scope) {
        List<Account> accList = (List<Account) scope;

        for(Account a : accList){
            a.Monthly_Activity_Count__c = 0;
        }

        update accList;
    }

    global void finish(Database.BatchableContext BC) {

    }
}
0
4

Your future method won't help you-- you need a batch or queueable class. This is actually really easy, we just need to move some code around:

global class updateMonthlyActivityCount Implements Schedulable, Database.Batchable<SObject> {    
    global void execute(SchedulableContext sc) {
        Database.executeBatch(this);
    }

    global Database.QueryLocator start(Database.BatchableContext context) {
        return Database.getQueryLocator([SELECT Id FROM Account WHERE Monthly_Activity_Count__c = null OR Monthly_Activity_Count__c > 0]);
    }

    global void execute(Database.BatchableContext context, Account[] accList) {
        for(Account a:accList){
            a.Monthly_Activity_Count__c = 0;
        }
        update accList;
    }

    global void finish(Database.BatchableContext context) {

    }
}

This will process your records in batches of 200 at a time, and you can schedule it to run through the UI or by code.

1
  • 2
    Thank you for the help! I tested and both worked like charm..wish I could select 2 answers!
    – AJK
    Apr 8, 2016 at 21:28

You must log in to answer this question.

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