Merge two adjacent cells in a spreadsheet

Merged cells are stored in worksheet XML under <mergeCells/>. The original cell values remain in the grid; applications display the merged range as one cell.

Before adding a merge range, make sure both endpoint cells exist. A writer normally creates any missing row or cell elements first, then records the range in mergeCells.

Merge markup

<mergeCells count="1">
  <mergeCell ref="A1:B1"/>
</mergeCells>

The ref attribute stores the merged range.

The range is expressed with normal cell references such as A1:B1. Parse a cell reference by separating the column letters from the row digits; this is useful both for checking adjacency and for inserting any missing cells in row and column order.

Rust workflow

#![allow(unused)]
fn main() {
pub fn merge_adjacent_cells(
  path: &Path,
  sheet_name: &str,
  first_cell: &str,
  second_cell: &str,
) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
  let mut document = SpreadsheetDocument::new_from_file_with_settings(path, lazy_settings())?;
  let workbook_part = document.workbook_part()?;
  let worksheet_part = worksheet_part_by_name(&document, &workbook_part, sheet_name)?;
  let worksheet_xml = worksheet_part.data_as_str(&document)?.unwrap_or_default();
  let updated_xml = add_merge_range(worksheet_xml, first_cell, second_cell)?;

  worksheet_part.set_data(&mut document, updated_xml.into_bytes())?;

  let mut buffer = Cursor::new(Vec::new());
  document.save(&mut buffer)?;
  Ok(buffer.into_inner())
}
}

The listing checks that the two endpoints are adjacent, appends the merge range, and updates the mergeCells count when the collection already exists. A more complete writer should also reject ranges that overlap existing merged ranges.

Only one cell's displayed content is preserved by spreadsheet applications after a merge. For left-to-right sheets, that is typically the upper-left cell in the merged range; for right-to-left sheets, applications can preserve the upper-right value. Avoid relying on values from the other cells in the range.