+ Start a Discussion
Anthony Zirilli 10Anthony Zirilli 10 

Create multiple records without recursively firing trigger

Hi there, 

I'm a little stuck on how to create a number of new child records on a parent object. I've been able to do it below a little half haphazardly by having the trigger fire multiple times until my two fields, “copy count” and a roll up field “Total Number of Line Items” are equal. Any insight on how to approach this to create the multiple line item records when Copy Count is less than the Total Number of Line Items so that copy count is equal to total number of line items. Thank you in advance.
Anthony
 
Current trigger below (When copy count increases by 15, "maximum trigger depth excedded" error is tripped):

trigger CreatePrintCopyLineItem on Print_Copy__c (before insert,after update) {

    List <Print_Copy_Line_Item__c> LineItemToInsert = new List <Print_Copy_Line_Item__c> ();
    
    for (Print_Copy__c PrintCopy : Trigger.new) {
    
       
       if (PrintCopy.Copy_Count__c>PrintCopy.Total_Number_of_Line_Items__c) {
       
       Print_Copy_Line_Item__c LineItemToAdd = new Print_Copy_Line_Item__c ();
       
       LineItemToAdd.Print_Copy__c=PrintCopy.Id;
       
       
       LineItemToInsert.add(LineItemToAdd);
       
       
       }
       
    }
    
    insert LineItemToInsert;
    
    
    }

Best Answer chosen by Anthony Zirilli 10
Amit Chaudhary 8Amit Chaudhary 8
Hi Anthony Zirilli 10,

Please check below blog how to stop recursive trigger in salesforce
http://amitsalesforce.blogspot.in/2015/03/how-to-stop-recursive-trigger-in.html

Solution :-
you can create a class with a static Boolean variable with default value true. In the trigger, before executing your code keep a check that the variable is true or not. Once you check make the variable false.

 Apex Class with Static Variable
public class ContactTriggerHandler
{
     public static Boolean isFirstTime = true;
}

Trigger Code
trigger ContactTriggers on Contact (after update)
{
    Set<String> accIdSet = new Set<String>(); 
    if(ContactTriggerHandler.isFirstTime)
    {
        ContactTriggerHandler.isFirstTime = false;
         for(Contact conObj : Trigger.New)
  {
            if(conObj.name != 'Test') 
     {
                accIdSet.add(conObj.accountId);
            }
         }
   // any code here
    }
}

I hope this will help you.


In your case. Please create one handler class like below :-
public class PrintCopyHandler
{
     public static Boolean isFirstTime = true;
}

Then Update your Trigger like below :-
trigger CreatePrintCopyLineItem on Print_Copy__c (before insert,after update) 
{
	if(PrintCopyHandler.isFirstTime)
    {
        PrintCopyHandler.isFirstTime = false;
		List <Print_Copy_Line_Item__c> LineItemToInsert = new List <Print_Copy_Line_Item__c> ();
		for (Print_Copy__c PrintCopy : Trigger.new) 
		{
			if (PrintCopy.Copy_Count__c>PrintCopy.Total_Number_of_Line_Items__c) 
			{
			   Print_Copy_Line_Item__c LineItemToAdd = new Print_Copy_Line_Item__c ();
			   LineItemToAdd.Print_Copy__c=PrintCopy.Id;
			   LineItemToInsert.add(LineItemToAdd);
			}
		}
		insert LineItemToInsert;
	}	
}

Please let us know if this will help you.

Thanks
Amit Chaudhary
amit.salesforce21@gmail.com

All Answers

Vivek DeshmaneVivek Deshmane
Hi Anthony,

You are getting this error because your trigger recursively calling himself. So to overcome with that you have to declare a static variable (Boolean type) in another class and make certain criteria based on that static variable inside your trigger. Please go through this link for more details:
 
http://developer.force.com/cookbook/recipe/controlling-recursive-triggers
 
Please let me know if it resovles your problem.
Best Regards,
-Vivek
vivek.deshmane@gmail.com
ManojjenaManojjena
Hi Anthony ,

Your trigger fall under recursion as your roll up summery field will update parent record and after that again your trigger will fire after update .

So you need to stop recursion by using below code .

 
//create a class like below .

public Class checkRecursive{
    private static boolean run = true;
    public static boolean runOnce(){
		if(run){
		 run=false;
		 return true;
		}else{
			return run;
		}
    }
}
//Try below trigger code it will help for sure 
trigger CreatePrintCopyLineItem on Print_Copy__c (after insert,after update) {
    if(checkRecursive.runOnce()){
		List <Print_Copy_Line_Item__c> lineItemToInsert = new List <Print_Copy_Line_Item__c> ();
		for (Print_Copy__c printCopy : Trigger.new) {
		  if (printCopy.Copy_Count__c > printCopy.Total_Number_of_Line_Items__c) {
			Print_Copy_Line_Item__c lineItemToAdd = new Print_Copy_Line_Item__c ();
			  lineItemToAdd.Print_Copy__c=printCopy.Id;
			  lineItemToInsert.add(lineItemToAdd);
		   }
		}
		try{
			insert lineItemToInsert;
	   }catch(dmlException de ){
	      System.debug(de);
	   }
   }
}

