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
Kyle BrandtKyle Brandt 

Insert CSV using batch class

I want to add a button to my opportunity header record that is called Insert Products. This will send the opportunity ID to a visualforce page which will have a select file button and an insert button that will loop through the CSV and insert the records to the related opportunity.

This is for non technical users so using Data loader is not an option.

I got this working using standard apex class however hit a limit when i load over 1,000 records (which would happen regularly).

I need to convert this to a batch process however am not sure how to do this.

Any one able to point me in the right direction? I understand a batch should have a start, execute and finish. However i am not sure where i should split the csv and where to read and load?

I found this link which i could not work out how to translate into my requirements:

Here is the code i have for the standard apex class which works.
public class importOppLinesController {
public List<OpportunityLineItem> oLiObj {get;set;}
public String recOppId {
        // *** setter is NOT being called ***
        set {
            recOppId = value;
public Blob csvFileBody{get;set;}
public string csvAsString{get;set;}
public String[] csvFileLines{get;set;}

public List<OpportunityLineItem> oppLine{get;set;}
  public importOppLinesController(){
    csvFileLines = new String[]{};
    oppLine = New List<OpportunityLineItem>();
  public void importCSVFile(){

       PricebookEntry pbeId;
       String unitPrice = '';

           csvAsString = csvFileBody.toString();
           csvFileLines = csvAsString.split('\n
           for(Integer i=1;i<csvFileLines.size();i++){
               OpportunityLineItem oLiObj = new OpportunityLineItem() ;
               string[] csvRecordData = csvFileLines[i].split(',');

               String pbeCode = csvRecordData[0];
                pbeId = [SELECT Id FROM PricebookEntry WHERE ProductCode = :pbeCode AND Pricebook2Id = 'xxxx HardCodedValue xxxx'][0];                  

                oLiObj.PricebookEntryId = pbeId.Id;

               oLiObj.Quantity = Decimal.valueOf(csvRecordData[1]) ;
               unitPrice = String.valueOf(csvRecordData[2]);
               oLiObj.UnitPrice =  Decimal.valueOf(unitPrice);

               oLiObj.OpportunityId = 'recOppId';;
               insert (oLiObj);
        catch (Exception e)

             ApexPages.Message errorMessage = new ApexPages.Message(ApexPages.severity.ERROR, e + ' - ' + unitPrice);


Carolina Ruiz MedinaCarolina Ruiz Medina
Hi Kyle, 
The code from the link that you are sharing basically is reading the CSV file and populating the values into the list called : csvLines. 
Therefore you will only need to add your logic where the coments are: 
      //TODO: csvLines contains a List with the values of the CSV file.
       //These information will be used to create a custom object to
       //process it.
It would be also nice if you check  the values saved in the list csvLines are the ones you need, before you implement your logic, just in case you need to add some code in the class that is reading the csv and populating the values in the list.

I'm guessing reading your code that what you actually do with the values of the CSV is to query the pricebookEntry where the productCode is the same as the one is in the CSV. 
Then this is what you will need to do, use this csvLines to query all the pricebookentries. 
I would also recomend to do one query to bring all the pricebooks instead to use one query pear each as it could lead you so quickly into limits problem. ( only 100 queries per transaction synchronously, 200 async. ) 
Another recomendation would be to do only one insert for all the records, as you have governor limits here too ( 150 DML) 
A good reading too is Trigger Bulkification.
Hope it helps. 


Kyle BrandtKyle Brandt
Hi Carolina,

Thanks for the reply. 
Sorry for some basic questions here.

firstly the comment: //TODO: Create a map with the column name and the position.
Would this be a mapping of the CSV columns or mapping the object and column?

If i have a commandbutton sending this CSV file how do i call the batch job? Do i send the command button to an apex class that then uses a database.execute command?

Sorry again for how basic this is, i am feeling a little out of my depth.
Kyle BrandtKyle Brandt
Thanks for trying to help but i think i am going to give up on this, it's too hard for me. I tried loading CSVReader class from the post and it errors because CSVValue isnt a valid type. 
Bhaswanthnaga vivek vutukuriBhaswanthnaga vivek vutukuri

@kyle Brandt - No it's not hard. it worked for me :) if you have any doubts feel free to contract me my email -

Niranjan Reddy 19Niranjan Reddy 19
Hi Vivek,
I'm facing same issue, can you please help me to recolve the same.