Currently we are using a custom list view Visual Force page button for mass actions to export data to excel sheet in salesforce classic.

Objects and relations:

  • Static List (Custom object with Master relationship to Static List Member )
  • Static List Member (Custom junction object to static list and static list member )
  • Contact (Standard object with Master relationship to Static List Member )

Expected behavior for the visual force page:

  • On the static List, list view select the static list and click export

  • The export in the excel file should return all the static list members for each static list.

    -Known limitations: The number of items in a collection that can be handled by iteration components is 10,000 in read only mode.

Current Behavior: Export for each list is maxed out at 1999 rows.

I'm trying to figure out if the current behavior is a salesforce bug or Am I missing something? Any help appreciated, below is the code snippet.

<apex:page standardController="Static_List__c" recordSetVar="staticLists" contentType="application/vnd.ms-excel#Static_List_Export{!NOW()}.xls" readOnly="true">
<!-- Vf page to generate the static member list records into a single excel sheet using standard controller functionality-->
<!-- Using content type along with date time stamp to create unique name every time the excel report is created-->
<!-- Using recordsetvar to fetch all the records from the list view-->
        #contacttable {
        font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
        border-collapse: collapse;
        width: 100%;
        #contacttable td, #contacttable th {
        border: 1px solid #ddd;
        padding: 8px;
        #contacttable tr:nth-child(even){background-color: #f2f2f2;}
        #contacttable tr:hover {background-color: #ddd;}
        #contacttable th {
        padding-top: 12px;
        padding-bottom: 12px;
        text-align: left;
        background-color: #4CAF50;
        color: white;
<table id="contacttable">
        <th>Static List: List Name</th>
        <th>Company Name</th>
        <th>Email opt-out</th>
        <th>Street Address</th>
    <!-- Iterating over the selected records on the list view -->
    <apex:repeat value="{!selected}" var="sL">
        <!-- Iterating over the child records using relationship-->
        <apex:repeat value="{!sL.Static_List_Members__r}" var="sLM">
            <tr >
                <td>   {!sLM.Static_List__r.Name}    </td>
                <td>   {!sLM.Contact_Name__r.Salutation}</td>
                <td>   {!sLM.Contact_Name__r.Name}</td>
                <td>   {!sLM.Company_Name__c}        </td>
                <td>   {!sLM.Contact_Status__c}      </td>
                <td>   {!sLM.Email_Opt_Out__c}       </td>
                <td>   {!sLM.Email__c}               </td>
                <td>   {!sLM.Contact_Name__r.Phone}</td>
                <td>   {!sLM.Contact_Name__r.MailingStreet}</td>
                <td>   {!sLM.Contact_Name__r.MailingCity}</td>
                <td>   {!sLM.Contact_Name__r.MailingState}</td>
                <td>   {!sLM.Contact_Name__r.MailingCountry}</td>
                <td>   {!sLM.Contact_Name__r.MailingPostalCode}</td>


Child records are limited to about 2,000 unless you iterate over all of them in your Apex Code first. This happens because the sub-query needs its own QueryLocator. You'd probably have better luck using a wrapper class, like this:

public class StaticList {
  public Static_List_Member__c members { get; set; }
  public StaticList() {
    members = new Static_List_Member__c[0];

Which you'd then populate using the rarely used for query list method:

StaticList[] sL = new StaticList[0];

for(Static_List__c record: [SELECT (SELECT ... FROM Static_List_Members__r) FROM Static_List__c]) {
  StaticList newList = new StaticList();
  for(Static_List_Member__c[] members: record.Static_List_Members__r) {

This should give you the approximately correct behavior; you just need to add in the missing pieces.

Of course, keep in mind that, as you know, you'll still need to keep the list smaller than 10,000 items. The iterator will not stop at 10,000, you'll just get a generic Visualforce exception instead.

  • Thanks for your help. One thing I'm aware is I can get this done with apex, but i was clueless of current behavior as i didn't find any appropriate documentation. The other one was when i select multiple lists i was able to get a file with more than 15000 rows which is contradictory to 10000 rows limit. – codeyinthecloud Jun 7 '18 at 16:30
  • 1
    @RajeshVarmaMudunuri It's 10,000 per iteration; conceptually, you could have 10,000 parents with 10,000 children each for a grand total of 10,000,000 (except, obviously, you'd reach the 1,000,000 row limit). – sfdcfox Jun 7 '18 at 16:35
  • Aah! Gotcha, now it makes sense. One final thing, Can you point me to the documentation about the 2000 child record limit. – codeyinthecloud Jun 7 '18 at 16:38
  • @RajeshVarmaMudunuri It's not necessarily 2,000, actually, it's an automatically adjusted limit based on the number of rows returned and how big each row is. I talk about that in this answer. The moral of the story is that you need to actually go through the query locator and pull out all the children. – sfdcfox Jun 7 '18 at 16:42
  • Thanks for jumping in. I could only hope for better documentation from salesforce. It's like connecting the dots together. – codeyinthecloud Jun 7 '18 at 16:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.