+ Start a Discussion
neckrneckr 

Is there a way to break up a data list into multiple columns based on a row limit?

Hi, Does anyone know how to break up a datalist or pageblock table into multiple colums based on a max number of rows set?

 

For example my page code snap shot below returns a list of 89 rows in one column by default, I would like to break it up on my page into 4 colums of 25 rows max.  What is the easiest way to do this?  I also need to do this for a pageblock table, if the solution is different. I posted the snippet for the  pagebloack table below as well.  Please help!!

 

 

 <apex:pageBlockSection title="Work Categories">
                 
                  <apex:dataList value="{!Categories}" var="c" id="table" type="none" >
                      <apex:commandLink value="{!c.Name}" action="{!ViewST}" reRender="pb"  >
                          <apex:param name="param1" value="{!c.Name}" assignTo="{!category}"/>
                      </apex:commandlink>   
                  </apex:dataList>
                  
         </apex:pageBlockSection>

 

 

 

 <apex:pageBlockSection title="Service Tasks for {!category}" id="ST">
                
                               
                      <apex:pageBlockTable value="{!servicetasks}" var="a" id="table">
                          <apex:column headervalue="Select">
                              <apex:inputCheckbox value="{!a.selected}"/>
                          </apex:column>
                              <apex:column headerValue="{!category} Service Tasks" value="{!a.ST.Service_Name__c}" /> 
                       </apex:pageBlockTable> 
                       
                       <apex:commandButton value="Add Service Tasks" action="{!processSelected}" rerender="table"/>
                     
 </apex:pageBlockSection>

 

 

 

Best Answer chosen by Admin (Salesforce Developers) 
bob_buzzardbob_buzzard

I misunderstood your post I think.  You want to display all 89 records on a single page, but with a maximum of 25 rows.  This is a bit more tricky I think.  I think you'll need to use wrapper classes where a class maps to a single row of the table and can have any number of columns.  

 

I wrote a blog post some time ago in a similar vein - its not exactly what you are doing, but should be straightforward to adapt:

 

http://bobbuzzard.blogspot.com/2010/09/rotating-visualforce-table.html

 

Off the top of my head you'll need to:

 

 

  • Pull back your list of objects
  • Create (list.size()/25)+1 RowWrapper classes
  • Iterate the list keeping a count
  • Add each value from the list to the RowWrapper element at (count mod 25).
This would mean you are working your way down the rows putting an entry in column 1 until you hit 25, then you start again putting an entry in column 2 etc.

 

All Answers

bob_buzzardbob_buzzard

If you are using a standard set controller you can get pagination for free.

 

If you aren't, its not that tricky to build yourself.  It boils down to the following:

 

 

  • Define the max rows per page in your controller (e.g. 25)
  • Define a page number property and set to zero
  • Retrieve all data
  • Create a method that retrieves the current page's data (i.e. the records from pageNo*25 to pageNo*25 + 24)
  • Back the datatable/pageblocktable/whatever with that method
  • Add prev/next methods that increment/decrement the page count - these need to ensure that you don't go negative or past the last page.
So essentially you are displaying a sliding window on the data.
As I mentioned earlier though, standard set controllers will give you most of this for free, so if you can use that it will cause you the least pain.

 

neckrneckr

Bob,  thanks for your reply.

 

I need all my columns to display on one page, side by side so I dont think pagintaion is gonna work for me in this case.

 

My thoughts now are to have 4 seperate lists each as a column in a datatable.  I been searching around for a way to break up my query list into chuncks of 25 for example.

 

The qurery syntax allows me to set a upper limit of records using LIMIT, but not a start number, is there a walk around to query a lists that return 1-25, 26-50, 51-75 and 76-100.

 

