[SalesForce] Removing rows separately from the Visualforce pageBlockTable list

I created a visualforce page (with controller) that allows adding multiple records to a custom object (master object is account). I can add new rows and save the new records, I'm also pulling information from the master records.
What I'm missing is the ability to remove each row separately – a custom button or a link. Can someone assist me with this?

Visualforce:

<apex:page controller="multiAddForecast" sidebar="false" id="CExPage" showheader="true" tabstyle="Bill__c">
<script language="JavaScript" type="text/javascript">
function CloseAndRefresh(){
window.parent.location.href="/{!$CurrentPage.parameters.id}"; self.close(); }
</script>
<apex:form >
<apex:pageBlock title="Forecast" >

<apex:pageBlockButtons >
<apex:pagemessages rendered="true" id="msg2" />
<apex:commandButton value="Add New" action="{!add}" rerender="rows" status="outStatus"/>
<apex:commandButton action="{!save}" value="Save and Close" oncomplete="javascript:CloseAndRefresh()" rerender="rows,msg2" status="outStatus"/>
</apex:pageBlockButtons>

<apex:pageBlockTable width="80%" align="center" value="{!cexs}" var="c" id="rows" >

<apex:column width="30%" headerValue="Forecasted Amount"><apex:inputField value="{!c.Forecasted_Number__c}" required="true"/></apex:column>
<apex:column width="30%" headerValue="Current Price"><apex:inputField value="{!c.Price_Per_Month__c}" required="true" /></apex:column>
<apex:column headervalue="Month"><apex:outputField value="{!c.Month__c}" /></apex:column>

</apex:pageBlockTable>       
</apex:pageblock>    
</apex:form>
</apex:page>

Controller:

public class multiAddForecast {

public List <Bill__c> CExList {get; set;}
public Id cID = ApexPages.currentPage().getParameters().get('Id'); //grab the Account ID
public Id getID {get; set;}

public multiAddForecast(){
    CExList = new List<Bill__c>();
    Date lastDate = getStartDateByAccount();
    Decimal Lastcurrency = getCurrentPriceAccount();
    addInternal(1,lastDate, Lastcurrency);
    addInternal(2,lastDate, Lastcurrency);
    addInternal(3,lastDate, Lastcurrency);

}

public List <Bill__c> getCExs() {
 return CExList;}

public void setAccounts(List <Bill__c> cexs) {
   CExList = cexs;}

public PageReference save() {//upsert records on save
upsert CExList;
ApexPages.Message myMsg = new ApexPages.message(ApexPages.Severity.Info, 'Records Saved Successfully'); //show confirmation message on save
ApexPages.addMessage(myMsg);
return null;}


public PageReference add() {

    Date lastDate = getStartDateByAccount();
    Decimal Lastcurrency = getCurrentPriceAccount();
    addInternal(CExList.size()+1,lastDate, Lastcurrency);

    return null;
}


private void addInternal(integer numMonth,Date startMonth, Decimal curr){
    Date lineDate = startMonth.addMonths(numMonth);
    Monthly_Cloud_Bill__c newObj = New Bill__c(Account__c = cID);
    newObj.Billing_Month__c = lineDate;
    newObj.Price_Per_Month__c = curr;
    CExList.add(newObj);
}    

private Date getStartDateByAccount(){
    Account account = [Select Last_Billed__c, Current_Price__c From Account Where Id = :cID];
    return account.Last_Billed__c;

}

private Decimal getCurrentPriceAccount(){
    Account account2 = [Select Current_Price__c From Account Where Id = :cID];
    return account2.Current_Price__c;

}

}

UPDATED Code:
thanks @mast0r, i published below the updated code. one problem: when trying to remove a row, i'm getting the following error: "List index out of bounds: 6
Error is in expression '{!removeNewObject}' in component in page multiaddforecast". Can you assist solving this??

Class:

public class multiAddForecast {

public List <Monthly_Cloud_Bill__c> CExList {get; set;}
public Id cID = ApexPages.currentPage().getParameters().get('Id'); //grab the Account ID
public Id getID {get; set;}
public Integer numberOfRowToRemove { get; set; }




public multiAddForecast(){
    CExList = new List<Monthly_Cloud_Bill__c>();
    Date lastDate = getStartDateByAccount();
    Decimal Lastcurrency = getCurrentPriceAccount();
    addInternal(1,lastDate, Lastcurrency);
    addInternal(2,lastDate, Lastcurrency);
    addInternal(3,lastDate, Lastcurrency);


}

public List <Monthly_Cloud_Bill__c> getCExs() {
 return CExList;}

public void setAccounts(List <Monthly_Cloud_Bill__c> cexs) {
   CExList = cexs;}

public PageReference save() {//upsert records on save
upsert CExList;
ApexPages.Message myMsg = new ApexPages.message(ApexPages.Severity.Info, 'Records Saved Successfully'); //show confirmation message on save
ApexPages.addMessage(myMsg);
return null;}


public PageReference add() {

    Date lastDate = getStartDateByAccount();
    Decimal Lastcurrency = getCurrentPriceAccount();
    addInternal(CExList.size()+1,lastDate, Lastcurrency);

    return null;
}



private void addInternal(integer numMonth,Date startMonth, Decimal curr){
    Date lineDate = startMonth.addMonths(numMonth);
    Monthly_Cloud_Bill__c newObj = New Monthly_Cloud_Bill__c(Account__c = cID);
    newObj.Billing_Month__c = lineDate;
    newObj.Effective_Price_Per_VM_Per_Month__c = curr;
    CExList.add(newObj);
}



private Date getStartDateByAccount(){
    Account account = [Select Last_Cloud_Billed__c, Current_Per_VM_Price__c From Account Where Id = :cID];
    return account.Last_Cloud_Billed__c;

}

private Decimal getCurrentPriceAccount(){
    Account account2 = [Select Current_Per_VM_Price__c From Account Where Id = :cID];
    return account2.Current_Per_VM_Price__c;

}

