My solution:

Template:

{{#each data}} {{#xlsxAdd "xl/worksheets/sheet1.xml" "worksheet.sheetData[0].row"}} {{rowCounter}} {{#if this.rowShouldTobeMarged}} {{rowsForMerging 'mergingType1'}} {{/if}} <row>...</row> {{/xlsxAdd}} {{/each}} {{#xlsxReplace "xl/worksheets/sheet1.xml" "worksheet.mergeCells"}} <mergeCells> {{#mergeRows}} <mergeCell ref="{{this}}"/> {{/mergeRows}} </mergeCells> {{/xlsxReplace}} {{{xlsxPrint}}}

Helpers:

function rowCounter(options) { if (!options.data.root.rowCounter) { options.data.root.rowCounter = 0; } options.data.root.rowCounter = options.data.root.rowCounter + 1; } function rowsForMerging(type, options) { if (!options.data.root.rowsForMerging) { options.data.root.rowsForMerging = []; } options.data.root.rowsForMerging = [ ...options.data.root.rowsForMerging, { type, row: options.data.root.rowCounter } ]; } function mergeRows(options){ returnData = ""; const rows = options.data.root.rowsForMerge; for (let i = 0; i < rows.length; i++) { const { row, type } = rows[i]; if (type === 'mergingType1') { returnData = returnData + options.fn(`B${row}:K${row}`); } // .... } return returnData; }