If this is not possible can you give me an example of the method you described that would break up the data of the full list? (Create a method that retrieves the current page's data (i.e. the records from pageNo*25 to pageNo*25 + 24))

bob_buzzardbob_buzzard

I misunderstood your post I think.  You want to display all 89 records on a single page, but with a maximum of 25 rows.  This is a bit more tricky I think.  I think you'll need to use wrapper classes where a class maps to a single row of the table and can have any number of columns.  

 

I wrote a blog post some time ago in a similar vein - its not exactly what you are doing, but should be straightforward to adapt:

 

http://bobbuzzard.blogspot.com/2010/09/rotating-visualforce-table.html

 

Off the top of my head you'll need to:

 

 

  • Pull back your list of objects
  • Create (list.size()/25)+1 RowWrapper classes
  • Iterate the list keeping a count
  • Add each value from the list to the RowWrapper element at (count mod 25).
This would mean you are working your way down the rows putting an entry in column 1 until you hit 25, then you start again putting an entry in column 2 etc.

 

This was selected as the best answer
neckrneckr

Bob - Your code worked very nicely with the help of your instructed modifications.  I decided to split my data into 5 colums and ended up with this.   Your assitance once again is very much appreciated!!!!!

 

 

  public List<RowWrapper> getRowWrappers()
    {
        if (null==rows)
        {
            rows=new List<RowWrapper>();
            
            // create rows
            for (Integer idx=0; idx<(getCategories().size()/5)+1; idx++)
            {
                rows.add(new RowWrapper());
            }
            
            // iterate the accounts and populate the rows for columns
            Integer count = 0;
            for (Integer idx=0; idx<(getCategories().size()/5)+1; idx++)
            {                           
                            rows[idx].addValue(getCategories()[count].Name);
                       count++;   
               }
          
          for (Integer idx=0; idx<(getCategories().size()/5)+1; idx++)
            {                           
                            rows[idx].addValue(getCategories()[count].Name);
                       count++;   
               }
        
         for (Integer idx=0; idx<(getCategories().size()/5)+1; idx++)
            {                           
                            rows[idx].addValue(getCategories()[count].Name);
                       count++;   
               }
         
         for (Integer idx=0; idx<(getCategories().size()/5)+1; idx++)
            {                           
                            rows[idx].addValue(getCategories()[count].Name);
                       count++;   
               }
         
            for (Integer idx=0; idx<math.mod(getCategories().size(),(getCategories().size()/5)+1); idx++)
            {                           
                            rows[idx].addValue(getCategories()[count].Name);
                       count++;   
               }
                  
        }
        
        return rows;
    }

 

 

 

neckrneckr

 Bob - I used your RowWrapper code for another purpose and it outputs a row of data into a column as desired.  However some of the rows display NULL, which makes sense because the values are empty in my database.  I only want to show the rows that are not equal to NULL.  I have tried many permutations of syntax in the rendered attribute and can't seem to get anywhere.  I think I may be missing something regarding if the NULL value is a string or a boolean value or the proper syntax to handle NULL values.  Hopefully my question is clear enough for some direction.  Here is a snippet of my page code and some of the syntax I tried that does not return the desired results.

 

<apex:repeat value="{!rowWrappers}" var="row">
       <tr>
         <apex:repeat value="{!row.values}" var="value" > //Returns all rows including rows that display NULL - When rendered //attribute is added to this component with syntax below it returns no rows
           <td>
             {!value}
           </td>
         </apex:repeat>

 

 

rendered ="{!row.values} <> 'NULL' "  // Returns no rows

 

rendered ="{!row.values} <> NULL"  // Returns no rows

 

rendered ="{!row.values} != NULL"  // Returns no rows

 

rendered ="{!row.values} != 'NULL' "  // Returns no rows

bob_buzzardbob_buzzard

I'm assuming here that you've got particular table cell entries displaying null that you want to remove from display, rather than entire rows or columns.

 

It will almost certainly be easier to not add things to the list.  Otherwise you'd be trying to avoid a table cell being drawn if the value is NULL, but the problem there is that would throw out the number of columns for that particular row, which would shift things around in an unpleasant way on the screen.  

 

I think the code that populates the wrapper columns can be dwindled down to:

 

 

   // iterate the accounts and populate the rows for columns
   Integer count = 0;
   for (Account acc : getCategories())
   {
      // check for null name
      String nameStr=acc.Name;
      if (null!=nameStr)
      {
         // name isn't null - add to the appropriate row
         rows[count/5].addValue(nameStr);

         // only increment the counter if we added a name, to avoid jumps
         count++;
      }
   }

 

 

Thus only non-null elements are added to the rows.  The row index is determined by dividing count by 5, thus:

 

0, 1, 2, 3, 4 go into row index 0

5, 6, 7, 8, 9 go into row index 1

 

etc.

 

The only thing that you might find is that you end up with some empty rows at the bottom, but that should be easy enough to detect.

neckrneckr

Got the data in the proper cells.  I am having formatting issues when I tried using the page <table> code within a pageblocksection.  I changed the columns attribute value to 5 considering I have 5 columns but it is not rendering properly.  I managed to get the code working in a pageblock, however I would like the collapsable option.  Is there a way to get this code working in a pageblocksection?

 

 

 
  <apex:form >
       
         <apex:pageBlock title="Work Categories" rendered="true">
 
              <table class="list" border="0" cellpadding="0" cellspacing="0">
                <apex:repeat value="{!rowWrappers}" var="row">
                   <tr>
                      <apex:repeat value="{!row.values}" var="c">
                          <td>
                            <apex:commandLink value="{!c}" action="{!ViewST}" reRender="ST,RC"  >
                                <apex:param name="cparam" value="{!c}" assignTo="{!category}" />
                             </apex:commandlink>
                          </td>
                      </apex:repeat>
                  </tr>
              </apex:repeat>
            </table>
   
   </apex:PageBlock>

 

 

bob_buzzardbob_buzzard

I'm guessing that when you are in a pageblocksection that you see the table squashed into one side or the other, as a pageblocksection is geared around label and value type of display.  Have you tried enclosing it in a pageblocksectionitem?  If you have one of these with a single child element it will span both cells of the column.