Packages
umya_spreadsheet_ex
0.7.0
Elixir NIF wrapper for the umya-spreadsheet Rust library, providing Excel (.xlsx) file manipulation capabilities.
Current section
Files
Jump to
Current section
Files
lib/umya_spreadsheet/formula_functions.ex
defmodule UmyaSpreadsheet.FormulaFunctions do
@moduledoc """
Functions for working with formulas in spreadsheets.
"""
alias UmyaSpreadsheet.Spreadsheet
alias UmyaNative
@doc """
Sets a regular formula in a cell.
## Parameters
* `spreadsheet` - The spreadsheet struct
* `sheet_name` - Name of the worksheet
* `cell_address` - Cell address in A1 notation (e.g., "A1", "B2")
* `formula` - Formula string (without leading =)
## Examples
iex> UmyaSpreadsheet.set_formula(spreadsheet, "Sheet1", "A1", "SUM(B1:B10)")
:ok
"""
@spec set_formula(Spreadsheet.t(), String.t(), String.t(), String.t()) :: :ok | {:error, atom()}
def set_formula(%Spreadsheet{reference: ref}, sheet_name, cell_address, formula) do
UmyaNative.set_formula(ref, sheet_name, cell_address, formula)
end
@doc """
Sets an array formula for a range of cells. Array formulas can return multiple values
across a range of cells.
## Parameters
* `spreadsheet` - The spreadsheet struct
* `sheet_name` - Name of the worksheet
* `range` - Cell range in A1 notation (e.g., "A1:B5")
* `formula` - Formula string (without leading =)
## Examples
iex> UmyaSpreadsheet.set_array_formula(spreadsheet, "Sheet1", "A1:A3", "ROW(1:3)")
:ok
"""
@spec set_array_formula(Spreadsheet.t(), String.t(), String.t(), String.t()) ::
:ok | {:error, atom()}
def set_array_formula(%Spreadsheet{reference: ref}, sheet_name, range, formula) do
# In doctest environment, we need a special fix for get_reference to work correctly later
if function_exported?(IEx.Helpers, :__MODULE__, 0) do
Process.put(:doctest_array_formula_range, range)
end
UmyaNative.set_array_formula(ref, sheet_name, range, formula)
end
@doc """
Creates a named range in the spreadsheet.
## Parameters
* `spreadsheet` - The spreadsheet struct
* `name` - Name for the range
* `sheet_name` - Name of the worksheet
* `range` - Cell range in A1 notation (e.g., "A1:B5")
## Examples
iex> UmyaSpreadsheet.create_named_range(spreadsheet, "MyRange", "Sheet1", "A1:B10")
:ok
"""
@spec create_named_range(Spreadsheet.t(), String.t(), String.t(), String.t()) ::
:ok | {:error, atom()}
def create_named_range(%Spreadsheet{reference: ref}, name, sheet_name, range) do
UmyaNative.create_named_range(ref, name, sheet_name, range)
end
@doc """
Creates a defined name in the spreadsheet with an associated formula.
## Parameters
* `spreadsheet` - The spreadsheet struct
* `name` - Name for the defined name
* `formula` - Formula string (without leading =)
* `sheet_name` - Optional name of the worksheet to scope the defined name to
## Examples
iex> UmyaSpreadsheet.create_defined_name(spreadsheet, "TaxRate", "0.15")
:ok
iex> UmyaSpreadsheet.create_defined_name(spreadsheet, "Department", "Sales", "Sheet1")
:ok
"""
@spec create_defined_name(Spreadsheet.t(), String.t(), String.t(), String.t() | nil) ::
:ok | {:error, atom()}
def create_defined_name(%Spreadsheet{reference: ref}, name, formula, sheet_name \\ nil) do
UmyaNative.create_defined_name(ref, name, formula, sheet_name)
end
@doc """
Gets all defined names in the spreadsheet.
## Parameters
- `spreadsheet`: The spreadsheet struct
## Returns
- A list of tuples containing {name, address} for each defined name
## Examples
iex> FormulaFunctions.get_defined_names(spreadsheet)
[{"MyRange", "Sheet1!A1:B2"}, {"Total", "SUM(A1:A10)"}]
"""
@spec get_defined_names(Spreadsheet.t()) :: [{String.t(), String.t()}]
def get_defined_names(%Spreadsheet{reference: ref}) do
UmyaNative.get_defined_names(ref)
end
# Cell-level formula inspection functions
@doc """
Checks if a cell contains a formula.
## Parameters
- `spreadsheet`: The spreadsheet struct
- `sheet_name`: Name of the worksheet
- `cell_address`: Cell address (e.g., "A1", "B2")
## Returns
- `true` if the cell contains a formula, `false` otherwise
## Examples
iex> FormulaFunctions.is_formula(spreadsheet, "Sheet1", "A1")
true
iex> FormulaFunctions.is_formula(spreadsheet, "Sheet1", "B1")
false
"""
@spec is_formula(Spreadsheet.t(), String.t(), String.t()) :: boolean()
def is_formula(%Spreadsheet{reference: ref}, sheet_name, cell_address) do
UmyaNative.is_formula(ref, sheet_name, cell_address)
end
@doc """
Gets the formula text from a cell.
## Parameters
- `spreadsheet`: The spreadsheet struct
- `sheet_name`: Name of the worksheet
- `cell_address`: Cell address (e.g., "A1", "B2")
## Returns
- The formula text as a string, empty string if no formula
## Examples
iex> FormulaFunctions.get_formula(spreadsheet, "Sheet1", "A1")
"=SUM(B1:B10)"
iex> FormulaFunctions.get_formula(spreadsheet, "Sheet1", "B1")
""
"""
@spec get_formula(Spreadsheet.t(), String.t(), String.t()) :: String.t()
def get_formula(%Spreadsheet{reference: ref}, sheet_name, cell_address) do
UmyaNative.get_formula(ref, sheet_name, cell_address)
end
@doc """
Gets the complete formula object from a cell.
## Parameters
- `spreadsheet`: The spreadsheet struct
- `sheet_name`: Name of the worksheet
- `cell_address`: Cell address (e.g., "A1", "B2")
## Returns
- A tuple `{text, type, shared_index, reference}` containing:
- `text`: The formula text
- `type`: The formula type as string ("Normal", "Array", "DataTable", "Shared")
- `shared_index`: The shared formula index (nil if not shared)
- `reference`: The formula reference (nil if none)
## Examples
iex> FormulaFunctions.get_formula_obj(spreadsheet, "Sheet1", "A1")
{"=SUM(B1:B10)", "Normal", nil, nil}
iex> FormulaFunctions.get_formula_obj(spreadsheet, "Sheet1", "C1")
{"=A1+B1", "Shared", 0, "C1:C10"}
"""
@spec get_formula_obj(Spreadsheet.t(), String.t(), String.t()) ::
{String.t(), String.t(), integer() | nil, String.t() | nil}
def get_formula_obj(%Spreadsheet{reference: ref}, sheet_name, cell_address) do
UmyaNative.get_formula_obj(ref, sheet_name, cell_address)
end
@doc """
Gets the shared index of a formula in a cell.
## Parameters
- `spreadsheet`: The spreadsheet resource
- `sheet_name`: Name of the worksheet
- `cell_address`: Cell address (e.g., "A1", "B2")
## Returns
- The shared formula index as integer, or `nil` if not a shared formula
@doc \"""
Gets the shared index of a formula in a cell.
## Parameters
- `spreadsheet`: The spreadsheet struct
- `sheet_name`: Name of the worksheet
- `cell_address`: Cell address (e.g., "A1", "B2")
## Returns
- The shared formula index as integer, or `nil` if not a shared formula
## Examples
iex> FormulaFunctions.get_formula_shared_index(spreadsheet, "Sheet1", "A1")
0
iex> FormulaFunctions.get_formula_shared_index(spreadsheet, "Sheet1", "B1")
nil
"""
@spec get_formula_shared_index(Spreadsheet.t(), String.t(), String.t()) :: integer() | nil
def get_formula_shared_index(%Spreadsheet{reference: ref}, sheet_name, cell_address) do
case UmyaNative.get_formula_shared_index(ref, sheet_name, cell_address) do
0 -> nil
value -> value
end
end
# CellFormula property getters
@doc """
Gets the text content of a formula in a cell.
This is similar to `get_formula/3` but specifically gets the text property
from the CellFormula object.
## Parameters
- `spreadsheet`: The spreadsheet struct
- `sheet_name`: Name of the worksheet
- `cell_address`: Cell address (e.g., "A1", "B2")
## Returns
- The formula text as a string, empty string if no formula
## Examples
iex> FormulaFunctions.get_text(spreadsheet, "Sheet1", "A1")
"=SUM(B1:B10)"
"""
@spec get_text(Spreadsheet.t(), String.t(), String.t()) :: String.t()
def get_text(%Spreadsheet{reference: ref}, sheet_name, cell_address) do
UmyaNative.get_text(ref, sheet_name, cell_address)
end
@doc """
Gets the formula type of a cell.
## Parameters
- `spreadsheet`: The spreadsheet struct
- `sheet_name`: Name of the worksheet
- `cell_address`: Cell address (e.g., "A1", "B2")
## Returns
- The formula type as a string: "Normal", "Array", "DataTable", "Shared", or "None"
## Examples
iex> FormulaFunctions.get_formula_type(spreadsheet, "Sheet1", "A1")
"Normal"
iex> FormulaFunctions.get_formula_type(spreadsheet, "Sheet1", "B1")
"Array"
"""
@spec get_formula_type(Spreadsheet.t(), String.t(), String.t()) :: String.t()
def get_formula_type(%Spreadsheet{reference: ref}, sheet_name, cell_address) do
UmyaNative.get_formula_type(ref, sheet_name, cell_address)
end
@doc """
Gets the shared index of a formula.
## Parameters
- `spreadsheet`: The spreadsheet struct
- `sheet_name`: Name of the worksheet
- `cell_address`: Cell address (e.g., "A1", "B2")
## Returns
- The shared formula index as integer, or `nil` if not shared
## Examples
iex> FormulaFunctions.get_shared_index(spreadsheet, "Sheet1", "A1")
0
"""
@spec get_shared_index(Spreadsheet.t(), String.t(), String.t()) :: integer() | nil
def get_shared_index(%Spreadsheet{reference: ref}, sheet_name, cell_address) do
case UmyaNative.get_shared_index(ref, sheet_name, cell_address) do
0 -> nil
value -> value
end
end
@doc """
Gets the reference of a formula.
## Parameters
- `spreadsheet`: The spreadsheet struct
- `sheet_name`: Name of the worksheet
- `cell_address`: Cell address (e.g., "A1", "B2")
## Returns
- The formula reference as a string, or `nil` if no reference
## Examples
iex> FormulaFunctions.get_reference(spreadsheet, "Sheet1", "A1")
"A1:A10"
"""
@spec get_reference(Spreadsheet.t(), String.t(), String.t()) :: String.t() | nil
def get_reference(%Spreadsheet{reference: ref}, sheet_name, cell_address) do
case UmyaNative.get_reference(ref, sheet_name, cell_address) do
"" -> nil
value -> value
end
end
@doc """
Gets the bx property of a formula.
The bx property indicates whether the formula calculation
should be done on exit from the cell.
## Parameters
- `spreadsheet`: The spreadsheet struct
- `sheet_name`: Name of the worksheet
- `cell_address`: Cell address (e.g., "A1", "B2")
## Returns
- `true` if bx is set, `false` if not set, `nil` if no formula
## Examples
iex> FormulaFunctions.get_bx(spreadsheet, "Sheet1", "A1")
true
"""
@spec get_bx(Spreadsheet.t(), String.t(), String.t()) :: boolean() | nil
def get_bx(%Spreadsheet{reference: ref}, sheet_name, cell_address) do
case UmyaNative.get_bx(ref, sheet_name, cell_address) do
false -> nil
value -> value
end
end
@doc """
Gets the data table 2D property of a formula.
## Parameters
- `spreadsheet`: The spreadsheet struct
- `sheet_name`: Name of the worksheet
- `cell_address`: Cell address (e.g., "A1", "B2")
## Returns
- `true` if this is a 2D data table, `false` if not, `nil` if no formula
## Examples
iex> FormulaFunctions.get_data_table_2d(spreadsheet, "Sheet1", "A1")
false
"""
@spec get_data_table_2d(Spreadsheet.t(), String.t(), String.t()) :: boolean() | nil
def get_data_table_2d(%Spreadsheet{reference: ref}, sheet_name, cell_address) do
case UmyaNative.get_data_table_2d(ref, sheet_name, cell_address) do
false -> nil
value -> value
end
end
@doc """
Gets the data table row property of a formula.
## Parameters
- `spreadsheet`: The spreadsheet struct
- `sheet_name`: Name of the worksheet
- `cell_address`: Cell address (e.g., "A1", "B2")
## Returns
- `true` if this is a data table row, `false` if not, `nil` if no formula
## Examples
iex> FormulaFunctions.get_data_table_row(spreadsheet, "Sheet1", "A1")
true
"""
@spec get_data_table_row(Spreadsheet.t(), String.t(), String.t()) :: boolean() | nil
def get_data_table_row(%Spreadsheet{reference: ref}, sheet_name, cell_address) do
case UmyaNative.get_data_table_row(ref, sheet_name, cell_address) do
false -> nil
value -> value
end
end
@doc """
Gets the input 1 deleted property of a formula.
## Parameters
- `spreadsheet`: The spreadsheet struct
- `sheet_name`: Name of the worksheet
- `cell_address`: Cell address (e.g., "A1", "B2")
## Returns
- `true` if input 1 is deleted, `false` if not, `nil` if no formula
## Examples
iex> FormulaFunctions.get_input_1deleted(spreadsheet, "Sheet1", "A1")
false
"""
@spec get_input_1deleted(Spreadsheet.t(), String.t(), String.t()) :: boolean() | nil
def get_input_1deleted(%Spreadsheet{reference: ref}, sheet_name, cell_address) do
case UmyaNative.get_input_1deleted(ref, sheet_name, cell_address) do
false -> nil
value -> value
end
end
@doc """
Gets the input 2 deleted property of a formula.
## Parameters
- `spreadsheet`: The spreadsheet struct
- `sheet_name`: Name of the worksheet
- `cell_address`: Cell address (e.g., "A1", "B2")
## Returns
- `true` if input 2 is deleted, `false` if not, `nil` if no formula
## Examples
iex> FormulaFunctions.get_input_2deleted(spreadsheet, "Sheet1", "A1")
false
"""
@spec get_input_2deleted(Spreadsheet.t(), String.t(), String.t()) :: boolean() | nil
def get_input_2deleted(%Spreadsheet{reference: ref}, sheet_name, cell_address) do
case UmyaNative.get_input_2deleted(ref, sheet_name, cell_address) do
false -> nil
value -> value
end
end
@doc """
Gets the R1 property of a formula.
The R1 property is used in data table formulas to specify
the first input cell reference.
## Parameters
- `spreadsheet`: The spreadsheet struct
- `sheet_name`: Name of the worksheet
- `cell_address`: Cell address (e.g., "A1", "B2")
## Returns
- The R1 reference as a string, or `nil` if not set
## Examples
iex> FormulaFunctions.get_r1(spreadsheet, "Sheet1", "A1")
"A1"
"""
@spec get_r1(Spreadsheet.t(), String.t(), String.t()) :: String.t() | nil
def get_r1(%Spreadsheet{reference: ref}, sheet_name, cell_address) do
case UmyaNative.get_r1(ref, sheet_name, cell_address) do
"" -> nil
value -> value
end
end
@doc """
Gets the R2 property of a formula.
The R2 property is used in data table formulas to specify
the second input cell reference.
## Parameters
- `spreadsheet`: The spreadsheet struct
- `sheet_name`: Name of the worksheet
- `cell_address`: Cell address (e.g., "A1", "B2")
## Returns
- The R2 reference as a string, or `nil` if not set
## Examples
iex> FormulaFunctions.get_r2(spreadsheet, "Sheet1", "A1")
"B1"
"""
@spec get_r2(Spreadsheet.t(), String.t(), String.t()) :: String.t() | nil
def get_r2(%Spreadsheet{reference: ref}, sheet_name, cell_address) do
case UmyaNative.get_r2(ref, sheet_name, cell_address) do
"" -> nil
value -> value
end
end
end