# How to read and capture a particular data from particular index in CSV file

I have created one csv parser with vf page and controller. But my requirement is to read and capture particular data from particular index.so i want apex method to capture particular data from particular index in csv file

here is my vf page:

<apex:page controller="importDataFromCSVController" >
<apex:form >
<apex:pagemessages />
<apex:pageBlock >
<apex:pageBlockSection columns="7" >
<apex:inputFile value="{!csvFileBody}"  filename="{!csvAsString}"/>
<apex:commandButton value="Import Timesheet" action="{!importCSVFile}"/>
</apex:pageBlockSection>
</apex:pageBlock>
<apex:pageBlock >
<apex:pageblocktable value="{!applist}" var="app">
<apex:column value="{!app.id__c}" />
<apex:column value="{!app.Total_Number_of_Hours_worked__c}" />
<apex:column value="{!app.Total_Cleint_Holidays__c}" />
<apex:column value="{!app.Total_Number_of_Days_worked__c}" />
</apex:pageblocktable>
</apex:pageBlock>
</apex:form>
</apex:page>


here is my controller :

public void importCSVFile(){
try{
csvAsString = csvFileBody.toString();
csvFileLines = csvAsString.split('\n');

for(Integer i=1;i<csvFileLines.size();i++){
appointment__c appObj = new appointment__c () ;
string[] csvRecordData = csvFileLines[i].split(',');
appObj.id__c = csvRecordData[24] ;
appObj.Total_Number_of_Hours_worked__c = Decimal.Valueof(csvRecordData[168]);
appObj.Total_Cleint_Holidays__c = Decimal.Valueof(csvRecordData[172]);
appObj.Total_Number_of_Days_worked__c = Decimal.Valueof(csvRecordData[176]);
}
//insert acclist;
}
catch (Exception e)
{
ApexPages.Message errorMessage = new ApexPages.Message(ApexPages.severity.ERROR,'An error has occured while importin data Please make sure input csv file is correct');
}
}
}


in the following image i want to capture particular data(written in bold) like Avvas - ID =A-006, Total Number of Hours worked = 60, Total Cleint Holidays = 1, Total Number of Days worked
=18

I think you should itereate until you found a not number in the first column.

intIndex = 0;
boolFound = false;
while(intIndex < csvFileLines.size() && !boolFound) {
string[] csvRecordData = csvFileLines[intIndex].split(',');
if(!csvRecordData[0].isNumeric()) {
boolFound = true;
}
}

TotalNumberofHoursworked = csvFileLines[intIndex];
Total Cleint Holidays = csvFileLines[intIndex + 1]


I was having the same challenge until i came up with this implementation that allows you to get the data from any row/column you specify.

Note however that you must have first converted the csv blob file to string and use split to get the rows one by one. If you have no idea how to do that, I'll show you how

global with sharing class DataLoading {
public Blob bfile{get;set;}
public string csvAsString{get;set;}
public string[] csvFileLines{get;set;}

// now inside the constructor do this

csvFileLines = new String[]{}; //create an array of string
}

// next you need a method that you use to call the getValAtIndex method

public  void importCsvFile(){
csvAsString = bfile.toString() ;   //convert the blob into a string file
csvFileLines = csvAsString.split('\n'); //split the string file lines so
//records/rows can be accessible
}

public String getValAtIndex(integer rowIndex, integer colIndex) {
String Value;
for (integer i=0; i < csvFileLines.size(); i++){
if (i == rowIndex){
String[]columns= csvFileLines[rowIndex].split(',',-1);
for(integer j= 0;j<columns.size();j++){
if (j== colIndex){
Value = columns[colIndex];
}
}
}
}
}
}


My variable scoping may be wrong as I put it here, this is because I had to skim unnecessary code. You should know how to fix that by yourself.

Just ensure that:

1. there is a constructor where you initialise the variables defined in the top of the code
2. your two methods are exclusive and both declared as public
3. you specify your index by using regular array index notation [0 1 2 ...] .. so a cell like A12 in excel will correspond to

string value = getValAtIndex(11,0) //because is A is index 0 and 12 is index 11

• There's no need for either of those for loops to be there. They're just wasting CPU time. You should perform bounds checking and then access the array element directly. – David Reed Jan 22 at 18:11
• Welcome to the site olaitan! I'm going to go out on a limb and guess that you're likely reasonably new to development (apologies if not), would it be of benefit if someone were to edit your post according to what @DavidReed has pointed out above? – Matt Lacey Jan 23 at 6:22
• Elaborating on David's comment a bit more... you could turn your for loops into sanity checking for your bounds. Instead of for(i = 0; i < csvFileLines.size(); i++), you could do if(rowIndex < 0 || rowIndex >= csvFileLines.size()) and return/error out if the bounds check fails. I hope you can see the similarity between the two. In a similar manner, you could do the same thing to the columns` list (after you pass the first check and split the target row. That'd turn this from an O(n^2) to an O(1) operation. – Derek F Jan 24 at 20:57
• yes definitely @Mattlacey.. im new to development... and yes im fine with editing my code to the best reasonable standard.. thanks for the help – olaitan adesoji Jan 28 at 10:43
• N.B. this CSV parser assumes there are no embedded line breaks or commas in any cell – cropredy Jan 29 at 4:41