"""The workbook-reading policy every layer that opens a spreadsheet shares.A cell carrying a formula states a computation, not a figure. Beside it aworkbook may cache whatever number was last computed into it, and that cachednumber is not the formula's value: a sheet edited somewhere else and savedwithout recalculating carries a figure nobody typed and the formula does notproduce. Reading it would take that number as fact.So a formula cell is **refused, never read**, everywhere a spreadsheet istreated as a source of financial or filing data — the bank-statement workbookprovider, the casilla-value spreadsheet, and the bulk invoice book each refuseon this ground. The alternative, reading the cached value, fails in thedirection that matters: the wrong figure reaches a return as a number ratherthan as any kind of failure, which is the one outcome no downstream check ispositioned to catch.The detection and the sentence live here so the three readers cannot driftapart on what a formula cell is or on what the operator is told about it. Whatstays with each reader is the part that genuinely differs: which rows are inscope (the statement provider ignores its preamble and header, the other tworead every row), and which error type its layer refuses with.This module deliberately does not import ``openpyxl``. The cell is describedstructurally instead, so resolving the policy never pulls a spreadsheet engineinto the innermost layer.See Also: :class:`~core.tabular.NormalizedTable` The delimited-text counterpart. A workbook states its own cell types, so it has no dialect to detect and shares nothing with that module beyond both being tabular sources."""from__future__importannotationsfromcollections.abcimportIterablefromtypingimportFinal,Protocol__all__=["FORMULA_CELL_REFUSAL","WorkbookCell","first_formula_cell_column",]FORMULA_CELL_REFUSAL:Final[str]="formula cached values are not accepted""""The clause every formula-cell refusal ends with, so all three read alike."""
[docs]classWorkbookCell(Protocol):"""The one attribute the policy needs from a workbook cell. Structural rather than nominal so that ``openpyxl``'s ``Cell``, ``ReadOnlyCell`` and ``EmptyCell`` all satisfy it without this module importing the library. Every one of them exposes ``data_type``. """@propertydefdata_type(self)->str:"""The cell's openpyxl type code; ``"f"`` marks a formula."""...
[docs]deffirst_formula_cell_column(cells:Iterable[WorkbookCell])->int|None:"""Return the 1-based column of the first formula cell in *cells*. Args: cells: One row's cells, in column order. Returns: The 1-based column number of the first cell stating a formula, or ``None`` when the row carries none. Reporting the position rather than raising leaves each caller free to refuse in its own layer's error type and to name its own artefact, while the test for what counts as a formula stays in one place. """forcolumn_number,cellinenumerate(cells,start=1):ifcell.data_type=="f":returncolumn_numberreturnNone