---
title: PDF Butler – Complex Column Repeater (Repeat Columns and Rows)
description: "Repeating columns and rows in a table in your Word document is possible. It will require programming skills (APEX) but if you follow this tutorial and check your data with [Butler Inspector](https://pdfbutler.com/academy/pdf-butler-academy/pdf-butler-tips-tricks/pdf-butler-data-inspector-butler-inspector/) you will be alright! *Thing to note:* If…"
url: "https://pdfbutler.com/academy/pdf-butler-academy/pdf-butler-by-configtype/pdf-butler-complex-column-repeater-repeat-columns-and-rows/"
updated: "2025-05-05"
category: PDF BUTLER BY CONFIGTYPE
---

# PDF Butler – Complex Column Repeater (Repeat Columns and Rows)

Repeating columns and rows in a table in your Word document is possible. It will require programming skills (APEX) but if you follow this tutorial and check your data with [Butler Inspector](https://pdfbutler.com/academy/pdf-butler-academy/pdf-butler-tips-tricks/pdf-butler-data-inspector-butler-inspector/) you will be alright!

*Thing to note:* If you need only columns to repeat, that can be done via the Simple Column Repeater and will require no APEX

[PDF Butler Complex Column Repeater Repeat Columns and Rows](https://www.youtube.com/embed/icf_M3E4Xqg?si=DLVqU3buo4oRcKYB)

#### Example 1:

Let's say you want to display the Lead Source against all your Lead records in Salesforce. Each column will represent a Lead Source picklist value, and each row will include the Lead Name with a 'Yes' marked under the corresponding Lead Source it belongs to as shown below in the first screenshot. From the example, it's evident that 'Lead Source' acts as a repeating column , while 'Lead Name' functions as a repeating row. So this example is the combination of both. This is possible with PDF Butler Complex Column repeater.

![Complex Column Repeater LeadSource Example pic1](https://pdfbutler.com/wp-content/uploads/2024/06/Complex-Column-Repeater-LeadSource-Example-pic1-e1745848178911.png)![Complex Column Repeater LeadSource Example pic2](https://pdfbutler.com/wp-content/uploads/2024/06/Complex-Column-Repeater-LeadSource-Example-pic2-e1745848344781.png)

The second screenshot is the DocConfig Document with merge fields. You can download it [here](https://pdfbutler.com/wp-content/uploads/2024/06/Column-repeater-sample-doc1.docx).

Let's try to understand how to map our merge fields with the correct Data Sources and Data Source field. Before that create below Data Sources, DocConfig and also Actionable record for the DocConfig as shown below.

##### SOQL DataSource

We need to have SOQL DataSource which fetches the column data from the Lead as shown below.

![Complex Column Repeater LeadSource Example DS1](https://pdfbutler.com/wp-content/uploads/2024/06/Complex-Column-Repeater-LeadSource-Example-DS1.png)

We need to have one more DataSource which fetches the row data from the Lead as shown below.

![Complex Column Repeater LeadSource Example Datasource DS3](https://pdfbutler.com/wp-content/uploads/2024/06/Complex-Column-Repeater-LeadSource-Example-Datasource-DS3.png)

##### KEYVALUE Data Source

Below is the KEYVALUE Data Source for row data. More information on KEYVALUE Data Source is found [here](https://pdfbutler.com/academy/pdf-butler-academy/pdf-butler-by-datasource/keyvalue/)
 ![Complex Column Repeater LeadSource Example DS2](https://pdfbutler.com/wp-content/uploads/2024/06/Complex-Column-Repeater-LeadSource-Example-DS2.png)

##### Main Word Document Doc Config

![Complex Column Repeater LeadSource Example DocConfig](https://pdfbutler.com/wp-content/uploads/2024/06/Complex-Column-Repeater-LeadSource-Example-DocConfig.png)

Create below Actionable record for above Doc Config.

![Complex Column Repeater LeadSource Example Complex column repeater Actionable record](https://pdfbutler.com/wp-content/uploads/2024/06/Complex-Column-Repeater-LeadSource-Example-Complex-column-repeater-Actionable-record.png)

##### Apex Class for Actionable Record

Below is the Apex class required for Actionable record, which is referred in place of 'Class' field as shown above. This should run with Data Sources. So it implements cadmus_core.AbstractBeforeWithDataSourcesActionable. More information is found [here](https://eu1.pdfbutler.com/files/api/cadmuscore/AbstractBeforeWithDataSourcesActionable.html).

This apex class sets the Data for each row against each column using the KEYVALUE Data Source created above.

```
global class MyActionable_LeadSourceColumnRepeater implements cadmus_core.AbstractBeforeWithDataSourcesActionable {

    global void execute(cadmus_core__Actionable__c actionable, Id docConfig, Id objectId, Map<String, Object> inputMap, Map<String, Object> dsMap, cadmus_core.ConvertController.ConvertDataModel cdm) 
    {
    
        //get the DataSource from PDF Butler
        Object leadSourcesObj =  dsMap.get('00D2p000000QL9s_a022p00000YNpp5'); //SOQL Lead DataSource id for column data like LeadSource and count in this example
        //get the data from the DataSource
        List<Map<String,Object>> leadSources = ((cadmus_core.ListWrapper)(leadSourcesObj)).data;
        System.debug('leadSources: ' + leadSources);
        
        //prepare the suffix for the columns in the rows
        Map<String,String> suffix = new Map<String,String>();
        Integer counter = 0;
        for(Map<String,Object> leadSource : leadSources) {
            if(counter != 0) {
                suffix.put((String)leadSource.get('LeadSource'), '_' + counter);
            } else {
                suffix.put((String)leadSource.get('LeadSource'), '');
            }           
            counter++;
        }
        
        Object rows_object = dsMap.get('00D2p000000QL9s_a022p00000PAp87');//data source for row data like Name,LeadSource in this example
        List<Map<String,Object>> rowsData = ((cadmus_core.ListWrapper)(rows_object)).data;
        system.debug('rowsData'+rowsData);
        
        List<Map<String, String>> leadList = new List<Map<String, String>>();
        for(Map<String,Object> rw : rowsData) {
            Map<String, String> rowItem = new Map<String, String>();  
            //Create the columns empty, we will overwrite the column in a few lines from now
            for(String val : suffix.values()) {
               rowItem.put('Item' + val, '');
            }
            
            //Put the real data
            rowItem.put('Name', String.valueOf(rw.get('Name')));
            rowItem.put('Item'+ suffix.get(String.valueOf(rw.get('LeadSource'))), 'Yes');
            //If you have more fields to handle, add them here.          
            leadList.add(rowItem);
        }            
        cadmus_core.ListWrapper dsLeads = new cadmus_core.ListWrapper();
        dsLeads.data = leadList;
        
        //put back the data into the list of data to sent to PDF Butler
        dsMap.put('00D2p000000QL9s_a022p00000YNppA',dsLeads); //Id of Key Value DataSource Created for Table row
    }
}
```

Open Doc Config PDF Builder and make sure to add all the 3 data sources in to the DocConfig.

When adding Column Data Source(SOQL), add 'ct' (ct is the name which you have given for count() in your column data source soql query) field manually as shown below.

![Complex Column Repeater LeadSource Example DocConfig PDF Builder DS1](https://pdfbutler.com/wp-content/uploads/2024/06/Complex-Column-Repeater-LeadSource-Example-DocConfig-PDF-Builder-DS1.png)

When adding KEYALUE Data Source, add Name(api name of field which will hold lead name) and Item(you can give any name instead of 'Item' , but make sure to give same name in the actionable apex class mentioned above) fields added manually as shown in below screenshot. As this is the KEYVALUE data source, data will be set to this data source in the actionable apex class using these field names

![Complex Column Repeater LeadSource Example DocConfig PDF Builder DS2](https://pdfbutler.com/wp-content/uploads/2024/06/Complex-Column-Repeater-LeadSource-Example-DocConfig-PDF-Builder-DS2.png)

For every row, depending on the number of columns, ROW_COL_VALUE field should replicate.

![Complex Column Repeater LeadSource Example pic2](https://pdfbutler.com/wp-content/uploads/2024/06/Complex-Column-Repeater-LeadSource-Example-pic2-e1745848344781.png)

PDF Butler Complex column repeater is going to create extra columns according to the column size as shown below. In the Data Source, first column will look for 'Item' and second column will look for 'Item_1' and so on. So 'Item' field which we should map to the ROW_COL_VALUE will have the counter appended to it from actionable apex class based on the number of columns.
 ![Complex Column Repeater LeadSource Example Complex column repeater Explaination pic](https://pdfbutler.com/wp-content/uploads/2024/06/Complex-Column-Repeater-LeadSource-Example-Complex-column-repeater-Explaination-pic.png)

##### Configtypes

Create Complex Column Repeater Configtype that should be mapped to [[!COL_ITEM!]] merge field with SOQL Data Source which has column fields in the query

![Complex Column Repeater LeadSource Example Complex column repeater config type](https://pdfbutler.com/wp-content/uploads/2024/06/Complex-Column-Repeater-LeadSource-Example-Complex-column-repeater-config-type.png)

Column repeater will repeat LeadSource and ct(count) Data Source fields. So, create

1. Child SINGLE Config type for LeadSource field that should map to [[!COL_ITEM!]] merge field
2. Child SINGLE Config type for ct field that should map to [[!COUNT!]] merge field

![Complex Column Repeater LeadSource Example Complex column repeater config type child configtypes](https://pdfbutler.com/wp-content/uploads/2024/06/Complex-Column-Repeater-LeadSource-Example-Complex-column-repeater-config-type-child-configtypes.png)

Create TABLE_ROW Config type for the merge field [[!ROW_ITEM!]]. Row repeater will repeat Name and Item Data Source fields of Row repeater KEYVALUE Data Source. So, create

1. Child SINGLE Config type for 'Name' field that should map to [[!ROW_ITEM!]] merge field
2. Child SINGLE_FOR_TABLE_COLUMN_REPEATER Config type for 'Item' field that should map to [[!ROW_COL_VALUE!]] merge field

![Complex Column Repeater LeadSource Example Table row config type and its child configtypes](https://pdfbutler.com/wp-content/uploads/2024/06/Complex-Column-Repeater-LeadSource-Example-Table-row-config-type-and-its-child-configtypes.png)
 Open any Lead record and edit the page to add PDF Butler Component and Doc Config Id to retrieve. Then Save. Generate the PDF.

#### **Use a JSON as input for Complex Column Repeater:**

Find a demo below.

*Thing to note:* I would propose to use chatGPT to create a JSON parser that parses you data instead of writing it yourself!

[BEFORE Actionable transforms JSON Data into DataSources](https://www.youtube.com/embed/0nE8yijtisk?si=L_WTc3ruuR9H6jK3)
