You need to sign in to do that
Don't have an account?
Akhil Tyagi
Import bulk contact records from csv using vf page
I want to import bulk contact records to insert from csv file using vf page.
I am able to insert around 1000 records but if there are than 1000 records, i get an error of 'time limit exceeded'.
Here is my VF Page:
I am able to insert around 1000 records but if there are than 1000 records, i get an error of 'time limit exceeded'.
Here is my VF Page:
<apex:page controller="UploadCSVController"> <h1 style="font-size:30px"><center>CSV Uplaod Page</center></h1><br/><br/> <apex:form id="idForm"> <apex:pageMessages /><br/><br/> <apex:pageBlock tabStyle="Contact" id="idInputBlock"> <p style="height:13px; font-size:13px"><b>Set the first column of the CSV file as LastName Field:</b></p><br/> <apex:inputFile value="{! fileBody}" fileSize="{! fileSize}" fileName="{! fileName}" accept=".csv" contentType="text/csv" id="idInputFile"></apex:inputFile> <!-- Input File --> <apex:commandButton value="Upload File" action="{! ReadFromFile}" onclick="document.getElementById('actionStatusUP').style.display = 'inline';" /> <!-- Upload Button to upload file --> <img src="/img/loading.gif" style="display:none" id="actionStatusUP" /> <apex:pageBlockButtons location="bottom" > <!-- Save Button to insert the records --> <apex:commandButton value="Save" action="{! save}" rendered="{! reVariableSave}" onclick="document.getElementById('imageSV').style.display = 'inline';" /> <img src="/img/loading.gif" style="display:none" id="imageSV" /> </apex:pageBlockButtons> </apex:pageBlock> <apex:pageBlock rendered="{! reVariableBlock}" id="idTable"> <apex:pageBlockSection collapsible="false" columns="2" > <p><b>Total Records in CSV File: </b></p> <apex:outputText value="{! totalRecords}" style="color:black" /> <p><b>Number of Records Successfully inserted: </b></p> <apex:outputText value="{! insertedRecords}" style="color:green" /> <p><b>Number of Failed Records: </b></p> <apex:outputText value="{! failedRecords}" style="color:red" /> </apex:pageBlockSection><br/> <center><p style="color:dodgerblue;font-size:25px"><b>Details of the inserted records</b></p></center><br/><br/> <apex:pageBlockTable value="{! contactsList}" rendered="{! reVariable}" var="con" > <!-- Table to display details of inserted records --> <apex:repeat value="{! fieldNamesList}" var="fld" > <apex:column value="{! con[fld]}" /> </apex:repeat> </apex:pageBlockTable> </apex:pageBlock> </apex:form> </apex:page>Here is my controller code:
public with sharing class UploadCSVController { //Public Variables---------------------------------------------------------------------------------------------------------------------------------------------- public transient Blob fileBody{ get; set; } //fileBody public transient Integer fileSize{ get; set; } //fileSize public transient String fileName{ get; set; } //fileName public List<Contact> contactsList{ get; set; } //List of inserted contacts public List<String> fieldNamesList{ get; set; } //List of fields in Contact Object's fields which are avaiable in CSV public Boolean reVariableSave{ get; set; } //Variable to render Save Button public Boolean reVariableBlock{ get; set; } //Variable to render PageBlock with inserted record details public Boolean reVariable{ get; set; } //Variable to render Record Details Table public Integer totalRecords{ get; set; } //Total number of records in CSV File public Integer insertedRecords{ get; set; } //Number of records successfully inserted public Integer failedRecords{ get; set; } //Number of failed records //Private Variables---------------------------------------------------------------------------------------------------------------------------------------------- String fileBodyAsString = ''; //String value of file Body String header = ''; //Constructor---------------------------------------------------------------------------------------------------------------------------------------------------- public UploadCSVController(){ contactsList = new List<SObject>(); fieldNamesList = new List<String>(); reVariableSave = false; reVariableBlock = false; reVariable = false; totalRecords = 0; insertedRecords = 0; failedRecords = 0; } //Method to check file size and whether the file body is readable------------------------------------------------------------------------------------------------ public void ReadFromFile(){ reVariableBlock = false; if(fileSize < 3280760 && fileName.substringAfterLast('.').equalsIgnoreCase('csv')){ try{ fileBodyAsString = fileBody.toString(); ReadCSVFile(); } catch(exception e){ ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'Error reading CSV file')); } } else{ ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'No File Chosen or,')); ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'File Size greater than 50 KB or,')); ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR,'File is not of CSV type')); } } //Method to read the file and create a contact list which will be inserted and check exceptions in CSV file------------------------------------------------------ private void ReadCSVFile(){ if(fileBodyAsString.length() > 100000){ header = fileBodyAsString.substring(0, 2000).split('\n')[0]; } else{ header = fileBodyAsString.split('\n')[0]; } fileBodyAsString = fileBodyAsString.substringAfter('\n'); contactsList.clear(); fieldNamesList.clear(); for(String str : header.split('\n')[0].split(',')){ fieldNamesList.add(str.trim()); } String contactDetails = ''; Map<string, SObjectField> fieldNamesMap = Schema.getGlobalDescribe().get('Contact').getDescribe().fields.getMap(); if(fieldNamesList[0].equalsIgnoreCase('LastName')){ Contact con = new Contact(); Integer flag = 0; while( !String.isEmpty(fileBodyAsString)){ //Itereation over each contact if(fileBodyAsString.length() > 100000){ contactDetails = fileBodyAsString.substring(0, 100000).split('\n')[0]; } else{ contactDetails = fileBodyAsString.split('\n')[0]; } fileBodyAsString = fileBodyAsString.substringAfter('\n'); String lastnameValue = contactDetails.substringBefore(',').trim(); for(Integer j=0; j<fieldNamesList.size(); j++){ //Iterating over the fields & assigning value to them for each contact Schema.DisplayType fieldType = fieldNamesMap.get(fieldNamesList[j]).getDescribe().getType(); if( fieldType == Schema.DisplayType.DATE ){ //Setting value of fields which are of Date Type try{ con.put(fieldNamesList[j].trim(), Date.valueOf(contactDetails.substringBefore(',').trim())); } catch(Exception e){ flag = 1; ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Empty ' + fieldNamesList[j].trim() + ' field or Date is not in format \"YYYY-MM-DD\" for record with LastName = ' + lastnameValue)); } } else if( fieldType == Schema.DisplayType.DATETIME ){ //Setting value of fields which are of DateTime Type try{ con.put(fieldNamesList[j].trim(), Datetime.valueOf(contactDetails.substringBefore(',').trim())); } catch(Exception e){ flag = 1; ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Empty ' + fieldNamesList[j].trim() + ' field or DateTime is not in format \"YYYY-MM-DD HH:MM:SS\" for record with LastName = ' + lastnameValue)); } } else if( fieldType == Schema.DisplayType.BOOLEAN ){ //Setting value of fields which are of Boolean Type if(contactDetails.substringBefore(',').trim().equalsIgnoreCase('true') || contactDetails.substringBefore(',').trim().equalsIgnoreCase('false') || contactDetails.substringBefore(',').trim() == ''){ con.put(fieldNamesList[j].trim(), Boolean.valueOf(contactDetails.substringBefore(',').trim())); } else{ flag = 1; ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'Acceptable value for ' + fieldNamesList[j].trim() + ' field is \"TRUE/FALSE\" for record with LastName = ' + lastnameValue)); } } else if( fieldType == Schema.DisplayType.TEXTAREA ){ //Setting value of fields which are of TextArea Type if(contactDetails.left(1) != '\"'){ //Setting value of fields which are of TextArea Type with comma con.put(fieldNamesList[j].trim(), contactDetails.substringBefore(',').trim()); } else{ //Setting value of fields which are of TextArea Type without comma con.put(fieldNamesList[j].trim(), contactDetails.substringBetween('\"', '\"') .trim()); contactDetails = contactDetails.substringAfter('\"').substringAfter('\"'); } } else{ //Setting value of all other type of fields try{ con.put(fieldNamesList[j].trim(), contactDetails.substringBefore(',').trim()); } catch(Exception e){ flag = 1; } } contactDetails = contactDetails.substringAfter(','); } contactsList.add(con); con = new Contact(); } if(flag != 1){ //If there is no exception, show Save button reVariableSave = true; ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.INFO, 'Click Save Button to insert the Records ')); } } else{ ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, 'First Column in CSV file is not LastName. Set the first column in CSV file as LastName')); } } //Save method to insert the Contact Recods and counting inserted records and failed records---------------------------------------------------------------------- public Pagereference save(){ reVariableBlock = true; Database.SaveResult[] srList = Database.insert(contactsList, false); contactsList.clear(); Set<Id> savedContactIdSet = new Set<Id>(); totalRecords = 0; insertedRecords = 0; failedRecords = 0; for (Database.SaveResult sr : srList) { ++totalRecords; if (!sr.isSuccess()) { ++failedRecords; for(Database.Error err : sr.getErrors()) { ApexPages.addMessage(new ApexPages.Message(ApexPages.Severity.ERROR, err.getStatusCode() + ': ' + err.getMessage() + ' for Record at Line Number: ' + (totalRecords + 1))); } } else{ ++insertedRecords; savedContactIdSet.add(sr.getId()); } } contactsList = Database.query('SELECT ' + header + ' FROM Contact WHERE Id in :savedContactIdSet'); if(contactsList.size() > 0 && contactsList.size()<400){ reVariable = true; } return null; } }Please help me with the solution on how to insert more than 10,000 reocrds without hitting the time limit exceed limt.
Dushyant Sonwar
The Only solution for this problem would be to break the csv file into smaller chunks using apex code , so it can process easily otherwise directly processing 10,000 records(approx 1Mb) file will lead to either view state , CPU Time limit or apex heap size error errors.