Let us know if it help !!
Thanks 
Manoj
Anthony Zirilli 10Anthony Zirilli 10
Thanks for the feedback. I put the above code in and says there is a Compile error. Unexpected token: Public. I not sure how to fix this error. 
viruSviruS
Put    Class Code in separeate class file with name checkRecursive


public Class checkRecursive{ private static boolean run = true; public static boolean runOnce(){ if(run){ run=false; return true; }else{ return run; } } }
 
Amit Chaudhary 8Amit Chaudhary 8
Hi Anthony Zirilli 10,

Please check below blog how to stop recursive trigger in salesforce
http://amitsalesforce.blogspot.in/2015/03/how-to-stop-recursive-trigger-in.html

Solution :-
you can create a class with a static Boolean variable with default value true. In the trigger, before executing your code keep a check that the variable is true or not. Once you check make the variable false.

 Apex Class with Static Variable
public class ContactTriggerHandler
{
     public static Boolean isFirstTime = true;
}

Trigger Code
trigger ContactTriggers on Contact (after update)
{
    Set<String> accIdSet = new Set<String>(); 
    if(ContactTriggerHandler.isFirstTime)
    {
        ContactTriggerHandler.isFirstTime = false;
         for(Contact conObj : Trigger.New)
  {
            if(conObj.name != 'Test') 
     {
                accIdSet.add(conObj.accountId);
            }
         }
   // any code here
    }
}

I hope this will help you.


In your case. Please create one handler class like below :-
public class PrintCopyHandler
{
     public static Boolean isFirstTime = true;
}

Then Update your Trigger like below :-
trigger CreatePrintCopyLineItem on Print_Copy__c (before insert,after update) 
{
	if(PrintCopyHandler.isFirstTime)
    {
        PrintCopyHandler.isFirstTime = false;
		List <Print_Copy_Line_Item__c> LineItemToInsert = new List <Print_Copy_Line_Item__c> ();
		for (Print_Copy__c PrintCopy : Trigger.new) 
		{
			if (PrintCopy.Copy_Count__c>PrintCopy.Total_Number_of_Line_Items__c) 
			{
			   Print_Copy_Line_Item__c LineItemToAdd = new Print_Copy_Line_Item__c ();
			   LineItemToAdd.Print_Copy__c=PrintCopy.Id;
			   LineItemToInsert.add(LineItemToAdd);
			}
		}
		insert LineItemToInsert;
	}	
}

Please let us know if this will help you.

Thanks
Amit Chaudhary
amit.salesforce21@gmail.com
This was selected as the best answer
SaranSaran
Hi Anthony,

Try the below code.
 
trigger CreatePrintCopyLineItem on Print_Copy__c (before insert,after update) {

    List <Print_Copy_Line_Item__c> LineItemToInsert = new List <Print_Copy_Line_Item__c> ();
    
    for (Print_Copy__c PrintCopy : Trigger.new) {

        if(PrintCopy.Copy_Count__c > PrintCopy.Total_Number_of_Line_Items__c) {
        	Integer count = PrintCopy.Copy_Count__c - PrintCopy.Total_Number_of_Line_Items__c;

        	for(integer i=0;i < count; i++)
        	{
		        Print_Copy_Line_Item__c LineItemToAdd = new Print_Copy_Line_Item__c ();
		        LineItemToAdd.Print_Copy__c=PrintCopy.Id;
		        LineItemToInsert.add(LineItemToAdd);
	        }
        }
       
    }
    
    if(LineItemToInsert.size() > 0)
    	insert LineItemToInsert;
}

This might work correctly as you expected.

Thanks
Anthony Zirilli 10Anthony Zirilli 10
Thanks for the help. That seemed to work, but by making the trigger fire once it stops the total number of line items from equaling te copy count field. How should the code be changed so that when a record is created or edited. It will create the right number of line items. Thanks!

 User-added image
SaranSaran
Hi Anthony,

Use the below code.
 
trigger CreatePrintCopyLineItem on Print_Copy__c (before insert,after update) {

    List <Print_Copy_Line_Item__c> LineItemToInsert = new List <Print_Copy_Line_Item__c> ();
    
    for (Print_Copy__c PrintCopy : Trigger.new) {

        if(PrintCopy.Copy_Count__c > PrintCopy.Total_Number_of_Line_Items__c) {
        	Integer count = PrintCopy.Copy_Count__c - PrintCopy.Total_Number_of_Line_Items__c;

        	for(integer i=0;i < count; i++)
        	{
		        Print_Copy_Line_Item__c LineItemToAdd = new Print_Copy_Line_Item__c ();
		        LineItemToAdd.Print_Copy__c=PrintCopy.Id;
		        LineItemToInsert.add(LineItemToAdd);
	        }
 PrintCopy.Total_Number_of_Line_Items__c = PrintCopy.Copy_Count__c;
        }      
    }
    
    if(LineItemToInsert.size() > 0)
    	insert LineItemToInsert;
}

Hope this works as you expected.

Thanks
 
Anthony Zirilli 10Anthony Zirilli 10
Thanks for all the replys. The above code works great after i remved the "PrintCopy.Total_Number_of_Line_Items__c = PrintCopy.Copy_Count__c" line. It said it was not writeable. Also when I tried to insert bulk records into Salesforce, I got the error "Too many SOQL queries: 101 Status code: 16". How would I go about bulkifying this code? Thank again.