function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
ApexDevApexDev 

Variable does not exist: Apex Batch

Hi Guys! 

I am newbie in Apex, but I am trying to write some code. The purpose was simple: I have PricebookEntry object on Salesforce, and 2 lookup fields: 
- Pricebook2Id
- Price_Book_2__c
I want to fill Price_Book_2__c with the same value as Pricebook2Id on each record.

When I opened and run batch in Anonymouse Window I get error: 
Line: 3, Column: 25
Variable does not exist: Pricebook2Id

Here is the Apex class: 

global class UpdatePriceBookCustomField implements Database.batchable<sObject>{
    global final String query;
    global Database.QueryLocator start (Database.BatchableContext BC) {
        return Database.getQueryLocator(query);}
    
    global void execute(Database.BatchableContext BC,List<sObject> scope){
        List<PricebookEntry>pbeToUpdate = new List<PricebookEntry>();
        
    for (sObject s : scope){PricebookEntry a = (PricebookEntry)s;
                            if(a.Price_Book_2__c==null){
                                a.Price_Book_2__c=a.Pricebook2Id;
                                pbeToUpdate.add(a);
                            }
                            }
    update pbeToUpdate;
        
    }
    global void finish(Database.BatchableContext BC) {
    }
}


Here is the batch: 
UpdatePriceBookCustomField PBE = new UpdatePriceBookCustomField();
PBE.query='Select Id, Pricebook2Id, Price_Book_2__c from PricebookEntry';
PBE.Price_Book_2__c=PBE.Pricebook2Id;
ID batchprocessid = Database.executeBatch(PBE);

Anyone has any idea why it don't want to run? I don't know why Apex is not seeing the Pricebook2Id...
Antoninus AugustusAntoninus Augustus
Hello and welcome to Salesforce. Here are a few tips to help improve your code a bit.

You don’t have to declare the class’s access modifier as ‘global’ unless you’re developing a managed package, otherwise use ‘public’.
For the second argument in the ‘execute’ method you’d want to define the sObject type for the scope list instead of using the generic ‘sObject’ like so:
public void execute(Database.BatchableContext context, List<PricebookEntry> lstPricebookEntries)
I saw you tried assigning the variable ‘query’ a value outside of the batch class. The class variable ‘query’ is set to final and cannot be changed. I recommend immediately assigning a value to this variable within the class and using it inside the ‘start’ method directly. I also recommend adding a WHERE clause in your query to get back only records that have ‘Price_Book_2__c’ set to null.
Database.getQueryLocator('SELECT ID, Pricebook2Id, Price_Book_2__c FROM PricebookEntry WHERE Price_Book_2__c = NULL');

Here's the overall idea of the updated class:
public class UpdatePriceBookCustomField implements Database.Batchable<sObject> {
    public Database.QueryLocator start(Database.BatchableContext context) {
        return Database.getQueryLocator('SELECT ID, Pricebook2Id, Price_Book_2__c FROM PricebookEntry WHERE Price_Book_2__c = NULL');
    }
    public void execute(Database.BatchableContext context, List<PricebookEntry> lstPricebookEntries) {
        for (PricebookEntry objPricebook : lstPricebookEntries) {
            objPricebook.Price_Book_2__c = objPricebook.Pricebook2Id;
        }
        update lstPricebookEntries;
    }
    public void finish(Database.BatchableContext context){}
}
As to your error, PBE is an instance of the class 'UpdatePriceBookCustomField'. This class doesn't have a Pricebook2Id variable, only the query variable you defined in it, which is type 'final' and would cause a runtime error when trying to change it. Hope this helps!
 
AnkaiahAnkaiah (Salesforce Developers) 
Hi Andzela,

As Leamsi said, you have missed the query in start method and you were not passing the PricebookEntry object.

Try with below code.
Public class UpdatePriceBookCustomField implements Database.batchable<sObject>{

    public Database.QueryLocator start (Database.BatchableContext BC) {
string query = 'select id,Price_Book_2__c,Pricebook2Id from PricebookEntry WHERE Price_Book_2__c ==Null ';
        return Database.getQueryLocator(query);}
    
    public void execute(Database.BatchableContext BC,List<PricebookEntry> scope){
        List<PricebookEntry>pbeToUpdate = new List<PricebookEntry>();
        
    for (sObject s : scope){
                        s.Price_Book_2__c=s.Pricebook2Id;
                   pbeToUpdate.add(s);
                  
         }
    update pbeToUpdate;
        
    }
    public void finish(Database.BatchableContext BC) {
    }
}
If this helps, Please mark it as best answer.

Thanks!!