Class: LiquidXlsx::MergeCellsTransformer

Inherits:
Object
  • Object
show all
Defined in:
lib/liquid_xlsx/merge_cells_transformer.rb

Overview

Handles transformation of merged cells when rows are inserted or deleted.

Instance Method Summary collapse

Instance Method Details

#clone_for_row(merge_range, row_offset) ⇒ String

Clone a merge range for a repeated row.

Parameters:

  • merge_range (String)

    e.g., "A3:B3"

  • row_offset (Integer)

    shift from original row

Returns:

  • (String)

    new merge range



10
11
12
13
14
15
16
17
18
19
20
# File 'lib/liquid_xlsx/merge_cells_transformer.rb', line 10

def clone_for_row(merge_range, row_offset)
  return nil if row_offset == 0

  start_ref, end_ref = merge_range.split(":")
  start = CellReference.new(start_ref)
  end_ref = CellReference.new(end_ref)

  new_start = start.shift(row_offset, 0)
  new_end = end_ref.shift(row_offset, 0)
  "#{new_start}:#{new_end}"
end

#crosses_boundary?(merge_start_row, merge_end_row, block_start, block_end) ⇒ Boolean

Check if a merge range crosses a structural block boundary.

Parameters:

  • merge_start_row (Integer)
  • merge_end_row (Integer)
  • block_start (Integer)
  • block_end (Integer)

Returns:

  • (Boolean)


54
55
56
57
58
59
60
61
62
63
64
# File 'lib/liquid_xlsx/merge_cells_transformer.rb', line 54

def crosses_boundary?(merge_start_row, merge_end_row, block_start, block_end)
  # Merge is completely inside the block - not crossing
  return false if merge_start_row >= block_start && merge_end_row <= block_end
  # Merge is completely above the block - not crossing
  return false if merge_end_row < block_start
  # Merge is completely below the block - not crossing
  return false if merge_start_row > block_end

  # Merge overlaps with block boundaries — crosses
  true
end

#inside_range?(merge_start_row, merge_end_row, range_start, range_end) ⇒ Boolean

Check if merge is inside a range

Parameters:

  • merge_start_row (Integer)
  • merge_end_row (Integer)
  • range_start (Integer)
  • range_end (Integer)

Returns:

  • (Boolean)


72
73
74
# File 'lib/liquid_xlsx/merge_cells_transformer.rb', line 72

def inside_range?(merge_start_row, merge_end_row, range_start, range_end)
  merge_start_row >= range_start && merge_end_row <= range_end
end

#shift_below(merge_range, boundary_start, boundary_end, row_delta) ⇒ String?

Shift merge ranges that are below a block boundary.

Parameters:

  • merge_range (String)

    original merge range

  • boundary_start (Integer)

    first row of the block

  • boundary_end (Integer)

    last row of the block

  • row_delta (Integer)

    net row shift (positive = insert, negative = delete)

Returns:

  • (String, nil)

    new merge range or nil if it should be removed



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/liquid_xlsx/merge_cells_transformer.rb', line 28

def shift_below(merge_range, boundary_start, boundary_end, row_delta)
  start_ref, end_ref = merge_range.split(":")
  start = CellReference.new(start_ref)
  end_ref = CellReference.new(end_ref)

  # Check if merge crosses the boundary
  if crosses_boundary?(start.row, end_ref.row, boundary_start, boundary_end)
    return nil # marked for error
  end

  # If merge is completely below the boundary, shift it
  if start.row >= boundary_start
    new_start = start.shift(row_delta, 0)
    new_end = end_ref.shift(row_delta, 0)
    "#{new_start}:#{new_end}"
  else
    merge_range # above boundary, keep as is
  end
end