ropenxlsx

openxlsx - Merge 2 cells on several rows in one call?


Is it currently possible to merge, say 2 cells (same row, consecutive columns), on several rows in one (or at least less than the total number of rows considered) call to mergeCells?

[EDIT]: Reproducible example:

library(openxlsx)

OutputFolder <- file.path(".", "Output")
if(!dir.exists(OutputFolder))   dir.create(OutputFolder)

OutputFile <- file.path(OutputFolder, "Reprex_Openxlsx_mergeCells.xlsx")

Workbook4Export <- createWorkbook()

addWorksheet(wb = Workbook4Export, sheetName = "Tab_1", zoom = 80, gridLines = FALSE)

for(i in 1:100000)
{
  mergeCells(wb = Workbook4Export, sheet = "Tab_1", cols = 1 + 0:1, rows = i)
}

Is there an alternative to this very long loop in terms of number of calls to mergeCells? For instance with the natural GUI of Excel, one can copy the whole format of a row of 2 columns (here 2 merged columns on the first row) and then paste on the other 99 000 subsequent rows with just a click or two to have each and every of these rows with the 2 columns merged.

This is what I am ultimately looking for within openxlsx.


Solution

  • The issue here is not actually the looping. mergeCells essentially just sets wb$worksheets[[wb$validateSheet(sheet)]]$mergeCells and add xml statements of the form <mergeCell ref="from:to" />. The issue with performance arises from a check whether the current merge overlaps with any previous ones. This gives the whole thing a complexity of θ(n) for adding a merge to n previous merges or θ(n²) for adding n merges in total.

    The trick here is to avoid invoking mergeCells but rather set the merges manually:

    corner1 <- openxlsx::getCellRefs(data.frame(1:100000, 1))
    corner2 <- openxlsx::getCellRefs(data.frame(1:100000, 2))
    Workbook4Export$worksheets[[Workbook4Export$validateSheet("Tab_1")]]$mergeCells <-
        sprintf("<mergeCell ref=\"%s:%s\"/>", corner1, corner2)