  // The method to remove an item from the list
    public PageReference removeNewObject(){

        CExList.remove(numberOfRowToRemove);  

        return null;
    }

}

Visualforce:

<apex:page controller="multiAddForecast" sidebar="false" id="CExPage" showheader="true" tabstyle="Monthly_Cloud_Bill__c">
<script language="JavaScript" type="text/javascript">
function CloseAndRefresh(){
window.parent.location.href="/{!$CurrentPage.parameters.id}"; self.close(); }
</script>
<apex:form >
<apex:pageBlock title="Forecast" >

<apex:variable value="{!0}" var="rowNumber" />

<apex:pageBlockButtons >
<apex:pagemessages rendered="true" id="msg2" />
<apex:commandButton value="Add New" action="{!add}" rerender="rows" status="outStatus"/>
<apex:commandButton action="{!save}" value="Save and Close" oncomplete="javascript:CloseAndRefresh()" rerender="rows,msg2" status="outStatus"/>
</apex:pageBlockButtons>

<!-- Here we will use an extra variable to define a row number -->
<apex:outputPanel id="panelWithVar">
    <apex:variable value="{!0}" var="rowNumber" />
</apex:outputPanel>

<!-- A list with new items -->
<apex:pageBlockTable width="80%" align="center" value="{!cexs}" var="c" id="rows" >

 <apex:column width="5%">
        <apex:commandButton action="{!removeNewObject}" value=" X " reRender="rows,panelWithVar">
            <apex:param name="p1" value="{!rowNumber}" assignTo="{!numberOfRowToRemove}"/>
        </apex:commandButton>
    </apex:column> 

<apex:column width="30%" headerValue="Forecasted Amount">
    <apex:inputField value="{!c.Forecasted_Number_of_VMs__c}" required="false"/>
</apex:column>
<apex:column width="30%" headerValue="Current Per VM Price">
    <apex:inputField value="{!c.Effective_Price_Per_VM_Per_Month__c}" required="true"/>
</apex:column>
<apex:column headervalue="Billing Month">
    <apex:outputField value="{!c.Billing_Month__c}" />
    <apex:variable var="rowNumber" value="{!rowNumber + 1}" /> 
</apex:column>

</apex:pageBlockTable>

</apex:pageblock>

</apex:form>
</apex:page>

Best Answer

I have a simple example for you, where you can add entries to the list and show this list on the visualforce page and separately remove these entries. This looks like this:

enter image description here

The idea is to use an extra variable to define a row number to remove. Try to reproduce my example and use the logic in your code:

Class:

public with sharing class test1 {

    public List<OpportunityContactRole> objectsToInsert { get; set; } 
    public Integer numberOfRowToRemove { get; set; }
    public Opportunity opp { get; set; }

    public test1()
    {
        objectsToInsert = new List<OpportunityContactRole>();
        opp = [ Select Id From Opportunity Limit 1 ];
    }

    // The method to add a new item to the list
    public PageReference addNewObject(){

        OpportunityContactRole newObject = new OpportunityContactRole(OpportunityId = opp.id);
        objectsToInsert.add(newObject);

        return null;
    }

    // The method to remove an item from the list
    public PageReference removeNewObject(){

        objectsToInsert.remove(numberOfRowToRemove);  

        return null;
    }
}

Page:

<apex:page controller="test1">
<apex:form>

<apex:pageBlock>
<apex:variable value="{!0}" var="rowNumber" />

<!-- A main button to add a new item -->
<apex:commandButton value="Add" action="{!addNewObject}" reRender="newItems,panelWithVar" immediate="true"/>

<!-- Here we will use an extra variable to define a row number -->
<apex:outputPanel id="panelWithVar">
    <apex:variable value="{!0}" var="rowNumber" />
</apex:outputPanel>

<!-- A list with new items -->
<apex:pageBlockTable value="{!objectsToInsert}" var="item" id="newItems">
    <!-- A button to remove individual entry. 
         We must to pass the line number to define a list entry number to remove -->
    <apex:column width="5%">
        <apex:commandButton action="{!removeNewObject}" value=" X " reRender="newItems,panelWithVar">
            <apex:param name="p1" value="{!rowNumber}" assignTo="{!numberOfRowToRemove}"/>
        </apex:commandButton>
    </apex:column>

    <!-- Moreover here we incrementing the row number variable -->
    <apex:column headerValue="{!$ObjectType.OpportunityContactRole.fields.Role.label}">
        <apex:inputField value="{!item.Role}"/>
        <apex:variable var="rowNumber" value="{!rowNumber + 1}" />
    </apex:column>

</apex:pageBlockTable>

</apex:pageBlock>

</apex:form>
</apex:page>