Customising Tables: Introducing Table.MergeRows in ReportMagic 4.2
ReportMagic 4.2 introduces a powerful new macro - [Table.MergeRows:] - that lets you horizontally merge adjacent cells within table rows. Whether you’re consolidating repeating quarter headers, grouping identical status cells, or cleaning up data-heavy reports, this macro gives you fine-grained control over horizontal cell merging with full formatting preservation.
What Does It Do?
[Table.MergeRows:] scans one or more rows in a table and merges adjacent cells that match a given criteria. By default, it merges cells with identical text, but it also supports pattern-based matching using Contains, NotContains, and Regex modes.
The leftmost cell’s style (background colour, font, borders) is always preserved, and you have full control over what content the merged cell should contain.
How It Works
[Table.MergeRows:] operates on the previous table in the document - it doesn’t create a table itself. In practice, that table might already exist in your Word or HTML document, or it might have been generated by any of the many table-producing macros such as [Jira.Table:], [LogicMonitor.DeviceTable:], [Database.Table:], [Web.Table:], and others.
In the examples below, we use [List.Table:] as a quick way to create inline tables for demonstration purposes only.
Quick Start
At its simplest, just place the macro after a table and it will merge all adjacent identical cells in every data row (the header row is skipped by default):
[List.Table: values=Status^Q1^Q2^Q3^Q4;Sales^Good^Good^Good^Poor;Support^OK^OK^OK^OK]
[Table.MergeRows:]
Result:
| Status | Q1 | Q2 | Q3 | Q4 |
|---|---|---|---|---|
| Sales | Good (colspan=3) | Poor | ||
| Support | OK (colspan=4) |
The three “Good” cells merge into one spanning 3 columns, and all four “OK” cells merge into one spanning 4 columns.
Parameters at a Glance
| Parameter | Default | Description |
|---|---|---|
ignoreHeaderRow |
true |
Whether to skip the header (first) row |
rowIndices |
(all rows) | Specific 1-based row indices to process (semicolon-separated) |
rowIndexFrom / rowIndexTo |
(all rows) | A range of rows to process |
startColumnIndex |
1 |
The 1-based leftmost column to consider |
endColumnIndex |
(last) | The 1-based rightmost column to consider |
matchType |
Identical |
How cells are matched: Identical, Contains, NotContains, or Regex |
matchText |
The text or regex pattern to match (required for Contains/NotContains/Regex) | |
mergeValue |
First |
What the merged cell should contain: First, Last, Empty, Joined, or MatchText |
joinDelimiter |
, |
Delimiter when using mergeValue=Joined |
skipMergedCells |
true |
Skip cells that are already part of a merge |
Note:
rowIndicesandrowIndexFrom/rowIndexToare mutually exclusive - use one approach or the other.
Examples
1. Basic Identical Merge
Merge adjacent cells with the same text across all data rows:
[List.Table: values=Name^Mon^Tue^Wed^Thu^Fri;Alice^Office^Office^Office^Remote^Remote;Bob^Remote^Remote^Office^Office^Office;Carol^Office^Office^Office^Office^Office]
[Table.MergeRows:]
Result:
| Name | Mon-Fri |
|---|---|
| Alice | Office (x3) |
| Bob | Remote (x2) |
| Carol | Office (x5) |
2. Merge the Header Row
By default the header row is skipped. Set ignoreHeaderRow=false to include it:
[List.Table: values=2025 Q1^2025 Q2^2025 Q3^2026 Q1^2026 Q2;100^200^300^400^500]
[Table.MergeRows: ignoreHeaderRow=false, matchType=Contains, matchText=2025, mergeValue=MatchText]
The three “2025” headers merge into a single cell displaying “2025” (colspan=3), while the 2026 headers remain separate.
3. Target Specific Rows
Use rowIndices to merge only the header row (row 1):
[List.Table: values=Region^Q1 2025^Q2 2025^Q3 2025^Q1 2026^Q2 2026;North^10^20^30^40^50;South^60^70^80^90^100]
[Table.MergeRows: rowIndices=1, matchType=Contains, matchText=2025, mergeValue=MatchText]
Only row 1 (the header) is processed. The three “2025” columns merge into one cell labelled “2025”, while data rows remain untouched.
4. Merge a Range of Rows
Use rowIndexFrom and rowIndexTo to process a specific range:
[List.Table: values=Name^Mon^Tue^Wed^Thu^Fri;Alice^x^x^x^y^y;Bob^a^a^b^b^b;Carol^z^z^z^z^z;Dave^p^q^r^s^t]
[Table.MergeRows: rowIndexFrom=2, rowIndexTo=4, startColumnIndex=2, endColumnIndex=6]
Only rows 2-4 are processed (Dave’s row is untouched), and only columns 2-6 participate in the merge.
5. Restrict Columns with startColumnIndex
Skip the first column (e.g. a label column) so it’s never merged:
[List.Table: values=Team^Sprint 1^Sprint 2^Sprint 3^Sprint 4;Alpha^Done^Done^Done^In Progress;Beta^Blocked^Blocked^Done^Done]
[Table.MergeRows: startColumnIndex=2]
Column 1 (“Team”) is excluded. Only the sprint columns participate in the merge.
6. Contains Match with MatchText Value
Merge cells whose text contains a keyword, and replace the merged content with the match text:
[List.Table: values=Category^Jan 2025^Feb 2025^Mar 2025^Jan 2026^Feb 2026;Revenue^1000^2000^3000^4000^5000]
[Table.MergeRows: rowIndices=1, matchType=Contains, matchText=2025, mergeValue=MatchText]
The three “2025” header cells merge into one cell displaying just “2025”.
7. NotContains Match
Merge cells that do not contain a specific value - useful for grouping everything except totals or separators:
[List.Table: values=C1^C2^C3^C4^C5;Total^100^200^Total^300]
[Table.MergeRows: rowIndices=2, matchType=NotContains, matchText=Total, mergeValue=Joined, joinDelimiter= + ]
Result: The “Total” cells act as barriers. Cells “100” and “200” merge into “100 + 200”, and “300” stays alone.
8. Regex Match
Use a regular expression to match cells. This example merges cells starting with “Q” followed by a digit:
[List.Table: values=Q1 Sales^Q2 Sales^H1 Sales^Q3 Sales;10^20^30^40]
[Table.MergeRows: rowIndices=1, matchType=Regex, matchText=^Q\d, mergeValue=First]
“Q1 Sales” and “Q2 Sales” merge (keeping “Q1 Sales”). “H1 Sales” breaks the group (doesn’t match). “Q3 Sales” stands alone.
9. Joined Merge Value
Instead of keeping just the first or last value, join all merged cell values with a delimiter:
[List.Table: values=Department^Role 1^Role 2^Role 3^Role 4;Engineering^Dev^Dev^Dev^QA;Operations^Ops^Ops^SRE^SRE]
[Table.MergeRows: mergeValue=Joined, joinDelimiter= / ]
Result:
| Department | Roles |
|---|---|
| Engineering | Dev / Dev / Dev (x3) |
| Operations | Ops / Ops (x2) |
10. Empty Merge Value
Clear the content of merged cells entirely - useful when you want the visual merge without any text:
[List.Table: values=H1^H2^H3;a^a^b;c^c^c]
[Table.MergeRows: mergeValue=Empty]
Adjacent identical cells are merged, but the resulting merged cell is empty.
11. Merging from a Specific Row to the End
Use rowIndexFrom without rowIndexTo to process from a given row to the last row:
[List.Table: values=H1^H2^H3;a^a^b;c^c^c;d^d^e;f^f^f]
[Table.MergeRows: rowIndexFrom=4]
Rows 2-3 are untouched. Only rows 4 and 5 are processed.
12. Preserving Formatting
When cells have styling (background colours, bold text, font sizes), [Table.MergeRows:] preserves the formatting of the leftmost cell in each merge group. This works in both Word and HTML output - your carefully styled tables stay beautiful.
Tips and Best Practices
- Start simple - use
[Table.MergeRows:]with no parameters to merge identical adjacent cells in all data rows. Add parameters as needed. - Header rows - remember
ignoreHeaderRowdefaults totrue. Set it tofalsewhen you need to merge header cells. - Column scope - use
startColumnIndexandendColumnIndexto protect label columns from being merged. - Pre-merged cells - cells that already have a colspan or rowspan are skipped by default (
skipMergedCells=true). Set tofalseif you want an error when this occurs. - Row targeting -
rowIndicesandrowIndexFrom/rowIndexToare mutually exclusive. UserowIndicesfor specific rows and the range parameters for contiguous blocks. - Works everywhere -
[Table.MergeRows:]works in Word (.docx) and HTML output. PowerPoint is not supported.
Conclusion
[Table.MergeRows:] fills a long-requested gap in ReportMagic’s table manipulation toolkit. Combined with existing macros like [Table.MergeCells:] (vertical merging) and [Table.Style:], you now have complete control over both horizontal and vertical cell merging - making it easy to produce clean, professional reports with properly structured headers and consolidated data cells.
Look out for this feature in ReportMagic 4.2, coming soon!
Have questions or feedback? Let us know in the comments below.