ExVEx.OOXML.Worksheet.Editable (ExVEx v0.2.0)

Copy Markdown View Source

ETS-backed editable representation of a worksheet. The parsed SimpleForm tree is converted on first access and materialised back to a tree at serialise time.

The cell grid lives in an ETS :set table for O(1) lookup and insert. Surrounding <worksheet> content (<sheetViews>, <cols>, <mergeCells>, <pageMargins>, …) passes through pre_sheet_data / post_sheet_data unchanged so fidelity is preserved.

Sharing semantics

ETS tables are mutable. Two %ExVEx.Workbook{} references that share the same cached sheet via Workbook.put_sheet_tree/3 also share the same underlying ETS table; a mutation on one is visible from the other.

In practice this shows up between a workbook and its put_cell descendants after the sheet has been parsed at least once. A pristine workbook from ExVEx.open/1 that has not yet touched a sheet is insulated because it will lazily create a fresh table on first access.

If you need an independent snapshot, ExVEx.save/2 it and open/1 that, or call ExVEx.close/1 and re-open.

Memory lifecycle

ETS tables persist until the owning process exits. In short-lived processes (scripts, one-shot jobs, tests) this is fine. In long-running servers that open many workbooks, call ExVEx.close/1 when done with a workbook to reclaim the tables eagerly.

Summary

Functions

Returns the resolved %ExVEx.OOXML.Worksheet.Cell{} record for the given coordinate, or :error if the cell is absent.

Drops the <dimension> element from the worksheet so Excel recomputes the used range on open. No-op if the sheet has no <dimension>.

Applies a structural row/column shift to every populated cell on this sheet. Cells in deletion spans are removed; surviving cells have their coordinates rekeyed; formulas inside cells are rewritten via ExVEx.Formula.Shift. Merged ranges in post_sheet_data are shifted too.

Types

cell_element()

@type cell_element() :: {String.t(), list(), list()}

t()

@type t() :: %ExVEx.OOXML.Worksheet.Editable{
  cells_table: :ets.tid() | nil,
  post_sheet_data: list(),
  pre_sheet_data: list(),
  row_attrs: %{required(pos_integer()) => list()},
  sheet_data_attrs: list(),
  worksheet_attrs: list()
}

Functions

cell_record_at(editable, coord)

@spec cell_record_at(t(), ExVEx.Utils.Coordinate.t()) ::
  {:ok, ExVEx.OOXML.Worksheet.Cell.t()} | :error

Returns the resolved %ExVEx.OOXML.Worksheet.Cell{} record for the given coordinate, or :error if the cell is absent.

cells_map(editable)

@spec cells_map(t()) :: %{
  required(ExVEx.Utils.Coordinate.t()) => ExVEx.OOXML.Worksheet.Cell.t()
}

clear_dimension(e)

@spec clear_dimension(t()) :: t()

Drops the <dimension> element from the worksheet so Excel recomputes the used range on open. No-op if the sheet has no <dimension>.

from_tree(arg)

@spec from_tree({String.t(), list(), list()}) :: t()

get_cell(editable, coord)

@spec get_cell(t(), ExVEx.Utils.Coordinate.t()) :: {:ok, cell_element()} | :error

merge(e, range, clear_non_anchor?)

@spec merge(t(), ExVEx.Utils.Range.t(), boolean()) :: t()

merged_ranges(editable)

@spec merged_ranges(t()) :: [ExVEx.Utils.Range.t()]

put_cell(e, coord, value)

@spec put_cell(t(), ExVEx.Utils.Coordinate.t(), ExVEx.cell_value()) :: t()

set_cell_style(e, coord, style_id)

@spec set_cell_style(t(), ExVEx.Utils.Coordinate.t(), non_neg_integer()) :: t()

shift(e, mut_shift, sheet_name)

@spec shift(t(), ExVEx.Mutation.Shift.t(), String.t()) :: t()

Applies a structural row/column shift to every populated cell on this sheet. Cells in deletion spans are removed; surviving cells have their coordinates rekeyed; formulas inside cells are rewritten via ExVEx.Formula.Shift. Merged ranges in post_sheet_data are shifted too.

sheet_name is the name of the sheet this Editable represents, used to scope formulas that reference the current sheet.

to_tree(e)

@spec to_tree(t()) :: {String.t(), list(), list()}

unmerge(e, range)

@spec unmerge(t(), ExVEx.Utils.Range.t()) :: t()