Skip to content

Sheets

albert.resources.sheets

Attributes:

Name Type Description
CellAttributeValue

CellAttributeValue

CellAttributeValue = (
    str | float | int | dict[str, Any] | list[Any] | None
)

CellChangeId

Bases: TypedDict

Internal identifier (row ID and column ID) locating a cell in a change payload.

Attributes:

Name Type Description
rowId str
colId str

rowId

rowId: str

colId

colId: str

CellChangePayload

Bases: TypedDict

Internal payload describing the patch operations to apply to a single cell.

Attributes:

Name Type Description
Id CellChangeId
data list[PatchDatum]

Id

data

CellColor

Bases: str, Enum

A background color that can be applied to Sheet cells.

Each value is the RGB string the platform stores for the cell background. Used with recolor_cells and recolor_cells to highlight cells in a Sheet.

Example

from albert.resources.sheets import CellColor
column = sheet.get_column(column_name="Formulation A")
column.recolor_cells(CellColor.GREEN)

Attributes:

Name Type Description
WHITE
RED
GREEN
BLUE
YELLOW
ORANGE
PURPLE

WHITE

WHITE = 'RGB(255, 255, 255)'

RED

RED = 'RGB(255, 161, 161)'

GREEN

GREEN = 'RGB(130, 222, 198)'

BLUE

BLUE = 'RGB(214, 233, 255)'

YELLOW

YELLOW = 'RGB(254, 240, 159)'

ORANGE

ORANGE = 'RGB(255, 227, 210)'

PURPLE

PURPLE = 'RGB(238, 215, 255)'

CellType

Bases: str, Enum

The kind of content a Cell, Column, or Row holds.

Cells, Columns, and Rows all carry a type drawn from this enum, which determines how the platform interprets their contents. The values most relevant when building formulations are INVENTORY (an ingredient amount), TOTAL (a computed total row), FORMULA and FOR (formulation columns), LKP (a lookup that displays an inventory attribute), and BLANK (an empty cell). The remaining members correspond to specialized grid content such as tags, prices, tasks, results, and apps.

Attributes:

Name Type Description
INVENTORY
APP
BLANK
FORMULA
TAG
PRICE
PDC
BAT
TOTAL
TAS
DEF
LKP
FOR
EXTINV
BTI
PRM
PRG
RSL
FNC
WFL
DAC
INT
DAT
NDR
PIC

INVENTORY

INVENTORY = 'INV'

APP

APP = 'APP'

BLANK

BLANK = 'BLK'

FORMULA

FORMULA = 'Formula'

TAG

TAG = 'TAG'

PRICE

PRICE = 'PRC'

PDC

PDC = 'PDC'

BAT

BAT = 'BAT'

TOTAL

TOTAL = 'TOT'

TAS

TAS = 'TAS'

DEF

DEF = 'DEF'

LKP

LKP = 'LKP'

FOR

FOR = 'FOR'

EXTINV

EXTINV = 'EXTINV'

BTI

BTI = 'BTI'

PRM

PRM = 'PRM'

PRG

PRG = 'PRG'

RSL

RSL = 'RSL'

FNC

FNC = 'FNC'

WFL

WFL = 'WFL'

DAC

DAC = 'DAC'

INT

INT = 'INT'

DAT

DAT = 'DAT'

NDR

NDR = 'NDR'

PIC

PIC = 'PIC'

DesignType

Bases: str, Enum

The section of a Sheet that a Design represents.

A Sheet is organized into stacked sections, each backed by a Design (Design). The type identifies which section:

  • PRODUCTS: Product Design, where formulations are built.
  • PROCESS: Process Design.
  • RESULTS: Results, holding Property Tasks and their data.
  • APPS: Apps, holding insights, reporting, and notes.

Attributes:

Name Type Description
APPS
PRODUCTS
RESULTS
PROCESS
REAGENTS

APPS

APPS = 'apps'

PRODUCTS

PRODUCTS = 'products'

RESULTS

RESULTS = 'results'

PROCESS

PROCESS = 'process'

REAGENTS

REAGENTS = 'reagents'

ColumnPosition

Bases: str, Enum

Where to insert a new column relative to a reference column.

Used by the add_*_column methods of Sheet to place a new column LEFT_OF or RIGHT_OF an existing one.

Attributes:

Name Type Description
LEFT_OF
RIGHT_OF

LEFT_OF

LEFT_OF = 'leftOf'

RIGHT_OF

RIGHT_OF = 'rightOf'

RowPosition

Bases: str, Enum

Where to insert a new row relative to a reference row.

Used by the row-adding methods of Sheet (e.g. add_lookup_row, add_app_row) to place a new row ABOVE or BELOW an existing one.

Attributes:

Name Type Description
ABOVE
BELOW

ABOVE

ABOVE = 'above'

BELOW

BELOW = 'below'

Cell

Bases: BaseResource

A single cell in a Sheet grid, at the intersection of a Column and a Row.

A Cell is a live grid element: it carries the session and knows its position (via column_id, row_id, and design_id) as well as its value, calculation, and formatting. Cells are typically read from a Sheet's grid or from cells / cells, and written back with update_cells.

Show JSON schema:
{
  "$defs": {
    "AuditFields": {
      "description": "The audit fields for a resource",
      "properties": {
        "by": {
          "default": null,
          "title": "By",
          "type": "string"
        },
        "byName": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Byname"
        },
        "at": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "At"
        }
      },
      "title": "AuditFields",
      "type": "object"
    },
    "CellType": {
      "description": "The kind of content a Cell, Column, or Row holds.\n\nCells, Columns, and Rows all carry a type drawn from this enum, which\ndetermines how the platform interprets their contents. The values most\nrelevant when building formulations are ``INVENTORY`` (an ingredient amount),\n``TOTAL`` (a computed total row), ``FORMULA`` and ``FOR`` (formulation\ncolumns), ``LKP`` (a lookup that displays an inventory attribute), and\n``BLANK`` (an empty cell). The remaining members correspond to specialized\ngrid content such as tags, prices, tasks, results, and apps.",
      "enum": [
        "INV",
        "APP",
        "BLK",
        "Formula",
        "TAG",
        "PRC",
        "PDC",
        "BAT",
        "TOT",
        "TAS",
        "DEF",
        "LKP",
        "FOR",
        "EXTINV",
        "BTI",
        "PRM",
        "PRG",
        "RSL",
        "FNC",
        "WFL",
        "DAC",
        "INT",
        "DAT",
        "NDR",
        "PIC"
      ],
      "title": "CellType",
      "type": "string"
    },
    "Status": {
      "description": "The status of a resource.\n\nAttributes\n----------\nACTIVE : str\n    The resource is fully operational and visible in normal operations.\nINACTIVE : str\n    The resource is hidden from normal operations and disabled from use.",
      "enum": [
        "active",
        "inactive"
      ],
      "title": "Status",
      "type": "string"
    }
  },
  "description": "A single cell in a Sheet grid, at the intersection of a Column and a Row.\n\nA Cell is a live grid element: it carries the session and knows its position\n(via ``column_id``, ``row_id``, and ``design_id``) as well as its value,\ncalculation, and formatting. Cells are typically read from a Sheet's grid or\nfrom [`cells`][albert.resources.sheets.Column.cells] / [`cells`][albert.resources.sheets.Row.cells], and written back with\n[`update_cells`][albert.resources.sheets.Sheet.update_cells].",
  "properties": {
    "status": {
      "anyOf": [
        {
          "$ref": "#/$defs/Status"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The status of the resource, optional."
    },
    "Created": {
      "anyOf": [
        {
          "$ref": "#/$defs/AuditFields"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Audit fields for the creation of the resource, optional."
    },
    "Updated": {
      "anyOf": [
        {
          "$ref": "#/$defs/AuditFields"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Audit fields for the update of the resource, optional."
    },
    "colId": {
      "description": "The ID of the Column this cell belongs to.",
      "title": "Colid",
      "type": "string"
    },
    "rowId": {
      "description": "The ID of the Row this cell belongs to.",
      "title": "Rowid",
      "type": "string"
    },
    "lableName": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The display name of the row this cell is in.",
      "title": "Lablename"
    },
    "value": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "additionalProperties": true,
          "type": "object"
        },
        {
          "items": {},
          "type": "array"
        }
      ],
      "default": "",
      "description": "The value of the cell. For an inventory cell this may be a dict rather than a plain string; see [`raw_value`][albert.resources.sheets.Cell.raw_value] for the underlying value.\n\nFor **special parameters** in the Process Design grid (parameters whose value\nreferences an inventory item: equipment, consumables, raw materials), the\nlinked-cell form is the lookup string ``\"<DisplayID> || <ItemName>\"`` (double\npipe with spaces, INV prefix stripped), e.g. ``\"B90948 || Copper Coupon\"``.\nWriting a bare ``\"INV...\"`` id is accepted by the API but stored as unlinked\nplain text, so the UI shows the raw id instead of the linked item. On reads,\na linked cell's value is a dict of the form ``{\"id\": \"INVB90948\", \"name\":\n\"B90948 || Copper Coupon\"}``.",
      "title": "Value"
    },
    "minValue": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The minimum allowed value for inventory cells. Optional.",
      "title": "Minvalue"
    },
    "maxValue": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The maximum allowed value for inventory cells. Optional.",
      "title": "Maxvalue"
    },
    "type": {
      "anyOf": [
        {
          "$ref": "#/$defs/CellType"
        },
        {
          "type": "string"
        }
      ],
      "description": "The type of the cell. Allowed values are the same as for [`CellType`][albert.resources.sheets.CellType].",
      "title": "Type"
    },
    "row_type": {
      "anyOf": [
        {
          "$ref": "#/$defs/CellType"
        },
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The type of the row containing this cell. Usually one of ``INV`` (inventory row), ``TOT`` (total row), ``TAS`` (task row), ``TAG``, ``PRC``, ``PDC``, ``BAT``, or ``BLK``.",
      "title": "Row Type"
    },
    "name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The name of the cell. Optional. Default is None.",
      "title": "Name"
    },
    "calculation": {
      "default": "",
      "description": "The formula backing the cell, if any (e.g. a total). Default is ``\"\"``.",
      "title": "Calculation",
      "type": "string"
    },
    "design_id": {
      "description": "The ID of the Design (Sheet section) this cell is in.",
      "title": "Design Id",
      "type": "string"
    },
    "cellFormat": {
      "additionalProperties": true,
      "description": "The cell formatting. Default is ``{}``. Keys are ``bgColor`` and ``fontColor``, with RGB string values such as ``\"RGB(255, 255, 255)\"``.",
      "title": "Cellformat",
      "type": "object"
    },
    "inventory_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Inventory Id"
    }
  },
  "required": [
    "colId",
    "rowId",
    "type",
    "design_id"
  ],
  "title": "Cell",
  "type": "object"
}

Fields:

column_id

column_id: str

The ID of the Column this cell belongs to.

row_id

row_id: str

The ID of the Row this cell belongs to.

row_label_name

row_label_name: str | None = None

The display name of the row this cell is in.

value

value: str | dict | list = ''

The value of the cell. For an inventory cell this may be a dict rather than a plain string; see raw_value for the underlying value.

For special parameters in the Process Design grid (parameters whose value references an inventory item: equipment, consumables, raw materials), the linked-cell form is the lookup string "<DisplayID> || <ItemName>" (double pipe with spaces, INV prefix stripped), e.g. "B90948 || Copper Coupon". Writing a bare "INV..." id is accepted by the API but stored as unlinked plain text, so the UI shows the raw id instead of the linked item. On reads, a linked cell's value is a dict of the form {"id": "INVB90948", "name": "B90948 || Copper Coupon"}.

min_value

min_value: str | None = None

The minimum allowed value for inventory cells. Optional.

max_value

max_value: str | None = None

The maximum allowed value for inventory cells. Optional.

type

type: CellType | str

The type of the cell. Allowed values are the same as for CellType.

row_type

row_type: CellType | str | None = None

The type of the row containing this cell. Usually one of INV (inventory row), TOT (total row), TAS (task row), TAG, PRC, PDC, BAT, or BLK.

name

name: str | None = None

The name of the cell. Optional. Default is None.

calculation

calculation: str = ''

The formula backing the cell, if any (e.g. a total). Default is "".

design_id

design_id: str

The ID of the Design (Sheet section) this cell is in.

format

format: dict

The cell formatting. Default is {}. Keys are bgColor and fontColor, with RGB string values such as "RGB(255, 255, 255)".

inventory_id

inventory_id: str | None = None

raw_value

raw_value

color

color

Component

Bases: BaseResource

One ingredient and its amount within a formulation.

A Component pairs an inventory item (InventoryItem) with the amount of it used in a formulation. Components are the input to add_formulation and add_components_to_formulation, which place each ingredient's amount into the appropriate Cell of a formulation Column. Provide either inventory_item or inventory_id; when inventory_item is given, inventory_id is populated from it automatically.

Example

from albert.resources.sheets import Component
component = Component(inventory_id="INVA9999999", amount=42.0)
Show JSON schema:
{
  "$defs": {
    "ACL": {
      "description": "A single access rule for a user.",
      "properties": {
        "id": {
          "description": "The id of the user for which this ACL applies",
          "title": "Id",
          "type": "string"
        },
        "fgc": {
          "anyOf": [
            {
              "$ref": "#/$defs/AccessControlLevel"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The Fine-Grain Control Level"
        }
      },
      "required": [
        "id"
      ],
      "title": "ACL",
      "type": "object"
    },
    "AccessControlLevel": {
      "description": "Access control levels you can grant users.",
      "enum": [
        "ProjectOwner",
        "ProjectEditor",
        "ProjectViewer",
        "ProjectAllTask",
        "ProjectStrictViewer",
        "ProjectPropertyTask",
        "InventoryOwner",
        "InventoryViewer",
        "CustomTemplateOwner",
        "CustomTemplateViewer",
        "CASFullAccess"
      ],
      "title": "AccessControlLevel",
      "type": "string"
    },
    "AuditFields": {
      "description": "The audit fields for a resource",
      "properties": {
        "by": {
          "default": null,
          "title": "By",
          "type": "string"
        },
        "byName": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Byname"
        },
        "at": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "At"
        }
      },
      "title": "AuditFields",
      "type": "object"
    },
    "Cas": {
      "description": "A CAS entry: a chemical substance identified by its CAS Registry Number.\n\nA ``Cas`` is Albert's dictionary record for a substance. Raw-material Inventory\nItems reference these entries to declare what they are made of, pairing each\n``Cas`` with an amount (see [`CasAmount`][albert.resources.inventory.CasAmount]).\nManage entries through\n[`CasCollection`][albert.collections.cas.CasCollection] (``client.cas``): most fields\nare populated by Albert, so you typically only build a ``Cas`` from a registry\n``number`` when creating a new entry.\n\n!!! example\n    ```python\n    from albert.resources.cas import Cas\n    # Build a CAS entry to register a new substance\n    cas = Cas(number=\"7727-37-9\")\n    ```",
      "properties": {
        "status": {
          "anyOf": [
            {
              "$ref": "#/$defs/Status"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The status of the resource, optional."
        },
        "Created": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the creation of the resource, optional."
        },
        "Updated": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the update of the resource, optional."
        },
        "number": {
          "description": "The CAS number.",
          "title": "Number",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Name of the CAS.",
          "title": "Name"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The description or name of the CAS.",
          "title": "Description"
        },
        "notes": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Notes related to the CAS.",
          "title": "Notes"
        },
        "category": {
          "anyOf": [
            {
              "$ref": "#/$defs/CasCategory"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The category of the CAS."
        },
        "casSmiles": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "CAS SMILES notation.",
          "title": "Cassmiles"
        },
        "inchiKey": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "InChIKey of the CAS.",
          "title": "Inchikey"
        },
        "iUpacName": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "IUPAC name of the CAS.",
          "title": "Iupacname"
        },
        "albertId": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The AlbertID of the CAS.",
          "title": "Albertid"
        },
        "hazards": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/Hazard"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Hazards associated with the CAS.",
          "title": "Hazards"
        },
        "wgk": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "German Water Hazard Class (WGK) number.",
          "title": "Wgk"
        },
        "ecListNo": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "European Community (EC) number.",
          "title": "Eclistno"
        },
        "type": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Internal classification_type reference.",
          "title": "Type"
        },
        "classificationType": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Classification type of the CAS.",
          "title": "Classificationtype"
        },
        "order": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "CAS order.",
          "title": "Order"
        },
        "Metadata": {
          "additionalProperties": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "integer"
              },
              {
                "type": "string"
              },
              {
                "$ref": "#/$defs/EntityLinkWithName"
              },
              {
                "$ref": "#/$defs/EntityLink"
              },
              {
                "items": {
                  "anyOf": [
                    {
                      "$ref": "#/$defs/EntityLinkWithName"
                    },
                    {
                      "$ref": "#/$defs/EntityLink"
                    }
                  ]
                },
                "type": "array"
              }
            ]
          },
          "description": "Custom metadata keyed by field. Updatable.",
          "title": "Metadata",
          "type": "object"
        }
      },
      "required": [
        "number"
      ],
      "title": "Cas",
      "type": "object"
    },
    "CasAmount": {
      "description": "A single CAS constituent and its concentration within an [`InventoryItem`][albert.resources.inventory.InventoryItem].\n\nA ``CasAmount`` links one CAS number (a chemical substance identifier) to the\namount of that substance present in an inventory item, expressed as a range\n(``min`` to ``max``) with an optional ``target``. A list of these on an\n[`InventoryItem`][albert.resources.inventory.InventoryItem] gives the item's compositional breakdown.\n\nIdentify the CAS in one of two ways: pass a full [`Cas`][albert.resources.cas.Cas]\nobject as ``cas`` (its ``id``, ``number``, and ``cas_smiles`` are then copied onto\nthis amount), or pass just the CAS resource ``id`` string. Do not pass both.\n\n!!! example\n    ```python\n    from albert.resources.inventory import CasAmount\n\n    # Reference an existing CAS resource by its Albert ID, 10-30% concentration\n    amount = CasAmount(min=10.0, max=30.0, id=\"CAS1\")\n    ```",
      "properties": {
        "min": {
          "description": "The minimum amount (concentration) of the CAS in the item.",
          "title": "Min",
          "type": "number"
        },
        "max": {
          "description": "The maximum amount (concentration) of the CAS in the item.",
          "title": "Max",
          "type": "number"
        },
        "inventoryValue": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The target amount of the CAS in the item. Serialized as ``inventoryValue``.",
          "title": "Inventoryvalue"
        },
        "id": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The Albert ID of the CAS resource this amount represents. Provide either a ``cas`` object or an ``id``; when ``cas`` is given, this is set from it.",
          "title": "Id"
        },
        "casCategory": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Whether the CAS is a trade secret.",
          "title": "Cascategory"
        },
        "inventoryFunction": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/ListItem"
                  },
                  {
                    "$ref": "#/$defs/EntityLink"
                  },
                  {
                    "type": "string"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Business-controlled functions associated with the CAS in this inventory context (e.g. what role the substance plays). Values come from a managed list.",
          "title": "Inventoryfunction"
        },
        "type": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The CAS type. Can be retrieved from the CAS collection before construction.",
          "title": "Type"
        },
        "classificationType": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The EU classification source for the CAS: harmonized, notified, or REACH.",
          "title": "Classificationtype"
        },
        "substanceId": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The substance ID linked to this CAS entry.",
          "title": "Substanceid"
        },
        "cas": {
          "anyOf": [
            {
              "$ref": "#/$defs/Cas"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The full CAS object associated with this amount. Read-only after init; excluded from serialization. Provide either a ``cas`` or an ``id``."
        },
        "casSmiles": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The SMILES string of the CAS resource. Read-only; set from the ``cas`` object.",
          "title": "Cassmiles"
        },
        "number": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The CAS number (e.g. ``\"7440-32-6\"``). Read-only; set from the ``cas`` object.",
          "title": "Number"
        },
        "Created": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit metadata for creation. Read-only."
        },
        "Updated": {
          "anyOf": [
            {
              "$ref": "#/$defs/CasAuditFieldsWithEmail"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit metadata for the last update. Read-only. See Also --------"
        }
      },
      "required": [
        "min",
        "max"
      ],
      "title": "CasAmount",
      "type": "object"
    },
    "CasAuditFieldsWithEmail": {
      "description": "The audit fields for a CAS resource with email",
      "properties": {
        "by": {
          "default": null,
          "title": "By",
          "type": "string"
        },
        "byName": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Byname"
        },
        "at": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "At"
        },
        "email": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Email"
        }
      },
      "title": "CasAuditFieldsWithEmail",
      "type": "object"
    },
    "CasCategory": {
      "enum": [
        "User",
        "Verisk",
        "TSCA - Public",
        "TSCA - Private",
        "not TSCA",
        "CAS linked to External Database",
        "Unknown (Trade Secret)",
        "CL_Inventory Upload"
      ],
      "title": "CasCategory",
      "type": "string"
    },
    "Company": {
      "description": "A manufacturing company or supplier tracked in Albert.\n\nA Company is the organization that makes or supplies a material. It is the\n``company`` linked on raw-material inventory items: each raw material points\nback to the Company that manufactures it (see\n[`InventoryItem`][albert.resources.inventory.InventoryItem]). Companies are managed\nthrough [`CompanyCollection`][albert.collections.companies.CompanyCollection], accessed as\n``client.companies``.\n\nCompanies are identified by a Company ID (format ``COM...``). A Company is\ntypically minimal: a name plus its assigned ID. You construct one directly\n(``Company(name=\"Acme Chemicals\")``) to create it or to attach it to an\ninventory item.\n\n!!! example\n    ```python\n    from albert.resources.companies import Company\n\n    # Build a company to create or attach to an inventory item\n    company = Company(name=\"Acme Chemicals\")\n    ```",
      "properties": {
        "status": {
          "anyOf": [
            {
              "$ref": "#/$defs/Status"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The status of the resource, optional."
        },
        "Created": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the creation of the resource, optional."
        },
        "Updated": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the update of the resource, optional."
        },
        "name": {
          "description": "The company's name. This is the primary identifier used when searching for or creating a company.",
          "title": "Name",
          "type": "string"
        },
        "albertId": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The Albert Company ID (format ``COM...``). ``None`` until the company is created in or retrieved from Albert.",
          "title": "Albertid"
        },
        "distance": {
          "anyOf": [
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Search-relevance score returned when the company comes back as a search result. Read-only; not set on companies you build yourself.",
          "title": "Distance"
        }
      },
      "required": [
        "name"
      ],
      "title": "Company",
      "type": "object"
    },
    "EntityLink": {
      "properties": {
        "id": {
          "title": "Id",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Name"
        },
        "category": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Category"
        }
      },
      "required": [
        "id"
      ],
      "title": "EntityLink",
      "type": "object"
    },
    "EntityLinkWithName": {
      "description": "EntityLink that includes the name field in serialization.",
      "properties": {
        "id": {
          "title": "Id",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Name"
        },
        "category": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Category"
        }
      },
      "required": [
        "id"
      ],
      "title": "EntityLinkWithName",
      "type": "object"
    },
    "Hazard": {
      "description": "A single GHS hazard classification associated with a CAS substance.\n\nHazards are read from the CAS record; a [`Cas`][albert.resources.cas.Cas] may carry a list of them.",
      "properties": {
        "subCategory": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Hazard subcategory",
          "title": "Subcategory"
        },
        "hCode": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Hazard code",
          "title": "Hcode"
        },
        "category": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "number"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Hazard category",
          "title": "Category"
        },
        "class": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Hazard classification",
          "title": "Class"
        },
        "hCodeText": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Hazard code text",
          "title": "Hcodetext"
        }
      },
      "title": "Hazard",
      "type": "object"
    },
    "InventoryCategory": {
      "description": "The kind of material an [`InventoryItem`][albert.resources.inventory.InventoryItem] represents.\n\nEvery inventory item belongs to exactly one category, which determines how it\nis used across the platform and which fields are relevant to it.\n\nAttributes\n----------\nRAW_MATERIALS : str\n    A purchased substance used as an ingredient (e.g. a solvent or pigment).\n    Typically linked to a manufacturing ``company`` and one or more CAS numbers.\nCONSUMABLES : str\n    Lab supplies consumed during work (e.g. gloves, vials, filters).\nEQUIPMENT : str\n    Instruments and apparatus (e.g. a balance or spectrometer).\nFORMULAS : str\n    A mixture designed in Albert through a Worksheet. Formulas are not created\n    through the inventory collection; they are produced by the Worksheet\n    collection ([`WorksheetCollection`][albert.collections.worksheets.WorksheetCollection]).",
      "enum": [
        "RawMaterials",
        "Consumables",
        "Equipment",
        "Formulas"
      ],
      "title": "InventoryCategory",
      "type": "string"
    },
    "InventoryItem": {
      "description": "A catalog entry for a material tracked in Albert.\n\nAn ``InventoryItem`` is the canonical record for a raw material, consumable,\npiece of equipment, or formula. Its [`InventoryCategory`][albert.resources.inventory.InventoryCategory] determines how it\nis used across the platform, and once saved it is referenced everywhere by its\nInventory ID (format ``INV...``, e.g. ``\"INVA9999999\"``). Raw materials are typically\nlinked to a manufacturing ``company`` and a compositional breakdown of CAS\namounts. Formula items are designed in Worksheets rather than created here (the\n[`create`][albert.collections.inventory.InventoryCollection.create] method rejects\nFormula items), and a Formula requires a ``project_id``.\n\nItems are managed through\n[`InventoryCollection`][albert.collections.inventory.InventoryCollection] (``client.inventory``).\n\n!!! example\n    ```python\n    from albert.resources.inventory import InventoryItem, InventoryCategory\n\n    item = InventoryItem(\n        name=\"Titanium Dioxide\",\n        category=InventoryCategory.RAW_MATERIALS,\n        company=\"Acme Chemicals\",\n    )\n    ```",
      "properties": {
        "status": {
          "anyOf": [
            {
              "$ref": "#/$defs/Status"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The status of the resource, optional."
        },
        "Created": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the creation of the resource, optional."
        },
        "Updated": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the update of the resource, optional."
        },
        "Tags": {
          "anyOf": [
            {
              "items": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Tag"
                  },
                  {
                    "$ref": "#/$defs/EntityLink"
                  }
                ]
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A list of Tag objects or strings representing tags.",
          "title": "Tags"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The name of the item.",
          "title": "Name"
        },
        "albertId": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The Albert Inventory ID (format ``INV...``). Set when the item is retrieved from or created in Albert. Serialized as ``albertId``.",
          "title": "Albertid"
        },
        "description": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "A free-text description of the item.",
          "title": "Description"
        },
        "category": {
          "$ref": "#/$defs/InventoryCategory",
          "description": "The kind of material this item represents. Required. One of ``RawMaterials``, ``Consumables``, ``Equipment``, or ``Formulas``."
        },
        "unitCategory": {
          "anyOf": [
            {
              "$ref": "#/$defs/InventoryUnitCategory"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The dimension the item is measured in (mass, volume, length, pressure, or units). If not supplied, it defaults from ``category``: mass for raw materials and formulas, units for equipment and consumables."
        },
        "class": {
          "anyOf": [
            {
              "$ref": "#/$defs/SecurityClass"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The access/security class of the item (e.g. confidential, shared, restricted)."
        },
        "Company": {
          "anyOf": [
            {
              "$ref": "#/$defs/Company"
            },
            {
              "$ref": "#/$defs/EntityLink"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The manufacturing Company associated with the item (links to the Company collection). Accepts a [`Company`][albert.resources.companies.Company] or a name string; a string is turned into a Company that is first-or-created on save.",
          "title": "Company"
        },
        "minimum": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/InventoryMinimum"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Per-Location reorder thresholds for the item. See [`InventoryMinimum`][albert.resources.inventory.InventoryMinimum].",
          "title": "Minimum"
        },
        "alias": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "An alternate name for the item.",
          "title": "Alias"
        },
        "Cas": {
          "anyOf": [
            {
              "items": {
                "$ref": "#/$defs/CasAmount"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The item's compositional breakdown as CAS amounts. See [`CasAmount`][albert.resources.inventory.CasAmount].",
          "title": "Cas"
        },
        "isFormulaOverride": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Whether the substance/CAS-level breakdown for this formula has been overridden from the auto-calculated value; commonly set to indicate the formula is not a non-reactive homogeneous mixture.",
          "title": "Isformulaoverride"
        },
        "Metadata": {
          "anyOf": [
            {
              "additionalProperties": {
                "anyOf": [
                  {
                    "type": "number"
                  },
                  {
                    "type": "integer"
                  },
                  {
                    "type": "string"
                  },
                  {
                    "$ref": "#/$defs/EntityLinkWithName"
                  },
                  {
                    "$ref": "#/$defs/EntityLink"
                  },
                  {
                    "items": {
                      "anyOf": [
                        {
                          "$ref": "#/$defs/EntityLinkWithName"
                        },
                        {
                          "$ref": "#/$defs/EntityLink"
                        }
                      ]
                    },
                    "type": "array"
                  }
                ]
              },
              "type": "object"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Custom metadata fields. Allowed keys are defined by the workspace's CustomFields configuration.",
          "title": "Metadata"
        },
        "parentId": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The parent Project ID. Required for Formulas. Serialized as ``parentId``.",
          "title": "Parentid"
        },
        "ACL": {
          "description": "Access-control entries governing who can act on the item.",
          "items": {
            "$ref": "#/$defs/ACL"
          },
          "title": "Acl",
          "type": "array"
        },
        "onHand": {
          "default": 0.0,
          "description": "Total amount currently on hand across all lots. Read-only.",
          "title": "Onhand",
          "type": "number"
        },
        "TaskConfig": {
          "anyOf": [
            {
              "items": {
                "additionalProperties": true,
                "type": "object"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Task configuration associated with the item. Read-only.",
          "title": "Taskconfig"
        },
        "formulaId": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The formula ID for a formula item. Read-only.",
          "title": "Formulaid"
        },
        "Symbols": {
          "anyOf": [
            {
              "items": {
                "additionalProperties": true,
                "type": "object"
              },
              "type": "array"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Hazard/pictogram symbols associated with the item. Read-only.",
          "title": "Symbols"
        },
        "unNumber": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The UN hazardous-material number, when applicable. Read-only.",
          "title": "Unnumber"
        },
        "recentAttachmentId": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The ID of the most recent attachment on the item. Read-only. See Also --------",
          "title": "Recentattachmentid"
        }
      },
      "required": [
        "category"
      ],
      "title": "InventoryItem",
      "type": "object"
    },
    "InventoryMinimum": {
      "description": "A reorder threshold: the minimum stock of an [`InventoryItem`][albert.resources.inventory.InventoryItem] to keep at a Location.\n\nEach entry pairs one Location with the minimum quantity of an item that must be\nkept on hand there. An [`InventoryItem`][albert.resources.inventory.InventoryItem] may carry several of these, one per\nLocation. Identify the Location either by passing a full\n[`Location`][albert.resources.locations.Location] object as ``location`` (its ``id`` is\nthen copied onto ``id``), or by passing the location ``id`` string directly. Provide\none or the other, not both.\n\n!!! example\n    ```python\n    from albert.resources.inventory import InventoryMinimum\n\n    minimum = InventoryMinimum(id=\"LOC9999999\", minimum=500)\n    ```",
      "properties": {
        "id": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The Albert ID of the Location this minimum applies to. Provide either a ``location`` or an ``id``; when ``location`` is given, this is set from it.",
          "title": "Id"
        },
        "location": {
          "anyOf": [
            {
              "$ref": "#/$defs/Location"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The Location object this minimum applies to. Excluded from serialization. Provide either a ``location`` or an ``id``."
        },
        "minimum": {
          "description": "The minimum amount of the item that must be kept in stock at the Location. Must be between 0 and 1e15. See Also --------",
          "maximum": 1000000000000000,
          "minimum": 0,
          "title": "Minimum",
          "type": "number"
        }
      },
      "required": [
        "minimum"
      ],
      "title": "InventoryMinimum",
      "type": "object"
    },
    "InventoryUnitCategory": {
      "description": "The dimension of the unit an [`InventoryItem`][albert.resources.inventory.InventoryItem] is measured and stocked in.\n\nDetermines how quantities on hand and in formulas are interpreted. When not\nsupplied, the category defaults based on [`InventoryCategory`][albert.resources.inventory.InventoryCategory]: ``MASS``\nfor raw materials and formulas, ``UNITS`` for equipment and consumables.\n\nAttributes\n----------\nMASS : str\n    Measured by mass (e.g. grams, kilograms).\nVOLUME : str\n    Measured by volume (e.g. milliliters, liters).\nLENGTH : str\n    Measured by length (e.g. meters).\nPRESSURE : str\n    Measured by pressure.\nUNITS : str\n    Counted as discrete units (e.g. each item).",
      "enum": [
        "mass",
        "volume",
        "length",
        "pressure",
        "units"
      ],
      "title": "InventoryUnitCategory",
      "type": "string"
    },
    "ListItem": {
      "description": "A single allowed value in a configurable list of options.\n\nList items back the choices offered by ``list``-type custom fields (e.g.\ndropdown options) and other fixed option sets in Albert. A\n[`CustomField`][albert.resources.custom_fields.CustomField] with\n[`LIST`][albert.resources.custom_fields.FieldType.LIST] defines a list (keyed\nby ``list_type``, typically the field's name); its selectable options are\n``ListItem`` records with a matching ``list_type``. Managed through\n[`ListsCollection`][albert.collections.lists.ListsCollection] (``client.lists``).\n\n!!! example\n    ```python\n    from albert.resources.lists import ListItem, ListItemCategory\n    item = ListItem(name=\"In Progress\", category=ListItemCategory.USER_DEFINED)\n    ```",
      "properties": {
        "status": {
          "anyOf": [
            {
              "$ref": "#/$defs/Status"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The status of the resource, optional."
        },
        "Created": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the creation of the resource, optional."
        },
        "Updated": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the update of the resource, optional."
        },
        "name": {
          "description": "The display name of the list item (the option value).",
          "title": "Name",
          "type": "string"
        },
        "albertId": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The Albert ID of the list item. Set when the item is retrieved from or created in Albert.",
          "title": "Albertid"
        },
        "category": {
          "anyOf": [
            {
              "$ref": "#/$defs/ListItemCategory"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The category of the list item. Allowed values are ``businessDefined``, ``userDefined``, ``projects``, ``extensions``, and ``inventory``."
        },
        "listType": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The list this item belongs to. For a list-type custom field this is typically the field's name (see [`CustomField`][albert.resources.custom_fields.CustomField]). For built-in categories the allowed values are ``projectState`` for ``projects``, ``extensions`` for ``extensions``, and ``casCategory`` or ``inventoryFunction`` for ``inventory``.",
          "title": "Listtype"
        }
      },
      "required": [
        "name"
      ],
      "title": "ListItem",
      "type": "object"
    },
    "ListItemCategory": {
      "description": "The category a list item belongs to, which governs its allowed list types.\n\nAttributes\n----------\nBUSINESS_DEFINED : str\n    Predefined values managed at the business/organization level.\nUSER_DEFINED : str\n    Custom values defined by users.\nPROJECTS : str\n    Values used by projects (e.g. project states).\nEXTENSIONS : str\n    Values used by extensions.\nINVENTORY : str\n    Values used by inventory (e.g. CAS categories or inventory functions).",
      "enum": [
        "businessDefined",
        "userDefined",
        "projects",
        "extensions",
        "inventory"
      ],
      "title": "ListItemCategory",
      "type": "string"
    },
    "Location": {
      "description": "A physical lab or site location in Albert.\n\nLocations are referenced by Tasks and Inventory Items to record where an\nactivity is performed or where a material lives, and each Location can hold\none or more Storage Locations\n([`StorageLocation`][albert.resources.storage_locations.StorageLocation]). Managed\nthrough [`LocationCollection`][albert.collections.locations.LocationCollection].\n\n!!! example\n    ```python\n    from albert.resources.locations import Location\n    location = Location(\n        name=\"Boston Lab\",\n        latitude=42.3601,\n        longitude=-71.0589,\n        address=\"1 Main St\",\n        country=\"US\",\n    )\n    ```",
      "properties": {
        "status": {
          "anyOf": [
            {
              "$ref": "#/$defs/Status"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The status of the resource, optional."
        },
        "Created": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the creation of the resource, optional."
        },
        "Updated": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the update of the resource, optional."
        },
        "name": {
          "description": "The human-readable name of the location.",
          "title": "Name",
          "type": "string"
        },
        "albertId": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The Albert ID of the location. Assigned by Albert and populated once the location has been created or retrieved.",
          "title": "Albertid"
        },
        "latitude": {
          "description": "The latitude of the location, in decimal degrees.",
          "title": "Latitude",
          "type": "number"
        },
        "longitude": {
          "description": "The longitude of the location, in decimal degrees.",
          "title": "Longitude",
          "type": "number"
        },
        "address": {
          "description": "The street address of the location.",
          "title": "Address",
          "type": "string"
        },
        "country": {
          "anyOf": [
            {
              "maxLength": 2,
              "minLength": 2,
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The two-letter country code of the location (for example, ``\"US\"``).",
          "title": "Country"
        }
      },
      "required": [
        "name",
        "latitude",
        "longitude",
        "address"
      ],
      "title": "Location",
      "type": "object"
    },
    "SecurityClass": {
      "description": "The security (access control) class of a resource.\n\nAttributes\n----------\nSHARED : str\n    Accessible to all members of the tenant.\nRESTRICTED : str\n    Access is restricted to specific teams or users.\nCONFIDENTIAL : str\n    Access is limited to designated users only.\nPRIVATE : str\n    Visible only to the owner. Used by Projects.",
      "enum": [
        "shared",
        "restricted",
        "confidential",
        "private"
      ],
      "title": "SecurityClass",
      "type": "string"
    },
    "Status": {
      "description": "The status of a resource.\n\nAttributes\n----------\nACTIVE : str\n    The resource is fully operational and visible in normal operations.\nINACTIVE : str\n    The resource is hidden from normal operations and disabled from use.",
      "enum": [
        "active",
        "inactive"
      ],
      "title": "Status",
      "type": "string"
    },
    "Tag": {
      "description": "A freeform text label used to categorize and connect entities.\n\nTags are shared by name across the platform and can be applied to inventory\nitems, companies, tasks, and other records to group and filter them. Managed\nthrough [`TagCollection`][albert.collections.tags.TagCollection] (``client.tags``);\nthe usual entry point is [`get_or_create`][albert.collections.tags.TagCollection.get_or_create].\n\n!!! example\n    ```python\n    from albert.resources.tags import Tag\n    tag = Tag(tag=\"high-priority\")\n    ```\nMethods\n-------\nfrom_string(tag) -> Tag\n    Build a Tag from its name string.",
      "properties": {
        "status": {
          "anyOf": [
            {
              "$ref": "#/$defs/Status"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The status of the resource, optional."
        },
        "Created": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the creation of the resource, optional."
        },
        "Updated": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the update of the resource, optional."
        },
        "name": {
          "description": "The name of the tag (its text label).",
          "title": "Name",
          "type": "string"
        },
        "albertId": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The Albert ID of the tag (format ``TAG...``). Set when the tag is retrieved from or created in Albert. Methods ------- from_string(tag) -> Tag Build a Tag from its name string.",
          "title": "Albertid"
        }
      },
      "required": [
        "name"
      ],
      "title": "Tag",
      "type": "object"
    }
  },
  "description": "One ingredient and its amount within a formulation.\n\nA Component pairs an inventory item ([`InventoryItem`][albert.resources.inventory.InventoryItem])\nwith the amount of it used in a formulation. Components are the input to\n[`add_formulation`][albert.resources.sheets.Sheet.add_formulation] and [`add_components_to_formulation`][albert.resources.sheets.Sheet.add_components_to_formulation],\nwhich place each ingredient's amount into the appropriate Cell of a\nformulation Column. Provide either ``inventory_item`` or ``inventory_id``;\nwhen ``inventory_item`` is given, ``inventory_id`` is populated from it\nautomatically.\n\n!!! example\n    ```python\n    from albert.resources.sheets import Component\n    component = Component(inventory_id=\"INVA9999999\", amount=42.0)\n    ```",
  "properties": {
    "status": {
      "anyOf": [
        {
          "$ref": "#/$defs/Status"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The status of the resource, optional."
    },
    "Created": {
      "anyOf": [
        {
          "$ref": "#/$defs/AuditFields"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Audit fields for the creation of the resource, optional."
    },
    "Updated": {
      "anyOf": [
        {
          "$ref": "#/$defs/AuditFields"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Audit fields for the update of the resource, optional."
    },
    "inventory_item": {
      "anyOf": [
        {
          "$ref": "#/$defs/InventoryItem"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The inventory item in the component. Optional when ``inventory_id`` is provided."
    },
    "inventory_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The inventory ID backing the component (format ``INV...``). Automatically populated from ``inventory_item`` when present; required when ``inventory_item`` is omitted.",
      "title": "Inventory Id"
    },
    "amount": {
      "description": "The amount of the inventory item in the formulation.",
      "title": "Amount",
      "type": "number"
    },
    "min_value": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The minimum allowed amount for the component. Optional.",
      "title": "Min Value"
    },
    "max_value": {
      "anyOf": [
        {
          "type": "number"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The maximum allowed amount for the component. Optional.",
      "title": "Max Value"
    }
  },
  "required": [
    "amount"
  ],
  "title": "Component",
  "type": "object"
}

Fields:

Validators:

  • _ensure_inventory_reference

inventory_item

inventory_item: InventoryItem | None = None

The inventory item in the component. Optional when inventory_id is provided.

inventory_id

inventory_id: InventoryId | None = None

The inventory ID backing the component (format INV...). Automatically populated from inventory_item when present; required when inventory_item is omitted.

amount

amount: float

The amount of the inventory item in the formulation.

min_value

min_value: float | None = None

The minimum allowed amount for the component. Optional.

max_value

max_value: float | None = None

The maximum allowed amount for the component. Optional.

cell

cell

inventory_item_id

inventory_item_id: InventoryId

DesignState

Bases: BaseResource

The display state of a Design section within a Sheet.

Show JSON schema:
{
  "$defs": {
    "AuditFields": {
      "description": "The audit fields for a resource",
      "properties": {
        "by": {
          "default": null,
          "title": "By",
          "type": "string"
        },
        "byName": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Byname"
        },
        "at": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "At"
        }
      },
      "title": "AuditFields",
      "type": "object"
    },
    "Status": {
      "description": "The status of a resource.\n\nAttributes\n----------\nACTIVE : str\n    The resource is fully operational and visible in normal operations.\nINACTIVE : str\n    The resource is hidden from normal operations and disabled from use.",
      "enum": [
        "active",
        "inactive"
      ],
      "title": "Status",
      "type": "string"
    }
  },
  "description": "The display state of a Design section within a Sheet.",
  "properties": {
    "status": {
      "anyOf": [
        {
          "$ref": "#/$defs/Status"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The status of the resource, optional."
    },
    "Created": {
      "anyOf": [
        {
          "$ref": "#/$defs/AuditFields"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Audit fields for the creation of the resource, optional."
    },
    "Updated": {
      "anyOf": [
        {
          "$ref": "#/$defs/AuditFields"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Audit fields for the update of the resource, optional."
    },
    "collapsed": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        }
      ],
      "default": false,
      "description": "Whether the Design section is collapsed in the Sheet view. Default is False.",
      "title": "Collapsed"
    }
  },
  "title": "DesignState",
  "type": "object"
}

Fields:

collapsed

collapsed: bool | None = False

Whether the Design section is collapsed in the Sheet view. Default is False.

RowConfig

Bases: BaseAlbertModel

Configuration for an APP or location-type row.

Show JSON schema:
{
  "description": "Configuration for an APP or location-type row.",
  "properties": {
    "option": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Option"
    },
    "value": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Value"
    }
  },
  "title": "RowConfig",
  "type": "object"
}

Fields:

option

option: str | None = None

value

value: str | None = None

RowGroup

Bases: BaseAlbertModel

A named group of rows within a Design.

Show JSON schema:
{
  "description": "A named group of rows within a Design.",
  "properties": {
    "rowId": {
      "title": "Rowid",
      "type": "string"
    },
    "name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Name"
    },
    "child_row_ids": {
      "items": {
        "type": "string"
      },
      "title": "Child Row Ids",
      "type": "array"
    }
  },
  "required": [
    "rowId"
  ],
  "title": "RowGroup",
  "type": "object"
}

Fields:

row_id

row_id: str

name

name: str | None = None

child_row_ids

child_row_ids: list[str]

Design

Design(**data)

Bases: BaseSessionResource

One section of a Sheet, backing the grid for a single DesignType.

A Sheet is made up of stacked sections (Product Design, Process Design, Results, and Apps) and each section is a Design. Designs are largely an internal detail: most work is done through the parent Sheet, which exposes its Designs as product_design, result_design, app_design, and process_design. A Design is a live grid element that carries the session and lazily loads its rows, columns, and grid on first access.

Methods:

Name Description
group_rows

Create a named row group within this design.

get_groups

Get all row groups in this design.

Show JSON schema:
{
  "$defs": {
    "AuditFields": {
      "description": "The audit fields for a resource",
      "properties": {
        "by": {
          "default": null,
          "title": "By",
          "type": "string"
        },
        "byName": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Byname"
        },
        "at": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "At"
        }
      },
      "title": "AuditFields",
      "type": "object"
    },
    "DesignState": {
      "description": "The display state of a Design section within a Sheet.",
      "properties": {
        "status": {
          "anyOf": [
            {
              "$ref": "#/$defs/Status"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The status of the resource, optional."
        },
        "Created": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the creation of the resource, optional."
        },
        "Updated": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the update of the resource, optional."
        },
        "collapsed": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": false,
          "description": "Whether the Design section is collapsed in the Sheet view. Default is False.",
          "title": "Collapsed"
        }
      },
      "title": "DesignState",
      "type": "object"
    },
    "DesignType": {
      "description": "The section of a Sheet that a Design represents.\n\nA Sheet is organized into stacked sections, each backed by a Design\n([`Design`][albert.resources.sheets.Design]). The type identifies which section:\n\n- ``PRODUCTS``: Product Design, where formulations are built.\n- ``PROCESS``: Process Design.\n- ``RESULTS``: Results, holding Property Tasks and their data.\n- ``APPS``: Apps, holding insights, reporting, and notes.",
      "enum": [
        "apps",
        "products",
        "results",
        "process",
        "reagents"
      ],
      "title": "DesignType",
      "type": "string"
    },
    "Status": {
      "description": "The status of a resource.\n\nAttributes\n----------\nACTIVE : str\n    The resource is fully operational and visible in normal operations.\nINACTIVE : str\n    The resource is hidden from normal operations and disabled from use.",
      "enum": [
        "active",
        "inactive"
      ],
      "title": "Status",
      "type": "string"
    }
  },
  "description": "One section of a Sheet, backing the grid for a single [`DesignType`][albert.resources.sheets.DesignType].\n\nA Sheet is made up of stacked sections (Product Design, Process Design,\nResults, and Apps) and each section is a Design. Designs are largely an\ninternal detail: most work is done through the parent [`Sheet`][albert.resources.sheets.Sheet], which\nexposes its Designs as [`product_design`][albert.resources.sheets.Sheet.product_design],\n[`result_design`][albert.resources.sheets.Sheet.result_design], [`app_design`][albert.resources.sheets.Sheet.app_design], and\n[`process_design`][albert.resources.sheets.Sheet.process_design]. A Design is a live grid element that carries the\nsession and lazily loads its rows, columns, and grid on first access.\nMethods\n-------\ngroup_rows(name, child_row_ids, ...) -> RowGroup\n    Create a named row group within this design.\nget_groups(refresh=False) -> list[RowGroup]\n    Get all row groups in this design.",
  "properties": {
    "status": {
      "anyOf": [
        {
          "$ref": "#/$defs/Status"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The status of the resource, optional."
    },
    "Created": {
      "anyOf": [
        {
          "$ref": "#/$defs/AuditFields"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Audit fields for the creation of the resource, optional."
    },
    "Updated": {
      "anyOf": [
        {
          "$ref": "#/$defs/AuditFields"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Audit fields for the update of the resource, optional."
    },
    "state": {
      "anyOf": [
        {
          "$ref": "#/$defs/DesignState"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The display state of the design. Optional. Default is None."
    },
    "albertId": {
      "description": "The Albert ID of the design.",
      "title": "Albertid",
      "type": "string"
    },
    "designType": {
      "anyOf": [
        {
          "$ref": "#/$defs/DesignType"
        },
        {
          "type": "string"
        }
      ],
      "description": "The section of the Sheet this design backs. See [`DesignType`][albert.resources.sheets.DesignType]. Unknown legacy/tenant values parse as plain strings.",
      "title": "Designtype"
    }
  },
  "required": [
    "albertId",
    "designType"
  ],
  "title": "Design",
  "type": "object"
}

Fields:

Source code in src/albert/core/shared/models/base.py
def __init__(self, **data):
    super().__init__(**data)
    self._session = data.get("session")

state

state: DesignState | None = None

The display state of the design. Optional. Default is None.

id

id: str

The Albert ID of the design.

design_type

design_type: DesignType | str

The section of the Sheet this design backs. See DesignType. Unknown legacy/tenant values parse as plain strings.

sheet

sheet

grid

grid

columns

columns: list[Column]

rows

rows: list[Row]

group_rows

group_rows(
    *,
    name: str,
    child_row_ids: list[str],
    reference_id: str | None = None,
    position: str = "above",
) -> RowGroup

Create a row group within this design.

Example

design = sheet.product_design
group = design.group_rows(name="Solvents", child_row_ids=["ROW2", "ROW3"])

Parameters:

Name Type Description Default
name str

The name of the row group.

required
child_row_ids list[str]

Row IDs to include in the group. Must contain at least one ID.

required
reference_id str

The reference row ID for insertion. Defaults to the first child row.

None
position str

Position relative to reference_id. One of "above" or "below". Default is "above".

'above'

Returns:

Type Description
RowGroup

The created row group.

Source code in src/albert/resources/sheets.py
def group_rows(
    self,
    *,
    name: str,
    child_row_ids: list[str],
    reference_id: str | None = None,
    position: str = "above",
) -> RowGroup:
    """Create a row group within this design.

    !!! example
        ```python
        design = sheet.product_design
        group = design.group_rows(name="Solvents", child_row_ids=["ROW2", "ROW3"])
        ```

    Parameters
    ----------
    name : str
        The name of the row group.
    child_row_ids : list[str]
        Row IDs to include in the group. Must contain at least one ID.
    reference_id : str, optional
        The reference row ID for insertion. Defaults to the first child row.
    position : str, optional
        Position relative to ``reference_id``. One of ``"above"`` or ``"below"``.
        Default is ``"above"``.

    Returns
    -------
    RowGroup
        The created row group.
    """
    if not child_row_ids:
        raise AlbertException("child_row_ids must include at least one row ID")

    seen: set[str] = set()
    ids = [x for x in child_row_ids if not (x in seen or seen.add(x))]

    if reference_id and reference_id in ids:
        ids = [reference_id] + [x for x in ids if x != reference_id]
    else:
        reference_id = ids[0]

    payload = {
        "name": name,
        "referenceId": reference_id,
        "position": position,
        "ChildRows": [{"rowId": rid} for rid in ids],
    }
    response = self.session.put(f"/api/v3/worksheet/{self.id}/designs/groups", json=payload)
    data = response.json()
    group = RowGroup(
        rowId=data.get("rowId", reference_id),
        name=data.get("name", name),
    )
    child_rows = data.get("ChildRows") or []
    group.child_row_ids = [r["rowId"] for r in child_rows if r.get("rowId")]
    if not group.child_row_ids:
        group.child_row_ids = ids

    existing = {g.row_id: g for g in (self._groups_cache or [])}
    existing[group.row_id] = group
    self._groups_cache = list(existing.values())
    self._rows = None
    return group

get_groups

get_groups(*, refresh: bool = False) -> list[RowGroup]

Get all row groups in this design.

Example

groups = sheet.product_design.get_groups()
for group in groups:
    print(group.name, group.child_row_ids)

Parameters:

Name Type Description Default
refresh bool

When True, re-fetches the group list even if cached. Default is False.

False

Returns:

Type Description
list[RowGroup]

The row groups in this design.

Source code in src/albert/resources/sheets.py
def get_groups(self, *, refresh: bool = False) -> list[RowGroup]:
    """Get all row groups in this design.

    !!! example
        ```python
        groups = sheet.product_design.get_groups()
        for group in groups:
            print(group.name, group.child_row_ids)
        ```

    Parameters
    ----------
    refresh : bool, optional
        When True, re-fetches the group list even if cached. Default is False.

    Returns
    -------
    list[RowGroup]
        The row groups in this design.
    """
    if self._groups_cache is not None and not refresh:
        return self._groups_cache

    try:
        response = self.session.get(f"/api/v3/worksheet/design/{self.id}/rows/sequence")
    except AlbertHTTPError:
        self._groups_cache = []
        return []

    seq = response.json()
    if not isinstance(seq, list):
        self._groups_cache = []
        return []

    groups: list[RowGroup] = []
    for item in seq:
        rid = item.get("rowId") or item.get("id")
        child_dicts = (
            item.get("children") or item.get("childRows") or item.get("ChildRows") or []
        )
        if rid and child_dicts:
            child_ids = [
                (c.get("rowId") or c.get("id"))
                for c in child_dicts
                if isinstance(c, dict) and (c.get("rowId") or c.get("id"))
            ]
            groups.append(RowGroup(rowId=rid, name=item.get("name"), child_row_ids=child_ids))

    self._groups_cache = groups
    return groups

SheetFormulationRef

Bases: BaseAlbertModel

A reference to a formulation in a sheet

Show JSON schema:
{
  "description": "A reference to a formulation in a sheet",
  "properties": {
    "id": {
      "description": "The Albert ID of the inventory item that is the formulation",
      "title": "Id",
      "type": "string"
    },
    "name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The name of the formulation",
      "title": "Name"
    },
    "hidden": {
      "description": "Whether the formulation is hidden",
      "title": "Hidden",
      "type": "boolean"
    }
  },
  "required": [
    "id",
    "hidden"
  ],
  "title": "SheetFormulationRef",
  "type": "object"
}

Fields:

id

id: str

The Albert ID of the inventory item that is the formulation

name

name: str | None = None

The name of the formulation

hidden

hidden: bool

Whether the formulation is hidden

Sheet

Sheet(**data)

Bases: BaseSessionResource

An interactive grid within a Worksheet where formulations are built.

A Sheet is one grid inside a Worksheet (Worksheet). It is organized into stacked sections, each a Design: Product Design (where formulations are built), Process Design, Results (Property Tasks and their data), and Apps (insights and notes). Access those sections through product_design, process_design, result_design, and app_design.

A Sheet Column can be a formulation (the most common case for the SDK), a lookup column that displays an inventory attribute, or an ingredient name. Rows typically represent ingredients (inventory items) and their amounts. Adding a formulation to a Sheet is what registers a Formula inventory item.

The Sheet is a live grid element that carries the session; its cells, columns, and rows are themselves interactive. Retrieve a Sheet from a Worksheet's sheets, then edit it in place with the methods below.

Example

from albert import Albert
client = Albert()
worksheet = client.worksheets.get_by_project_id(project_id="PROA9999999")
sheet = worksheet.sheets[0]
print(sheet.grid)

Methods:

Name Description
rename

Rename the sheet.

add_formulation

Build a formulation column from a list of components (registers a Formula).

add_components_to_formulation

Add components to an existing formulation column.

add_formulation_columns

Add one or more empty formulation columns.

add_inventory_row

Add an ingredient (inventory) row.

add_blank_row

Add a blank row.

add_lookup_row

Add a lookup row.

add_app_row

Add an application row.

add_parameter_group_row

Add a parameter group (PRG) row to Process Design.

add_blank_column

Add a blank column.

add_lookup_column

Add a lookup column.

add_function_column

Add a function column.

add_property_column

Add a property/result column.

get_column

Retrieve a column by column ID, inventory ID, or name.

update_cells

Write changed cells back to the sheet.

pin_columns

Pin columns to the left or right edge.

unpin_columns

Unpin columns.

lock_column

Lock or unlock a column.

hide_column

Hide a column.

show_column

Show a hidden column.

set_columns_width

Set the display width of columns.

delete_column

Delete a column.

delete_row

Delete a row.

Show JSON schema:
{
  "$defs": {
    "AuditFields": {
      "description": "The audit fields for a resource",
      "properties": {
        "by": {
          "default": null,
          "title": "By",
          "type": "string"
        },
        "byName": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Byname"
        },
        "at": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "At"
        }
      },
      "title": "AuditFields",
      "type": "object"
    },
    "Design": {
      "description": "One section of a Sheet, backing the grid for a single [`DesignType`][albert.resources.sheets.DesignType].\n\nA Sheet is made up of stacked sections (Product Design, Process Design,\nResults, and Apps) and each section is a Design. Designs are largely an\ninternal detail: most work is done through the parent [`Sheet`][albert.resources.sheets.Sheet], which\nexposes its Designs as [`product_design`][albert.resources.sheets.Sheet.product_design],\n[`result_design`][albert.resources.sheets.Sheet.result_design], [`app_design`][albert.resources.sheets.Sheet.app_design], and\n[`process_design`][albert.resources.sheets.Sheet.process_design]. A Design is a live grid element that carries the\nsession and lazily loads its rows, columns, and grid on first access.\nMethods\n-------\ngroup_rows(name, child_row_ids, ...) -> RowGroup\n    Create a named row group within this design.\nget_groups(refresh=False) -> list[RowGroup]\n    Get all row groups in this design.",
      "properties": {
        "status": {
          "anyOf": [
            {
              "$ref": "#/$defs/Status"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The status of the resource, optional."
        },
        "Created": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the creation of the resource, optional."
        },
        "Updated": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the update of the resource, optional."
        },
        "state": {
          "anyOf": [
            {
              "$ref": "#/$defs/DesignState"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The display state of the design. Optional. Default is None."
        },
        "albertId": {
          "description": "The Albert ID of the design.",
          "title": "Albertid",
          "type": "string"
        },
        "designType": {
          "anyOf": [
            {
              "$ref": "#/$defs/DesignType"
            },
            {
              "type": "string"
            }
          ],
          "description": "The section of the Sheet this design backs. See [`DesignType`][albert.resources.sheets.DesignType]. Unknown legacy/tenant values parse as plain strings.",
          "title": "Designtype"
        }
      },
      "required": [
        "albertId",
        "designType"
      ],
      "title": "Design",
      "type": "object"
    },
    "DesignState": {
      "description": "The display state of a Design section within a Sheet.",
      "properties": {
        "status": {
          "anyOf": [
            {
              "$ref": "#/$defs/Status"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The status of the resource, optional."
        },
        "Created": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the creation of the resource, optional."
        },
        "Updated": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the update of the resource, optional."
        },
        "collapsed": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": false,
          "description": "Whether the Design section is collapsed in the Sheet view. Default is False.",
          "title": "Collapsed"
        }
      },
      "title": "DesignState",
      "type": "object"
    },
    "DesignType": {
      "description": "The section of a Sheet that a Design represents.\n\nA Sheet is organized into stacked sections, each backed by a Design\n([`Design`][albert.resources.sheets.Design]). The type identifies which section:\n\n- ``PRODUCTS``: Product Design, where formulations are built.\n- ``PROCESS``: Process Design.\n- ``RESULTS``: Results, holding Property Tasks and their data.\n- ``APPS``: Apps, holding insights, reporting, and notes.",
      "enum": [
        "apps",
        "products",
        "results",
        "process",
        "reagents"
      ],
      "title": "DesignType",
      "type": "string"
    },
    "SheetFormulationRef": {
      "description": "A reference to a formulation in a sheet",
      "properties": {
        "id": {
          "description": "The Albert ID of the inventory item that is the formulation",
          "title": "Id",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The name of the formulation",
          "title": "Name"
        },
        "hidden": {
          "description": "Whether the formulation is hidden",
          "title": "Hidden",
          "type": "boolean"
        }
      },
      "required": [
        "id",
        "hidden"
      ],
      "title": "SheetFormulationRef",
      "type": "object"
    },
    "Status": {
      "description": "The status of a resource.\n\nAttributes\n----------\nACTIVE : str\n    The resource is fully operational and visible in normal operations.\nINACTIVE : str\n    The resource is hidden from normal operations and disabled from use.",
      "enum": [
        "active",
        "inactive"
      ],
      "title": "Status",
      "type": "string"
    }
  },
  "description": "An interactive grid within a Worksheet where formulations are built.\n\nA Sheet is one grid inside a Worksheet ([`Worksheet`][albert.resources.worksheets.Worksheet]).\nIt is organized into stacked sections, each a [`Design`][albert.resources.sheets.Design]: Product Design\n(where formulations are built), Process Design, Results (Property Tasks and\ntheir data), and Apps (insights and notes). Access those sections through\n[`product_design`][albert.resources.sheets.Sheet.product_design], [`process_design`][albert.resources.sheets.Sheet.process_design], [`result_design`][albert.resources.sheets.Sheet.result_design], and\n[`app_design`][albert.resources.sheets.Sheet.app_design].\n\nA Sheet Column can be a formulation (the most common case for the SDK), a\nlookup column that displays an inventory attribute, or an ingredient name.\nRows typically represent ingredients (inventory items) and their amounts.\nAdding a formulation to a Sheet is what registers a Formula inventory item.\n\nThe Sheet is a live grid element that carries the session; its cells, columns,\nand rows are themselves interactive. Retrieve a Sheet from a Worksheet's\n[`sheets`][albert.resources.worksheets.Worksheet.sheets], then edit it in place\nwith the methods below.\n\n!!! example\n    ```python\n    from albert import Albert\n    client = Albert()\n    worksheet = client.worksheets.get_by_project_id(project_id=\"PROA9999999\")\n    sheet = worksheet.sheets[0]\n    print(sheet.grid)\n    ```\nMethods\n-------\nrename(new_name) -> Sheet\n    Rename the sheet.\nadd_formulation(formulation_name, components, ...) -> Column\n    Build a formulation column from a list of components (registers a Formula).\nadd_components_to_formulation(components, ...) -> Column\n    Add components to an existing formulation column.\nadd_formulation_columns(formulation_names, ...) -> list[Column]\n    Add one or more empty formulation columns.\nadd_inventory_row(inventory_id, ...) -> Row\n    Add an ingredient (inventory) row.\nadd_blank_row(row_name, ...) -> Row\n    Add a blank row.\nadd_lookup_row(name, ...) -> Row\n    Add a lookup row.\nadd_app_row(app_id, name, ...) -> Row\n    Add an application row.\nadd_parameter_group_row(parameter_group_id, ...) -> Row\n    Add a parameter group (PRG) row to Process Design.\nadd_blank_column(name, ...) -> Column\n    Add a blank column.\nadd_lookup_column(name, ...) -> Column\n    Add a lookup column.\nadd_function_column(name, ...) -> Column\n    Add a function column.\nadd_property_column(name, attribute_id, ...) -> Column\n    Add a property/result column.\nget_column(...) -> Column\n    Retrieve a column by column ID, inventory ID, or name.\nupdate_cells(cells) -> tuple[list[Cell], list[Cell]]\n    Write changed cells back to the sheet.\npin_columns(col_ids, side) -> None\n    Pin columns to the left or right edge.\nunpin_columns(col_ids) -> None\n    Unpin columns.\nlock_column(...) -> Column\n    Lock or unlock a column.\nhide_column(col_id) -> None\n    Hide a column.\nshow_column(col_id) -> None\n    Show a hidden column.\nset_columns_width(col_ids, width) -> None\n    Set the display width of columns.\ndelete_column(column_id) -> None\n    Delete a column.\ndelete_row(row_id, design_id) -> None\n    Delete a row.",
  "properties": {
    "status": {
      "anyOf": [
        {
          "$ref": "#/$defs/Status"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The status of the resource, optional."
    },
    "Created": {
      "anyOf": [
        {
          "$ref": "#/$defs/AuditFields"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Audit fields for the creation of the resource, optional."
    },
    "Updated": {
      "anyOf": [
        {
          "$ref": "#/$defs/AuditFields"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Audit fields for the update of the resource, optional."
    },
    "albertId": {
      "description": "The Albert ID of the sheet.",
      "title": "Albertid",
      "type": "string"
    },
    "name": {
      "description": "The name of the sheet.",
      "title": "Name",
      "type": "string"
    },
    "Formulas": {
      "description": "References to the formulations present on the sheet.",
      "items": {
        "$ref": "#/$defs/SheetFormulationRef"
      },
      "title": "Formulas",
      "type": "array"
    },
    "hidden": {
      "description": "Whether the sheet is hidden.",
      "title": "Hidden",
      "type": "boolean"
    },
    "isColumnRight": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "When True, copied columns are placed to the right of the source column; when False, to the left.",
      "title": "Iscolumnright"
    },
    "colSizeMode": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Column width sizing mode. Allowed values are ``\"minimum\"`` and ``\"fitToColumn\"``. ``None`` resets to the default grid width.",
      "title": "Colsizemode"
    },
    "Designs": {
      "description": "The Designs (sections) of the sheet.",
      "items": {
        "$ref": "#/$defs/Design"
      },
      "title": "Designs",
      "type": "array"
    },
    "projectId": {
      "description": "The ID of the Project the sheet belongs to (format ``PRO...``).",
      "title": "Projectid",
      "type": "string"
    }
  },
  "required": [
    "albertId",
    "name",
    "hidden",
    "Designs",
    "projectId"
  ],
  "title": "Sheet",
  "type": "object"
}

Fields:

Validators:

Source code in src/albert/core/shared/models/base.py
def __init__(self, **data):
    super().__init__(**data)
    self._session = data.get("session")

id

id: str

The Albert ID of the sheet.

name

name: str

The name of the sheet.

formulations

formulations: list[SheetFormulationRef]

References to the formulations present on the sheet.

hidden

hidden: bool

Whether the sheet is hidden.

is_column_right

is_column_right: bool | None = None

When True, copied columns are placed to the right of the source column; when False, to the left.

col_size_mode

col_size_mode: str | None = None

Column width sizing mode. Allowed values are "minimum" and "fitToColumn". None resets to the default grid width.

designs

designs: list[Design]

The Designs (sections) of the sheet.

project_id

project_id: str

The ID of the Project the sheet belongs to (format PRO...).

app_design

app_design

product_design

product_design

result_design

result_design

process_design

process_design

grid

grid

leftmost_pinned_column

leftmost_pinned_column

The leftmost pinned column in the sheet

columns

columns: list[Column]

The columns of a given sheet

rows

rows: list[Row]

The rows of a given sheet

set_session

set_session()
Source code in src/albert/resources/sheets.py
@model_validator(mode="after")
def set_session(self):
    if self.session is not None:
        for d in self.designs:
            d._session = self.session
    return self

set_sheet_fields

set_sheet_fields() -> Sheet
Source code in src/albert/resources/sheets.py
@model_validator(mode="after")
def set_sheet_fields(self: Sheet) -> Sheet:
    for _idx, d in enumerate(self.designs):  # Instead of creating a new list
        d._sheet = self  # Set the reference to the sheet
        if d.design_type == DesignType.APPS:
            self._app_design = d
        elif d.design_type == DesignType.PRODUCTS:
            self._product_design = d
        elif d.design_type == DesignType.RESULTS:
            self._result_design = d
        elif d.design_type == DesignType.PROCESS:
            self._process_design = d
    return self

rename

rename(*, new_name: str)

Rename this sheet.

Example

sheet.rename(new_name="Final trial")

Parameters:

Name Type Description Default
new_name str

The new name for the sheet.

required

Returns:

Type Description
Sheet

This sheet, with its name updated.

Source code in src/albert/resources/sheets.py
def rename(self, *, new_name: str):
    """Rename this sheet.

    !!! example
        ```python
        sheet.rename(new_name="Final trial")
        ```

    Parameters
    ----------
    new_name : str
        The new name for the sheet.

    Returns
    -------
    Sheet
        This sheet, with its name updated.
    """
    endpoint = f"/api/v3/worksheet/sheet/{self.id}"

    payload = [{"attribute": "name", "operation": "update", "newValue": new_name}]

    self.session.patch(endpoint, json=payload)

    self.name = new_name
    return self

add_formulation

add_formulation(
    *,
    formulation_name: str,
    components: list[Component],
    inventory_id: InventoryId | None = None,
    enforce_order: bool = False,
    clear: bool = True,
) -> Column

Build a formulation on this sheet from a list of components.

This is the primary way to create a formulation. Each component (Component) contributes an ingredient and its amount, which are written into a formulation column. Adding rows for any new ingredients and maintaining the column's Total cell are handled automatically. Building a formulation this way is what registers a Formula inventory item (InventoryItem).

If a column named formulation_name already exists and clear is True, that column is emptied and reused; otherwise a new formulation column is added.

Example

from albert import Albert
from albert.resources.sheets import Component
client = Albert()
worksheet = client.worksheets.get_by_project_id(project_id="PROA9999999")
sheet = worksheet.sheets[0]
column = sheet.add_formulation(
    formulation_name="Formulation A",
    components=[
        Component(inventory_id="INVA9999999", amount=80.0),
        Component(inventory_id="INVA9999998", amount=20.0),
    ],
)

Parameters:

Name Type Description Default
formulation_name str

The name of the formulation, used as the column header.

required
components list[Component]

The ingredients and their amounts to place in the formulation.

required
inventory_id InventoryId

The inventory ID of an existing formulation column to target (format INV...). Used to disambiguate when reusing a column.

None
enforce_order bool

When True, ingredient rows are arranged to match the order of components, adding rows as needed. Default is False.

False
clear bool

When True, an existing column with the same name is cleared and reused rather than adding a duplicate. Default is True.

True

Returns:

Type Description
Column

The formulation column that was created or updated.

Source code in src/albert/resources/sheets.py
def add_formulation(
    self,
    *,
    formulation_name: str,
    components: list[Component],
    inventory_id: InventoryId | None = None,
    enforce_order: bool = False,
    clear: bool = True,
) -> Column:
    """Build a formulation on this sheet from a list of components.

    This is the primary way to create a formulation. Each component
    ([`Component`][albert.resources.sheets.Component]) contributes an ingredient and its amount, which are
    written into a formulation column. Adding rows for any new ingredients and
    maintaining the column's Total cell are handled automatically. Building a
    formulation this way is what registers a Formula inventory item
    ([`InventoryItem`][albert.resources.inventory.InventoryItem]).

    If a column named ``formulation_name`` already exists and ``clear`` is True,
    that column is emptied and reused; otherwise a new formulation column is added.

    !!! example
        ```python
        from albert import Albert
        from albert.resources.sheets import Component
        client = Albert()
        worksheet = client.worksheets.get_by_project_id(project_id="PROA9999999")
        sheet = worksheet.sheets[0]
        column = sheet.add_formulation(
            formulation_name="Formulation A",
            components=[
                Component(inventory_id="INVA9999999", amount=80.0),
                Component(inventory_id="INVA9999998", amount=20.0),
            ],
        )
        ```

    Parameters
    ----------
    formulation_name : str
        The name of the formulation, used as the column header.
    components : list[Component]
        The ingredients and their amounts to place in the formulation.
    inventory_id : InventoryId, optional
        The inventory ID of an existing formulation column to target
        (format ``INV...``). Used to disambiguate when reusing a column.
    enforce_order : bool, optional
        When True, ingredient rows are arranged to match the order of
        ``components``, adding rows as needed. Default is False.
    clear : bool, optional
        When True, an existing column with the same name is cleared and reused
        rather than adding a duplicate. Default is True.

    Returns
    -------
    Column
        The formulation column that was created or updated.
    """

    all_cells: list[Cell] = []
    existing_formulation_names = [x.name for x in self.columns]
    if clear and formulation_name in existing_formulation_names:
        # get the existing column and clear it out to put the new formulation in
        col = self.get_column(column_name=formulation_name, inventory_id=inventory_id)
        self._clear_formulation_from_column(column=col)
    else:
        col = self.add_formulation_columns(formulation_names=[formulation_name])[0]
    column_id = col.column_id

    self.grid = None  # reset the grid for saftey
    product_rows = list(self.product_design.rows)
    initial_row_ids = {row.row_id for row in product_rows}

    for component in components:
        component_inventory_id = component.inventory_item_id
        row_id = self._get_row_id_for_component(
            inventory_id=component_inventory_id,
            existing_cells=all_cells,
            enforce_order=enforce_order,
            product_rows=product_rows,
        )
        if row_id is None:
            raise AlbertException(f"No Component with id {component_inventory_id}")

        value = str(component.amount)
        min_value = str(component.min_value) if component.min_value is not None else None
        max_value = str(component.max_value) if component.max_value is not None else None
        this_cell = Cell(
            column_id=column_id,
            row_id=row_id,
            value=value,
            calculation="",
            type=CellType.INVENTORY,
            design_id=self.product_design.id,
            name=formulation_name,
            inventory_id=col.inventory_id,
            min_value=min_value,
            max_value=max_value,
        )
        all_cells.append(this_cell)

    new_row_ids = [row.row_id for row in product_rows if row.row_id not in initial_row_ids]

    total_row = next((r for r in product_rows if r.type == CellType.TOTAL), None)
    if total_row is not None:
        ingredient_row_ids = [
            row.row_id
            for row in product_rows
            if row.inventory_id is not None and row.row_id != total_row.row_id
        ]
        calculation = "=" + "+".join(f"{column_id}{row_id}" for row_id in ingredient_row_ids)
        total_cell = Cell(
            column_id=column_id,
            row_id=total_row.row_id,
            value=str(sum(component.amount for component in components)),
            calculation=calculation,
            type=CellType.TOTAL,
            design_id=self.product_design.id,
            name=formulation_name,
            inventory_id=col.inventory_id,
        )
        all_cells.append(total_cell)

        # When new ingredient rows were added to the sheet, every other existing
        # inventory column's Total cell must also include those rows in its
        # calculation formula.
        if new_row_ids:
            all_ingredient_row_ids = [
                row.row_id
                for row in product_rows
                if row.inventory_id is not None and row.row_id != total_row.row_id
            ]
            for other_col in self.columns:
                if other_col.column_id == column_id or other_col.type != CellType.INVENTORY:
                    continue
                other_total_cell = next(
                    (
                        c
                        for c in other_col.cells
                        if isinstance(c, Cell) and c.row_id == total_row.row_id
                    ),
                    None,
                )
                if other_total_cell is None:
                    continue
                new_calculation = "=" + "+".join(
                    f"{other_col.column_id}{rid}" for rid in all_ingredient_row_ids
                )
                all_cells.append(
                    other_total_cell.model_copy(update={"calculation": new_calculation})
                )

    # Send ingredient cells first, then Total cells in a separate call.
    def _is_total_cell(c: Cell) -> bool:
        return c.row_type == CellType.TOTAL or c.type == CellType.TOTAL

    ingredient_cells = [c for c in all_cells if not _is_total_cell(c)]
    total_cells = [c for c in all_cells if _is_total_cell(c)]

    if ingredient_cells:
        self.update_cells(cells=ingredient_cells)

    if total_cells:
        # grid reset for safety
        self.grid = None
        self.update_cells(cells=total_cells)

    return self.get_column(column_id=column_id)

add_components_to_formulation

add_components_to_formulation(
    *,
    formulation_name: str | None = None,
    column_id: str | None = None,
    inventory_id: InventoryId | None = None,
    components: list[Component],
    enforce_order: bool = False,
) -> Column

Add components to an existing formulation column without clearing other cells.

Exactly one of column_id, inventory_id, or formulation_name must be provided.

Example

from albert.resources.sheets import Component
column = sheet.add_components_to_formulation(
    formulation_name="Formulation A",
    components=[Component(inventory_id="INVA9999997", amount=5.0)],
)

Parameters:

Name Type Description Default
formulation_name str

The name of the formulation column.

None
column_id str

The column ID of the formulation column.

None
inventory_id str

The inventory ID of the formulation column.

None
components list[Component]

The components to append.

required
enforce_order bool

When True, rows are inserted in the order of components. Default is False.

False

Returns:

Type Description
Column

The updated formulation column.

Source code in src/albert/resources/sheets.py
@validate_call
def add_components_to_formulation(
    self,
    *,
    formulation_name: str | None = None,
    column_id: str | None = None,
    inventory_id: InventoryId | None = None,
    components: list[Component],
    enforce_order: bool = False,
) -> Column:
    """Add components to an existing formulation column without clearing other cells.

    Exactly one of ``column_id``, ``inventory_id``, or ``formulation_name`` must be provided.

    !!! example
        ```python
        from albert.resources.sheets import Component
        column = sheet.add_components_to_formulation(
            formulation_name="Formulation A",
            components=[Component(inventory_id="INVA9999997", amount=5.0)],
        )
        ```

    Parameters
    ----------
    formulation_name : str, optional
        The name of the formulation column.
    column_id : str, optional
        The column ID of the formulation column.
    inventory_id : str, optional
        The inventory ID of the formulation column.
    components : list[Component]
        The components to append.
    enforce_order : bool, optional
        When True, rows are inserted in the order of ``components``. Default is False.

    Returns
    -------
    Column
        The updated formulation column.
    """
    col = self.get_column(
        column_id=column_id, inventory_id=inventory_id, column_name=formulation_name
    )
    col_id = col.column_id
    self.grid = None

    product_rows = list(self.product_design.rows)
    all_cells: list[Cell] = []
    for component in components:
        inv_item = component.inventory_item
        item_id: InventoryId = inv_item.id if inv_item is not None else component.inventory_id
        row_id = self._get_row_id_for_component(
            inventory_id=item_id,
            existing_cells=all_cells,
            enforce_order=enforce_order,
            product_rows=product_rows,
        )
        if row_id is None:
            raise AlbertException(f"No row found for inventory ID {item_id}")

        all_cells.append(
            Cell(
                column_id=col_id,
                row_id=row_id,
                value=str(component.amount),
                calculation="",
                type=CellType.INVENTORY,
                design_id=self.product_design.id,
                name=col.name or formulation_name or "",
                inventory_id=col.inventory_id,
                min_value=str(component.min_value)
                if component.min_value is not None
                else None,
                max_value=str(component.max_value)
                if component.max_value is not None
                else None,
            )
        )

    self.update_cells(cells=all_cells)
    return self.get_column(column_id=col_id)

add_formulation_columns

add_formulation_columns(
    *,
    formulation_names: list[str],
    starting_position: dict | None = None,
) -> list[Column]

Add one or more empty formulation columns to this sheet.

Creates the formulation columns without populating any ingredient amounts. To build a formulation and fill in its components in one step, use add_formulation instead.

Example

columns = sheet.add_formulation_columns(
    formulation_names=["Formulation A", "Formulation B"]
)

Parameters:

Name Type Description Default
formulation_names list[str]

The names of the formulation columns to add, used as column headers.

required
starting_position dict

Where to insert the new columns, as a dict with reference_id (a column ID) and position ("leftOf" or "rightOf"). When omitted, the platform chooses the default placement.

None

Returns:

Type Description
list[Column]

The created formulation columns, in the order requested.

Source code in src/albert/resources/sheets.py
def add_formulation_columns(
    self,
    *,
    formulation_names: list[str],
    starting_position: dict | None = None,
) -> list[Column]:
    """Add one or more empty formulation columns to this sheet.

    Creates the formulation columns without populating any ingredient amounts.
    To build a formulation and fill in its components in one step, use
    [`add_formulation`][albert.resources.sheets.Sheet.add_formulation] instead.

    !!! example
        ```python
        columns = sheet.add_formulation_columns(
            formulation_names=["Formulation A", "Formulation B"]
        )
        ```

    Parameters
    ----------
    formulation_names : list[str]
        The names of the formulation columns to add, used as column headers.
    starting_position : dict, optional
        Where to insert the new columns, as a dict with ``reference_id`` (a
        column ID) and ``position`` (``"leftOf"`` or ``"rightOf"``). When
        omitted, the platform chooses the default placement.

    Returns
    -------
    list[Column]
        The created formulation columns, in the order requested.
    """
    endpoint = f"/api/v3/worksheet/sheet/{self.id}/columns"

    # In case a user supplied a single formulation name instead of a list
    formulation_names = (
        formulation_names if isinstance(formulation_names, list) else [formulation_names]
    )

    payload = []
    for formulation_name in formulation_names:
        entry = {"type": "INV", "name": formulation_name}
        # When no position is given, omit referenceId/position so the platform
        # applies its default placement. Sending a null (or stale) referenceId
        # leaves the new column out of the sheet sequence, hiding it on refresh.
        if starting_position is not None:
            entry["referenceId"] = starting_position["reference_id"]
            entry["position"] = starting_position["position"]
        payload.append(entry)
    response = self.session.post(endpoint, json=payload)

    self.grid = None
    new_dicts = self._reformat_formulation_addition_payload(response_json=response.json())
    return [Column(**x) for x in new_dicts]

add_blank_row

add_blank_row(
    *,
    row_name: str,
    design: DesignType = PRODUCTS,
    position: dict | None = None,
)

Add a blank (BLK) row to a Design section of this sheet.

Example

row = sheet.add_blank_row(row_name="Notes")

Parameters:

Name Type Description Default
row_name str

The display name of the new row.

required
design DesignType

Which Design section to add the row to. Default is DesignType.PRODUCTS. Rows cannot be added to the Results design.

PRODUCTS
position dict

Where to insert the row, as a dict with reference_id (a row ID) and position ("above" or "below"). Defaults to above "ROW1".

None

Returns:

Type Description
Row

The created row.

Raises:

Type Description
AlbertException

If design is DesignType.RESULTS or DesignType.PROCESS. Process Design only accepts parameter-group (PRG) rows: use add_parameter_group_row.

Source code in src/albert/resources/sheets.py
def add_blank_row(
    self,
    *,
    row_name: str,
    design: DesignType = DesignType.PRODUCTS,
    position: dict | None = None,
):
    """Add a blank (BLK) row to a Design section of this sheet.

    !!! example
        ```python
        row = sheet.add_blank_row(row_name="Notes")
        ```

    Parameters
    ----------
    row_name : str
        The display name of the new row.
    design : DesignType, optional
        Which Design section to add the row to. Default is ``DesignType.PRODUCTS``.
        Rows cannot be added to the Results design.
    position : dict, optional
        Where to insert the row, as a dict with ``reference_id`` (a row ID) and
        ``position`` (``"above"`` or ``"below"``). Defaults to above ``"ROW1"``.

    Returns
    -------
    Row
        The created row.

    Raises
    ------
    AlbertException
        If ``design`` is ``DesignType.RESULTS`` or ``DesignType.PROCESS``.
        Process Design only accepts parameter-group (PRG) rows: use
        [`add_parameter_group_row`][albert.resources.sheets.Sheet.add_parameter_group_row].
    """
    if design == DesignType.RESULTS:
        raise AlbertException("You cannot add rows to the results design")
    if design == DesignType.PROCESS or design == DesignType.PROCESS.value:
        raise AlbertException(
            "Blank rows cannot be added to Process Design; "
            "use add_parameter_group_row to attach a parameter group"
        )
    if position is None:
        position = {"reference_id": "ROW1", "position": "above"}
    endpoint = f"/api/v3/worksheet/design/{self._get_design_id(design=design)}/rows"

    payload = [
        {
            "type": "BLK",
            "name": row_name,
            "referenceId": position["reference_id"],
            "position": position["position"],
        }
    ]

    response = self.session.post(endpoint, json=payload)

    self.grid = None
    row_dict = response.json()[0]
    return Row(
        rowId=row_dict["rowId"],
        type=row_dict["type"],
        session=self.session,
        design=self._get_design(design=design),
        name=row_dict["name"],
        sheet=self,
    )

add_inventory_row

add_inventory_row(
    *, inventory_id: str, position: dict | None = None
)

Add an ingredient (inventory) row to the Product Design.

The row represents an inventory item that can then carry amounts in each formulation column. The INV prefix is added to inventory_id if absent.

Example

row = sheet.add_inventory_row(inventory_id="INVA9999999")

Parameters:

Name Type Description Default
inventory_id str

The inventory ID of the item to add as a row (format INV...).

required
position dict

Where to insert the row, as a dict with reference_id (a row ID) and position ("above" or "below"). Defaults to above "ROW1".

None

Returns:

Type Description
Row

The created inventory row.

Source code in src/albert/resources/sheets.py
def add_inventory_row(
    self,
    *,
    inventory_id: str,
    position: dict | None = None,
):
    """Add an ingredient (inventory) row to the Product Design.

    The row represents an inventory item that can then carry amounts in each
    formulation column. The ``INV`` prefix is added to ``inventory_id`` if absent.

    !!! example
        ```python
        row = sheet.add_inventory_row(inventory_id="INVA9999999")
        ```

    Parameters
    ----------
    inventory_id : str
        The inventory ID of the item to add as a row (format ``INV...``).
    position : dict, optional
        Where to insert the row, as a dict with ``reference_id`` (a row ID) and
        ``position`` (``"above"`` or ``"below"``). Defaults to above ``"ROW1"``.

    Returns
    -------
    Row
        The created inventory row.
    """
    if position is None:
        position = {"reference_id": "ROW1", "position": "above"}
    design_id = self.product_design.id
    endpoint = f"/api/v3/worksheet/design/{design_id}/rows"

    payload = {
        "type": "INV",
        "id": ("INV" + inventory_id if not inventory_id.startswith("INV") else inventory_id),
        "referenceId": position["reference_id"],
        "position": position["position"],
    }

    response = self.session.post(endpoint, json=payload)

    self.grid = None
    row_dict = response.json()
    return Row(
        rowId=row_dict["rowId"],
        inventory_id=inventory_id,
        type=row_dict["type"],
        session=self.session,
        design=self.product_design,
        sheet=self,
        name=row_dict["name"],
        id=row_dict["id"],
        manufacturer=row_dict["manufacturer"],
    )

add_lookup_row

add_lookup_row(
    *,
    name: str,
    design: DesignType | str | None = APPS,
    reference_id: str = "ROW1",
    position: RowPosition = ABOVE,
) -> Row

Add a lookup (LKP) row to a design.

Example

row = sheet.add_lookup_row(name="Density")

Parameters:

Name Type Description Default
name str

The display name of the new row.

required
design DesignType or str

Which design to add the row to. Default is DesignType.APPS.

APPS
reference_id str

The row ID to insert relative to. Defaults to "ROW1".

'ROW1'
position RowPosition

Whether to insert ABOVE or BELOW the reference row. Default is ABOVE.

ABOVE

Returns:

Type Description
Row

The created row.

Source code in src/albert/resources/sheets.py
@validate_call
def add_lookup_row(
    self,
    *,
    name: str,
    design: DesignType | str | None = DesignType.APPS,
    reference_id: str = "ROW1",
    position: RowPosition = RowPosition.ABOVE,
) -> Row:
    """Add a lookup (LKP) row to a design.

    !!! example
        ```python
        row = sheet.add_lookup_row(name="Density")
        ```

    Parameters
    ----------
    name : str
        The display name of the new row.
    design : DesignType or str, optional
        Which design to add the row to. Default is ``DesignType.APPS``.
    reference_id : str, optional
        The row ID to insert relative to. Defaults to ``"ROW1"``.
    position : RowPosition, optional
        Whether to insert ``ABOVE`` or ``BELOW`` the reference row.
        Default is ``ABOVE``.

    Returns
    -------
    Row
        The created row.
    """
    if design == DesignType.RESULTS:
        raise AlbertException("Cannot add rows to the results design")
    design_obj = self._get_design(design=design)
    payload = [
        {
            "type": "LKP",
            "name": name,
            "referenceId": reference_id,
            "position": position.value,
        }
    ]
    response = self.session.post(
        f"/api/v3/worksheet/design/{design_obj.id}/rows", json=payload
    )
    self.grid = None
    data = response.json()[0] if isinstance(response.json(), list) else response.json()
    return Row(
        rowId=data["rowId"],
        type=data["type"],
        session=self.session,
        design=design_obj,
        sheet=self,
        name=data.get("lableName") or data.get("name") or name,
        inventory_id=data.get("id"),
        manufacturer=data.get("manufacturer"),
    )

add_app_row

add_app_row(
    *,
    app_id: str,
    name: str,
    config: RowConfig | None = None,
    design: DesignType | str | None = APPS,
    reference_id: str = "ROW1",
    position: RowPosition = ABOVE,
) -> Row

Add an application (APP) row to a design.

Example

row = sheet.add_app_row(app_id="APP1", name="Cost insight")

Parameters:

Name Type Description Default
app_id str

The ID of the application. The APP prefix is added automatically if absent.

required
name str

The display name of the row.

required
config RowConfig

Row configuration (option and value). Used to scope the app to a location or region.

None
design DesignType or str

Which design to add the row to. Default is DesignType.APPS.

APPS
reference_id str

The row ID to insert relative to. Defaults to "ROW1".

'ROW1'
position RowPosition

Whether to insert ABOVE or BELOW the reference row. Default is ABOVE.

ABOVE

Returns:

Type Description
Row

The created row.

Source code in src/albert/resources/sheets.py
@validate_call
def add_app_row(
    self,
    *,
    app_id: str,
    name: str,
    config: RowConfig | None = None,
    design: DesignType | str | None = DesignType.APPS,
    reference_id: str = "ROW1",
    position: RowPosition = RowPosition.ABOVE,
) -> Row:
    """Add an application (APP) row to a design.

    !!! example
        ```python
        row = sheet.add_app_row(app_id="APP1", name="Cost insight")
        ```

    Parameters
    ----------
    app_id : str
        The ID of the application. The ``APP`` prefix is added automatically if absent.
    name : str
        The display name of the row.
    config : RowConfig, optional
        Row configuration (``option`` and ``value``). Used to scope the app
        to a location or region.
    design : DesignType or str, optional
        Which design to add the row to. Default is ``DesignType.APPS``.
    reference_id : str, optional
        The row ID to insert relative to. Defaults to ``"ROW1"``.
    position : RowPosition, optional
        Whether to insert ``ABOVE`` or ``BELOW`` the reference row.
        Default is ``ABOVE``.

    Returns
    -------
    Row
        The created row.
    """
    if design == DesignType.RESULTS:
        raise AlbertException("Cannot add rows to the results design")
    design_obj = self._get_design(design=design)
    app_id = app_id if app_id.startswith("APP") else f"APP{app_id}"

    payload: dict = {
        "type": "APP",
        "id": app_id,
        "name": name,
        "referenceId": reference_id,
        "position": position.value,
    }
    if config is not None:
        payload["config"] = config.model_dump(by_alias=True, mode="json", exclude_none=True)

    response = self.session.post(
        f"/api/v3/worksheet/design/{design_obj.id}/rows", json=[payload]
    )
    self.grid = None
    data = response.json()[0] if isinstance(response.json(), list) else response.json()
    return Row(
        rowId=data["rowId"],
        type=data["type"],
        session=self.session,
        design=design_obj,
        sheet=self,
        name=data.get("name") or name,
        inventory_id=data.get("id"),
        manufacturer=data.get("manufacturer"),
        config=data.get("config"),
    )

add_parameter_group_row

add_parameter_group_row(
    *,
    parameter_group_id: ParameterGroupId,
    reference_id: str | None = None,
    position: RowPosition = ABOVE,
) -> Row

Add a parameter group (PRG) row to this sheet's Process Design.

The platform expands the PRG into one PRM row per parameter in the group.

Example

row = sheet.add_parameter_group_row(parameter_group_id="PRG9999999")

Parameters:

Name Type Description Default
parameter_group_id ParameterGroupId

The Parameter Group ID to add (format PRG...).

required
reference_id str

The row ID to insert relative to. Defaults to the first Process Design row when one exists. Omit (or leave None) when Process Design is empty (the first PRG does not need a reference row).

None
position RowPosition

Whether to insert ABOVE or BELOW the reference row. Default is ABOVE. Ignored when Process Design has no rows and reference_id is omitted.

ABOVE

Returns:

Type Description
Row

The created PRG row.

Raises:

Type Description
AlbertException

If the sheet has no Process Design section, or the response has no rows.

Source code in src/albert/resources/sheets.py
@validate_call
def add_parameter_group_row(
    self,
    *,
    parameter_group_id: ParameterGroupId,
    reference_id: str | None = None,
    position: RowPosition = RowPosition.ABOVE,
) -> Row:
    """Add a parameter group (PRG) row to this sheet's Process Design.

    The platform expands the PRG into one PRM row per parameter in the group.

    !!! example
        ```python
        row = sheet.add_parameter_group_row(parameter_group_id="PRG9999999")
        ```

    Parameters
    ----------
    parameter_group_id : ParameterGroupId
        The Parameter Group ID to add (format ``PRG...``).
    reference_id : str, optional
        The row ID to insert relative to. Defaults to the first Process Design
        row when one exists. Omit (or leave ``None``) when Process Design is
        empty (the first PRG does not need a reference row).
    position : RowPosition, optional
        Whether to insert ``ABOVE`` or ``BELOW`` the reference row.
        Default is ``ABOVE``. Ignored when Process Design has no rows and
        ``reference_id`` is omitted.

    Returns
    -------
    Row
        The created PRG row.

    Raises
    ------
    AlbertException
        If the sheet has no Process Design section, or the response has no rows.
    """
    design_obj = self.process_design
    if design_obj is None:
        raise AlbertException(
            "Sheet has no Process Design section; cannot add a parameter group row"
        )
    payload_item: dict[str, str] = {
        "type": CellType.PRG.value,
        "id": parameter_group_id,
    }
    if reference_id is None:
        existing_rows = design_obj.rows
        if existing_rows:
            reference_id = existing_rows[0].row_id
    if reference_id is not None:
        # Empty Process Design accepts a PRG with no referenceId/position.
        payload_item["referenceId"] = reference_id
        payload_item["position"] = position.value

    payload = [payload_item]
    response = self.session.post(f"/api/v3/designs/{design_obj.id}/rows", json=payload)
    self.grid = None
    rows = response.json()
    if not isinstance(rows, list):
        rows = [rows]
    if not rows:
        raise AlbertException(
            f"No rows returned when adding parameter group '{parameter_group_id}' "
            f"to Process Design '{design_obj.id}'"
        )
    data = next((row for row in rows if row.get("type") == CellType.PRG.value), rows[0])
    return Row(
        rowId=data["rowId"],
        type=data["type"],
        session=self.session,
        design=design_obj,
        sheet=self,
        name=data.get("labelName") or data.get("name"),
        inventory_id=data.get("id"),
    )

update_cells

update_cells(*, cells: list[Cell])

Write changed cells back to the sheet.

Compares each cell against the current grid and sends only the changed attributes (value, calculation, formatting, bounds). Higher-level methods such as add_formulation and recolor_cells call this for you; use it directly when editing cells obtained from the grid.

Example

from albert.resources.sheets import CellColor
column = sheet.get_column(column_name="Formulation A")
recolored = [c.model_copy(update={"format": {"bgColor": CellColor.YELLOW.value}})
             for c in column.cells]
updated, failed = sheet.update_cells(cells=recolored)

Parameters:

Name Type Description Default
cells list[Cell]

The cells to update. Typically copies of existing cells with modified values or formatting.

required

Returns:

Type Description
tuple[list[Cell], list[Cell]]

A (updated, failed) pair: the cells that were successfully updated and the cells that failed to update.

Source code in src/albert/resources/sheets.py
def update_cells(self, *, cells: list[Cell]):
    """Write changed cells back to the sheet.

    Compares each cell against the current grid and sends only the changed
    attributes (value, calculation, formatting, bounds). Higher-level methods
    such as [`add_formulation`][albert.resources.sheets.Sheet.add_formulation] and [`recolor_cells`][albert.resources.sheets.Column.recolor_cells] call this
    for you; use it directly when editing cells obtained from the grid.

    !!! example
        ```python
        from albert.resources.sheets import CellColor
        column = sheet.get_column(column_name="Formulation A")
        recolored = [c.model_copy(update={"format": {"bgColor": CellColor.YELLOW.value}})
                     for c in column.cells]
        updated, failed = sheet.update_cells(cells=recolored)
        ```

    Parameters
    ----------
    cells : list[Cell]
        The cells to update. Typically copies of existing cells with modified
        values or formatting.

    Returns
    -------
    tuple[list[Cell], list[Cell]]
        A ``(updated, failed)`` pair: the cells that were successfully updated
        and the cells that failed to update.
    """

    request_path_dict: dict[str, list[Cell]] = {}
    updated: list[Cell] = []
    failed: list[Cell] = []
    # sort by design ID
    for c in cells:
        if c.design_id not in request_path_dict:
            request_path_dict[c.design_id] = [c]
        else:
            request_path_dict[c.design_id].append(c)

    for design_id, cell_list in request_path_dict.items():
        payload_entries: list[tuple[CellChangePayload, Cell]] = []
        for cell in cell_list:
            change_dict = self._get_cell_changes(cell=cell)
            if change_dict is None:
                continue

            is_calculation_cell = cell.calculation is not None and cell.calculation != ""
            max_items = 2 if is_calculation_cell else 1

            if len(change_dict["data"]) > max_items:
                for item in change_dict["data"]:
                    single_change: CellChangePayload = {
                        "Id": change_dict["Id"],
                        "data": [item],
                    }
                    payload_entries.append((single_change, cell))
            else:
                payload_entries.append((change_dict, cell))

        if not payload_entries:
            continue

        this_url = f"/api/v3/worksheet/{design_id}/values"
        pending_by_cell: dict[tuple[str, str], list[tuple[CellChangePayload, Cell]]] = {}
        for payload, cell in payload_entries:
            key = (payload["Id"]["rowId"], payload["Id"]["colId"])
            pending_by_cell.setdefault(key, []).append((payload, cell))

        ordered_keys = list(pending_by_cell.keys())

        def _unique_cells(cells: list[Cell]) -> list[Cell]:
            seen: set[tuple[str, str, str]] = set()
            result: list[Cell] = []
            for c in cells:
                key = (c.design_id, c.row_id, c.column_id)
                if key not in seen:
                    seen.add(key)
                    result.append(c)
            return result

        batch_index = 0
        while True:
            batch_payloads: list[CellChangePayload] = []
            batch_cells: list[Cell] = []
            for key in ordered_keys:
                queue = pending_by_cell.get(key)
                if queue:
                    payload, cell = queue.pop(0)
                    batch_payloads.append(payload)
                    batch_cells.append(cell)
            if not batch_payloads:
                break

            payload_body = [
                {
                    "Id": payload["Id"],
                    "data": [datum.model_dump(by_alias=True) for datum in payload["data"]],
                }
                for payload in batch_payloads
            ]
            response = self.session.patch(this_url, json=payload_body)
            target_cells = _unique_cells(batch_cells)

            if response.status_code == 204:
                for c in target_cells:
                    if c not in updated:
                        updated.append(c)
            elif response.status_code == 206:
                cell_results = self._filter_cells(
                    cells=target_cells, response_dict=response.json()
                )
                for c in cell_results[0]:
                    if c not in updated:
                        updated.append(c)
                for c in cell_results[1]:
                    if c not in failed:
                        failed.append(c)
            else:
                for c in target_cells:
                    if c not in failed:
                        failed.append(c)

            batch_index += 1

    # reset the in-memory grid after updates
    self.grid = None
    return (updated, failed)

add_blank_column

add_blank_column(
    *,
    name: str,
    reference_id: str | None = None,
    position: ColumnPosition = RIGHT_OF,
) -> Column

Add a blank (BLK) column to this sheet.

Example

column = sheet.add_blank_column(name="Notes")

Parameters:

Name Type Description Default
name str

The display name of the new column.

required
reference_id str

The column ID to insert relative to. Defaults to the last column in the sheet.

None
position ColumnPosition

Whether to insert LEFT_OF or RIGHT_OF the reference column. Default is RIGHT_OF.

RIGHT_OF

Returns:

Type Description
Column

The created column.

Source code in src/albert/resources/sheets.py
@validate_call
def add_blank_column(
    self,
    *,
    name: str,
    reference_id: str | None = None,
    position: ColumnPosition = ColumnPosition.RIGHT_OF,
) -> Column:
    """Add a blank (BLK) column to this sheet.

    !!! example
        ```python
        column = sheet.add_blank_column(name="Notes")
        ```

    Parameters
    ----------
    name : str
        The display name of the new column.
    reference_id : str, optional
        The column ID to insert relative to. Defaults to the last column in the sheet.
    position : ColumnPosition, optional
        Whether to insert ``LEFT_OF`` or ``RIGHT_OF`` the reference column.
        Default is ``RIGHT_OF``.

    Returns
    -------
    Column
        The created column.
    """
    return self._add_column(
        type="BLK", name=name, reference_id=reference_id, position=position
    )

add_lookup_column

add_lookup_column(
    *,
    name: str,
    reference_id: str | None = None,
    position: ColumnPosition = RIGHT_OF,
) -> Column

Add a lookup (LKP) column to this sheet.

Example

column = sheet.add_lookup_column(name="CAS Number")

Parameters:

Name Type Description Default
name str

The display name of the new column.

required
reference_id str

The column ID to insert relative to. Defaults to the last column in the sheet.

None
position ColumnPosition

Whether to insert LEFT_OF or RIGHT_OF the reference column. Default is RIGHT_OF.

RIGHT_OF

Returns:

Type Description
Column

The created column.

Source code in src/albert/resources/sheets.py
@validate_call
def add_lookup_column(
    self,
    *,
    name: str,
    reference_id: str | None = None,
    position: ColumnPosition = ColumnPosition.RIGHT_OF,
) -> Column:
    """Add a lookup (LKP) column to this sheet.

    !!! example
        ```python
        column = sheet.add_lookup_column(name="CAS Number")
        ```

    Parameters
    ----------
    name : str
        The display name of the new column.
    reference_id : str, optional
        The column ID to insert relative to. Defaults to the last column in the sheet.
    position : ColumnPosition, optional
        Whether to insert ``LEFT_OF`` or ``RIGHT_OF`` the reference column.
        Default is ``RIGHT_OF``.

    Returns
    -------
    Column
        The created column.
    """
    return self._add_column(
        type="LKP", name=name, reference_id=reference_id, position=position
    )

add_function_column

add_function_column(
    *,
    name: str,
    reference_id: str | None = None,
    position: ColumnPosition = RIGHT_OF,
) -> Column

Add a function (FNC) column to this sheet.

Example

column = sheet.add_function_column(name="Cost per kg")

Parameters:

Name Type Description Default
name str

The display name of the new column.

required
reference_id str

The column ID to insert relative to. Defaults to the last column in the sheet.

None
position ColumnPosition

Whether to insert LEFT_OF or RIGHT_OF the reference column. Default is RIGHT_OF.

RIGHT_OF

Returns:

Type Description
Column

The created column.

Source code in src/albert/resources/sheets.py
@validate_call
def add_function_column(
    self,
    *,
    name: str,
    reference_id: str | None = None,
    position: ColumnPosition = ColumnPosition.RIGHT_OF,
) -> Column:
    """Add a function (FNC) column to this sheet.

    !!! example
        ```python
        column = sheet.add_function_column(name="Cost per kg")
        ```

    Parameters
    ----------
    name : str
        The display name of the new column.
    reference_id : str, optional
        The column ID to insert relative to. Defaults to the last column in the sheet.
    position : ColumnPosition, optional
        Whether to insert ``LEFT_OF`` or ``RIGHT_OF`` the reference column.
        Default is ``RIGHT_OF``.

    Returns
    -------
    Column
        The created column.
    """
    return self._add_column(
        type="FNC", name=name, reference_id=reference_id, position=position
    )

add_property_column

add_property_column(
    *,
    name: str,
    attribute_id: str,
    data_column_id: DataColumnId | None = None,
    data_column_name: str | None = None,
    reference_id: str | None = None,
    position: ColumnPosition = RIGHT_OF,
) -> Column

Add a property/result (RSL) column to this sheet.

Exactly one of data_column_id or data_column_name must be provided; the other is fetched automatically.

Example

column = sheet.add_property_column(
    name="Viscosity",
    attribute_id="ATR2020",
    data_column_name="Viscosity",
)

Parameters:

Name Type Description Default
name str

The display name of the new column.

required
attribute_id str

The ID of the attribute (e.g. "ATR2020").

required
data_column_id DataColumnId

The data column ID (e.g. "DAC2900"). Fetched from the API if omitted.

None
data_column_name str

The data column name. Fetched from the API if omitted.

None
reference_id str

The column ID to insert relative to. Defaults to the last column in the sheet.

None
position ColumnPosition

Whether to insert LEFT_OF or RIGHT_OF the reference column. Default is RIGHT_OF.

RIGHT_OF

Returns:

Type Description
Column

The created column.

Source code in src/albert/resources/sheets.py
@validate_call
def add_property_column(
    self,
    *,
    name: str,
    attribute_id: str,
    data_column_id: DataColumnId | None = None,
    data_column_name: str | None = None,
    reference_id: str | None = None,
    position: ColumnPosition = ColumnPosition.RIGHT_OF,
) -> Column:
    """Add a property/result (RSL) column to this sheet.

    Exactly one of ``data_column_id`` or ``data_column_name`` must be provided;
    the other is fetched automatically.

    !!! example
        ```python
        column = sheet.add_property_column(
            name="Viscosity",
            attribute_id="ATR2020",
            data_column_name="Viscosity",
        )
        ```

    Parameters
    ----------
    name : str
        The display name of the new column.
    attribute_id : str
        The ID of the attribute (e.g. ``"ATR2020"``).
    data_column_id : DataColumnId, optional
        The data column ID (e.g. ``"DAC2900"``). Fetched from the API if omitted.
    data_column_name : str, optional
        The data column name. Fetched from the API if omitted.
    reference_id : str, optional
        The column ID to insert relative to. Defaults to the last column in the sheet.
    position : ColumnPosition, optional
        Whether to insert ``LEFT_OF`` or ``RIGHT_OF`` the reference column.
        Default is ``RIGHT_OF``.

    Returns
    -------
    Column
        The created column.
    """
    if not data_column_id and not data_column_name:
        raise AlbertException("Provide at least one of data_column_id or data_column_name.")
    if not data_column_id or not data_column_name:
        from albert.collections.data_columns import DataColumnCollection

        dc_collection = DataColumnCollection(session=self.session)
        if data_column_id and not data_column_name:
            dc = dc_collection.get_by_id(id=data_column_id)
            data_column_name = dc.name
        else:
            dc = dc_collection.get_by_name(name=data_column_name)
            if dc is None:
                raise AlbertException(f"No data column found with name '{data_column_name}'.")
            data_column_id = dc.id

    return self._add_column(
        type="RSL",
        name=name,
        reference_id=reference_id,
        position=position,
        extra={
            "id": attribute_id,
            "datacolumnId": data_column_id,
            "datacolumnName": data_column_name,
        },
    )

pin_columns

pin_columns(
    *, col_ids: list[str], side: Literal["left", "right"]
) -> None

Pin one or more columns to the left or right edge of the sheet.

Example

sheet.pin_columns(col_ids=["COL9999999", "COL2"], side="left")

Parameters:

Name Type Description Default
col_ids list[str]

The column IDs to pin.

required
side 'left' or 'right'

Which edge to pin to.

required

Returns:

Type Description
None
Source code in src/albert/resources/sheets.py
@validate_call
def pin_columns(
    self,
    *,
    col_ids: list[str],
    side: Literal["left", "right"],
) -> None:
    """Pin one or more columns to the left or right edge of the sheet.

    !!! example
        ```python
        sheet.pin_columns(col_ids=["COL9999999", "COL2"], side="left")
        ```

    Parameters
    ----------
    col_ids : list[str]
        The column IDs to pin.
    side : "left" or "right"
        Which edge to pin to.

    Returns
    -------
    None
    """
    payload = {
        "data": [
            {
                "operation": "update",
                "attribute": "pinned",
                "colIds": col_ids,
                "newValue": side,
            }
        ]
    }
    self.session.patch(f"/api/v3/worksheet/sheet/{self.id}/columns", json=payload)
    self.grid = None

unpin_columns

unpin_columns(*, col_ids: list[str]) -> None

Unpin one or more columns.

Example

sheet.unpin_columns(col_ids=["COL9999999", "COL2"])

Parameters:

Name Type Description Default
col_ids list[str]

The column IDs to unpin.

required

Returns:

Type Description
None
Source code in src/albert/resources/sheets.py
@validate_call
def unpin_columns(self, *, col_ids: list[str]) -> None:
    """Unpin one or more columns.

    !!! example
        ```python
        sheet.unpin_columns(col_ids=["COL9999999", "COL2"])
        ```

    Parameters
    ----------
    col_ids : list[str]
        The column IDs to unpin.

    Returns
    -------
    None
    """
    payload = {
        "data": [
            {
                "operation": "update",
                "attribute": "pinned",
                "colIds": col_ids,
                "newValue": False,
            }
        ]
    }
    self.session.patch(f"/api/v3/worksheet/sheet/{self.id}/columns", json=payload)
    self.grid = None

set_columns_width

set_columns_width(
    *, col_ids: list[str], width: str
) -> None

Set the display width of one or more columns.

Example

sheet.set_columns_width(col_ids=["COL9999999"], width="200px")

Parameters:

Name Type Description Default
col_ids list[str]

Column IDs to update.

required
width str

Width value, e.g. "142px".

required

Returns:

Type Description
None
Source code in src/albert/resources/sheets.py
@validate_call
def set_columns_width(self, *, col_ids: list[str], width: str) -> None:
    """Set the display width of one or more columns.

    !!! example
        ```python
        sheet.set_columns_width(col_ids=["COL9999999"], width="200px")
        ```

    Parameters
    ----------
    col_ids : list[str]
        Column IDs to update.
    width : str
        Width value, e.g. ``"142px"``.

    Returns
    -------
    None
    """
    payload = {
        "data": [
            {
                "operation": "update",
                "attribute": "columnWidth",
                "colIds": col_ids,
                "newValue": width,
            }
        ]
    }
    self.session.patch(f"/api/v3/worksheet/sheet/{self.id}/columns", json=payload)
    self.grid = None

hide_column

hide_column(*, col_id: str) -> None

Hide a column.

Example

sheet.hide_column(col_id="COL5")

Parameters:

Name Type Description Default
col_id str

The column ID to hide.

required

Returns:

Type Description
None
Source code in src/albert/resources/sheets.py
@validate_call
def hide_column(self, *, col_id: str) -> None:
    """Hide a column.

    !!! example
        ```python
        sheet.hide_column(col_id="COL5")
        ```

    Parameters
    ----------
    col_id : str
        The column ID to hide.

    Returns
    -------
    None
    """
    self.session.patch(
        f"/api/v3/worksheet/sheet/{self.id}/columns",
        json={
            "data": [
                {
                    "operation": "update",
                    "attribute": "hidden",
                    "colId": col_id,
                    "newValue": True,
                }
            ]
        },
    )
    self.grid = None

show_column

show_column(*, col_id: str) -> None

Show a hidden column.

Example

sheet.show_column(col_id="COL5")

Parameters:

Name Type Description Default
col_id str

The column ID to show.

required

Returns:

Type Description
None
Source code in src/albert/resources/sheets.py
@validate_call
def show_column(self, *, col_id: str) -> None:
    """Show a hidden column.

    !!! example
        ```python
        sheet.show_column(col_id="COL5")
        ```

    Parameters
    ----------
    col_id : str
        The column ID to show.

    Returns
    -------
    None
    """
    self.session.patch(
        f"/api/v3/worksheet/sheet/{self.id}/columns",
        json={
            "data": [
                {
                    "operation": "update",
                    "attribute": "hidden",
                    "colId": col_id,
                    "newValue": False,
                }
            ]
        },
    )
    self.grid = None

delete_column

delete_column(*, column_id: str) -> None

Delete a column from this sheet.

Example

sheet.delete_column(column_id="COL5")

Parameters:

Name Type Description Default
column_id str

The ID of the column to delete.

required

Returns:

Type Description
None
Source code in src/albert/resources/sheets.py
def delete_column(self, *, column_id: str) -> None:
    """Delete a column from this sheet.

    !!! example
        ```python
        sheet.delete_column(column_id="COL5")
        ```

    Parameters
    ----------
    column_id : str
        The ID of the column to delete.

    Returns
    -------
    None
    """
    endpoint = f"/api/v3/worksheet/sheet/{self.id}/columns"
    payload = [{"colId": column_id}]
    self.session.delete(endpoint, json=payload)

    if self._grid is not None:  # if I have a grid loaded into memory, adjust it.
        self.grid = None

delete_row

delete_row(*, row_id: str, design_id: str) -> None

Delete a row from a Design section of this sheet.

Example

sheet.delete_row(row_id="ROW3", design_id=sheet.product_design.id)

Parameters:

Name Type Description Default
row_id str

The ID of the row to delete.

required
design_id str

The ID of the Design (section) the row belongs to.

required

Returns:

Type Description
None
Source code in src/albert/resources/sheets.py
def delete_row(self, *, row_id: str, design_id: str) -> None:
    """Delete a row from a Design section of this sheet.

    !!! example
        ```python
        sheet.delete_row(row_id="ROW3", design_id=sheet.product_design.id)
        ```

    Parameters
    ----------
    row_id : str
        The ID of the row to delete.
    design_id : str
        The ID of the Design (section) the row belongs to.

    Returns
    -------
    None
    """
    endpoint = f"/api/v3/worksheet/design/{design_id}/rows"
    payload = [{"rowId": row_id}]
    self.session.delete(endpoint, json=payload)

    if self._grid is not None:  # if I have a grid loaded into memory, adjust it.
        self.grid = None

get_column

get_column(
    *,
    column_id: str | None = None,
    inventory_id: InventoryId | None = None,
    column_name: str | None = None,
) -> Column

Retrieve a Column by its column ID, underlying inventory ID, or header name.

Provide at least one of the three identifiers; the match must be unique.

Example

column = sheet.get_column(column_name="Formulation A")

Parameters:

Name Type Description Default
column_id str

The sheet column ID to match (e.g. "COL5").

None
inventory_id str

The underlying inventory ID to match (e.g. "INVP015-001").

None
column_name str

The human-readable header name of the column (e.g. "Formulation A").

None

Returns:

Type Description
Column

The matching column.

Raises:

Type Description
AlbertException

If no identifier is provided, no matching column is found, or multiple columns match.

Source code in src/albert/resources/sheets.py
@validate_call
def get_column(
    self,
    *,
    column_id: str | None = None,
    inventory_id: InventoryId | None = None,
    column_name: str | None = None,
) -> Column:
    """Retrieve a Column by its column ID, underlying inventory ID, or header name.

    Provide at least one of the three identifiers; the match must be unique.

    !!! example
        ```python
        column = sheet.get_column(column_name="Formulation A")
        ```

    Parameters
    ----------
    column_id : str, optional
        The sheet column ID to match (e.g. ``"COL5"``).
    inventory_id : str, optional
        The underlying inventory ID to match (e.g. ``"INVP015-001"``).
    column_name : str, optional
        The human-readable header name of the column (e.g. ``"Formulation A"``).

    Returns
    -------
    Column
        The matching column.

    Raises
    ------
    AlbertException
        If no identifier is provided, no matching column is found, or multiple
        columns match.
    """

    if not (column_id or inventory_id or column_name):
        raise AlbertException(
            "Must provide at least one of column_id, inventory_id or column_name"
        )
    # Gather candidates matching your filters
    candidates: list[Column] = []
    for col in self.columns:
        if column_id and col.column_id != column_id:
            continue
        if inventory_id and col.inventory_id != inventory_id:
            continue
        if column_name and col.name != column_name:
            continue
        candidates.append(col)

    if not candidates:
        raise AlbertException(
            f"No column found matching id={column_id}, "
            f"inventory_id={inventory_id}, column_name={column_name}"
        )
    if len(candidates) > 1:
        raise AlbertException("Ambiguous column match; please be more specific.")

    return candidates[0]

lock_column

lock_column(
    *,
    column_id: str | None = None,
    inventory_id: InventoryId | None = None,
    column_name: str | None = None,
    locked: bool = True,
) -> Column

Lock or unlock a column in the sheet.

The column can be specified by its sheet column ID (e.g. "COL5"), by the underlying inventory identifier of a formulation/product, or by the displayed header name. By default the column will be locked; pass locked=False to unlock it.

Example

sheet.lock_column(column_name="Formulation A")

Parameters:

Name Type Description Default
column_id str | None

The sheet column ID to match.

None
inventory_id str | None

The inventory identifier of the formulation or product to match.

None
column_name str | None

The displayed header name of the column.

None
locked bool

Whether to lock (True) or unlock (False) the column. Defaults to True.

True

Returns:

Type Description
Column

The column that was updated.

Source code in src/albert/resources/sheets.py
def lock_column(
    self,
    *,
    column_id: str | None = None,
    inventory_id: InventoryId | None = None,
    column_name: str | None = None,
    locked: bool = True,
) -> Column:
    """Lock or unlock a column in the sheet.

    The column can be specified by its sheet column ID (e.g. ``"COL5"``),
    by the underlying inventory identifier of a formulation/product, or by
    the displayed header name. By default the column will be locked; pass
    ``locked=False`` to unlock it.

    !!! example
        ```python
        sheet.lock_column(column_name="Formulation A")
        ```

    Parameters
    ----------
    column_id : str | None
        The sheet column ID to match.
    inventory_id : str | None
        The inventory identifier of the formulation or product to match.
    column_name : str | None
        The displayed header name of the column.
    locked : bool
        Whether to lock (``True``) or unlock (``False``) the column. Defaults to
        ``True``.

    Returns
    -------
    Column
        The column that was updated.
    """

    column = self.get_column(
        column_id=column_id, inventory_id=inventory_id, column_name=column_name
    )

    payload = {
        "data": [
            {
                "operation": "update",
                "attribute": "locked",
                "colIds": [column.column_id],
                "newValue": locked,
            }
        ]
    }

    self.session.patch(
        url=f"/api/v3/worksheet/sheet/{self.id}/columns",
        json=payload,
    )

    self.grid = None

    return self.get_column(column_id=column.column_id)

Column

Column(**data)

Bases: BaseSessionResource

A column in a Sheet.

A Column is a live grid element that carries the session. A column can be a formulation (the most common case for the SDK), a lookup column that displays an inventory attribute, an ingredient name, or another type given by CellType. Its cells are read through cells and written back with update_cells.

Methods:

Name Description
rename

Rename the column.

recolor_cells

Apply a background color to every cell in the column.

Show JSON schema:
{
  "$defs": {
    "AuditFields": {
      "description": "The audit fields for a resource",
      "properties": {
        "by": {
          "default": null,
          "title": "By",
          "type": "string"
        },
        "byName": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Byname"
        },
        "at": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "At"
        }
      },
      "title": "AuditFields",
      "type": "object"
    },
    "CellType": {
      "description": "The kind of content a Cell, Column, or Row holds.\n\nCells, Columns, and Rows all carry a type drawn from this enum, which\ndetermines how the platform interprets their contents. The values most\nrelevant when building formulations are ``INVENTORY`` (an ingredient amount),\n``TOTAL`` (a computed total row), ``FORMULA`` and ``FOR`` (formulation\ncolumns), ``LKP`` (a lookup that displays an inventory attribute), and\n``BLANK`` (an empty cell). The remaining members correspond to specialized\ngrid content such as tags, prices, tasks, results, and apps.",
      "enum": [
        "INV",
        "APP",
        "BLK",
        "Formula",
        "TAG",
        "PRC",
        "PDC",
        "BAT",
        "TOT",
        "TAS",
        "DEF",
        "LKP",
        "FOR",
        "EXTINV",
        "BTI",
        "PRM",
        "PRG",
        "RSL",
        "FNC",
        "WFL",
        "DAC",
        "INT",
        "DAT",
        "NDR",
        "PIC"
      ],
      "title": "CellType",
      "type": "string"
    },
    "Design": {
      "description": "One section of a Sheet, backing the grid for a single [`DesignType`][albert.resources.sheets.DesignType].\n\nA Sheet is made up of stacked sections (Product Design, Process Design,\nResults, and Apps) and each section is a Design. Designs are largely an\ninternal detail: most work is done through the parent [`Sheet`][albert.resources.sheets.Sheet], which\nexposes its Designs as [`product_design`][albert.resources.sheets.Sheet.product_design],\n[`result_design`][albert.resources.sheets.Sheet.result_design], [`app_design`][albert.resources.sheets.Sheet.app_design], and\n[`process_design`][albert.resources.sheets.Sheet.process_design]. A Design is a live grid element that carries the\nsession and lazily loads its rows, columns, and grid on first access.\nMethods\n-------\ngroup_rows(name, child_row_ids, ...) -> RowGroup\n    Create a named row group within this design.\nget_groups(refresh=False) -> list[RowGroup]\n    Get all row groups in this design.",
      "properties": {
        "status": {
          "anyOf": [
            {
              "$ref": "#/$defs/Status"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The status of the resource, optional."
        },
        "Created": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the creation of the resource, optional."
        },
        "Updated": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the update of the resource, optional."
        },
        "state": {
          "anyOf": [
            {
              "$ref": "#/$defs/DesignState"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The display state of the design. Optional. Default is None."
        },
        "albertId": {
          "description": "The Albert ID of the design.",
          "title": "Albertid",
          "type": "string"
        },
        "designType": {
          "anyOf": [
            {
              "$ref": "#/$defs/DesignType"
            },
            {
              "type": "string"
            }
          ],
          "description": "The section of the Sheet this design backs. See [`DesignType`][albert.resources.sheets.DesignType]. Unknown legacy/tenant values parse as plain strings.",
          "title": "Designtype"
        }
      },
      "required": [
        "albertId",
        "designType"
      ],
      "title": "Design",
      "type": "object"
    },
    "DesignState": {
      "description": "The display state of a Design section within a Sheet.",
      "properties": {
        "status": {
          "anyOf": [
            {
              "$ref": "#/$defs/Status"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The status of the resource, optional."
        },
        "Created": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the creation of the resource, optional."
        },
        "Updated": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the update of the resource, optional."
        },
        "collapsed": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": false,
          "description": "Whether the Design section is collapsed in the Sheet view. Default is False.",
          "title": "Collapsed"
        }
      },
      "title": "DesignState",
      "type": "object"
    },
    "DesignType": {
      "description": "The section of a Sheet that a Design represents.\n\nA Sheet is organized into stacked sections, each backed by a Design\n([`Design`][albert.resources.sheets.Design]). The type identifies which section:\n\n- ``PRODUCTS``: Product Design, where formulations are built.\n- ``PROCESS``: Process Design.\n- ``RESULTS``: Results, holding Property Tasks and their data.\n- ``APPS``: Apps, holding insights, reporting, and notes.",
      "enum": [
        "apps",
        "products",
        "results",
        "process",
        "reagents"
      ],
      "title": "DesignType",
      "type": "string"
    },
    "Sheet": {
      "description": "An interactive grid within a Worksheet where formulations are built.\n\nA Sheet is one grid inside a Worksheet ([`Worksheet`][albert.resources.worksheets.Worksheet]).\nIt is organized into stacked sections, each a [`Design`][albert.resources.sheets.Design]: Product Design\n(where formulations are built), Process Design, Results (Property Tasks and\ntheir data), and Apps (insights and notes). Access those sections through\n[`product_design`][albert.resources.sheets.Sheet.product_design], [`process_design`][albert.resources.sheets.Sheet.process_design], [`result_design`][albert.resources.sheets.Sheet.result_design], and\n[`app_design`][albert.resources.sheets.Sheet.app_design].\n\nA Sheet Column can be a formulation (the most common case for the SDK), a\nlookup column that displays an inventory attribute, or an ingredient name.\nRows typically represent ingredients (inventory items) and their amounts.\nAdding a formulation to a Sheet is what registers a Formula inventory item.\n\nThe Sheet is a live grid element that carries the session; its cells, columns,\nand rows are themselves interactive. Retrieve a Sheet from a Worksheet's\n[`sheets`][albert.resources.worksheets.Worksheet.sheets], then edit it in place\nwith the methods below.\n\n!!! example\n    ```python\n    from albert import Albert\n    client = Albert()\n    worksheet = client.worksheets.get_by_project_id(project_id=\"PROA9999999\")\n    sheet = worksheet.sheets[0]\n    print(sheet.grid)\n    ```\nMethods\n-------\nrename(new_name) -> Sheet\n    Rename the sheet.\nadd_formulation(formulation_name, components, ...) -> Column\n    Build a formulation column from a list of components (registers a Formula).\nadd_components_to_formulation(components, ...) -> Column\n    Add components to an existing formulation column.\nadd_formulation_columns(formulation_names, ...) -> list[Column]\n    Add one or more empty formulation columns.\nadd_inventory_row(inventory_id, ...) -> Row\n    Add an ingredient (inventory) row.\nadd_blank_row(row_name, ...) -> Row\n    Add a blank row.\nadd_lookup_row(name, ...) -> Row\n    Add a lookup row.\nadd_app_row(app_id, name, ...) -> Row\n    Add an application row.\nadd_parameter_group_row(parameter_group_id, ...) -> Row\n    Add a parameter group (PRG) row to Process Design.\nadd_blank_column(name, ...) -> Column\n    Add a blank column.\nadd_lookup_column(name, ...) -> Column\n    Add a lookup column.\nadd_function_column(name, ...) -> Column\n    Add a function column.\nadd_property_column(name, attribute_id, ...) -> Column\n    Add a property/result column.\nget_column(...) -> Column\n    Retrieve a column by column ID, inventory ID, or name.\nupdate_cells(cells) -> tuple[list[Cell], list[Cell]]\n    Write changed cells back to the sheet.\npin_columns(col_ids, side) -> None\n    Pin columns to the left or right edge.\nunpin_columns(col_ids) -> None\n    Unpin columns.\nlock_column(...) -> Column\n    Lock or unlock a column.\nhide_column(col_id) -> None\n    Hide a column.\nshow_column(col_id) -> None\n    Show a hidden column.\nset_columns_width(col_ids, width) -> None\n    Set the display width of columns.\ndelete_column(column_id) -> None\n    Delete a column.\ndelete_row(row_id, design_id) -> None\n    Delete a row.",
      "properties": {
        "status": {
          "anyOf": [
            {
              "$ref": "#/$defs/Status"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The status of the resource, optional."
        },
        "Created": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the creation of the resource, optional."
        },
        "Updated": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the update of the resource, optional."
        },
        "albertId": {
          "description": "The Albert ID of the sheet.",
          "title": "Albertid",
          "type": "string"
        },
        "name": {
          "description": "The name of the sheet.",
          "title": "Name",
          "type": "string"
        },
        "Formulas": {
          "description": "References to the formulations present on the sheet.",
          "items": {
            "$ref": "#/$defs/SheetFormulationRef"
          },
          "title": "Formulas",
          "type": "array"
        },
        "hidden": {
          "description": "Whether the sheet is hidden.",
          "title": "Hidden",
          "type": "boolean"
        },
        "isColumnRight": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "When True, copied columns are placed to the right of the source column; when False, to the left.",
          "title": "Iscolumnright"
        },
        "colSizeMode": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Column width sizing mode. Allowed values are ``\"minimum\"`` and ``\"fitToColumn\"``. ``None`` resets to the default grid width.",
          "title": "Colsizemode"
        },
        "Designs": {
          "description": "The Designs (sections) of the sheet.",
          "items": {
            "$ref": "#/$defs/Design"
          },
          "title": "Designs",
          "type": "array"
        },
        "projectId": {
          "description": "The ID of the Project the sheet belongs to (format ``PRO...``).",
          "title": "Projectid",
          "type": "string"
        }
      },
      "required": [
        "albertId",
        "name",
        "hidden",
        "Designs",
        "projectId"
      ],
      "title": "Sheet",
      "type": "object"
    },
    "SheetFormulationRef": {
      "description": "A reference to a formulation in a sheet",
      "properties": {
        "id": {
          "description": "The Albert ID of the inventory item that is the formulation",
          "title": "Id",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The name of the formulation",
          "title": "Name"
        },
        "hidden": {
          "description": "Whether the formulation is hidden",
          "title": "Hidden",
          "type": "boolean"
        }
      },
      "required": [
        "id",
        "hidden"
      ],
      "title": "SheetFormulationRef",
      "type": "object"
    },
    "Status": {
      "description": "The status of a resource.\n\nAttributes\n----------\nACTIVE : str\n    The resource is fully operational and visible in normal operations.\nINACTIVE : str\n    The resource is hidden from normal operations and disabled from use.",
      "enum": [
        "active",
        "inactive"
      ],
      "title": "Status",
      "type": "string"
    }
  },
  "description": "A column in a Sheet.\n\nA Column is a live grid element that carries the session. A column can be a\nformulation (the most common case for the SDK), a lookup column that displays\nan inventory attribute, an ingredient name, or another type given by\n[`CellType`][albert.resources.sheets.CellType]. Its cells are read through [`cells`][albert.resources.sheets.Column.cells] and written back\nwith [`update_cells`][albert.resources.sheets.Sheet.update_cells].\nMethods\n-------\nrename(new_name) -> Column\n    Rename the column.\nrecolor_cells(color) -> tuple[list[Cell], list[Cell]]\n    Apply a background color to every cell in the column.",
  "properties": {
    "status": {
      "anyOf": [
        {
          "$ref": "#/$defs/Status"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The status of the resource, optional."
    },
    "Created": {
      "anyOf": [
        {
          "$ref": "#/$defs/AuditFields"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Audit fields for the creation of the resource, optional."
    },
    "Updated": {
      "anyOf": [
        {
          "$ref": "#/$defs/AuditFields"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Audit fields for the update of the resource, optional."
    },
    "colId": {
      "description": "The ID of the column.",
      "title": "Colid",
      "type": "string"
    },
    "name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The header name of the column. Optional. Default is None.",
      "title": "Name"
    },
    "type": {
      "anyOf": [
        {
          "$ref": "#/$defs/CellType"
        },
        {
          "type": "string"
        }
      ],
      "description": "The type of the column. Allowed values are the same as for [`CellType`][albert.resources.sheets.CellType].",
      "title": "Type"
    },
    "sheet": {
      "$ref": "#/$defs/Sheet",
      "description": "The sheet the column belongs to."
    },
    "inventory_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "For a formulation column, the underlying inventory ID (format ``INV...``). Optional. Default is None.",
      "title": "Inventory Id"
    },
    "locked": {
      "default": false,
      "description": "Whether the column is locked against edits. Default is False.",
      "title": "Locked",
      "type": "boolean"
    },
    "hidden": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Whether the column is hidden. Optional. Default is None.",
      "title": "Hidden"
    },
    "pinned": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The edge the column is pinned to (``\"left\"`` or ``\"right\"``), or None.",
      "title": "Pinned"
    },
    "column_width": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The display width of the column (e.g. ``\"142px\"``), or None.",
      "title": "Column Width"
    }
  },
  "required": [
    "colId",
    "type",
    "sheet"
  ],
  "title": "Column",
  "type": "object"
}

Fields:

Validators:

Source code in src/albert/core/shared/models/base.py
def __init__(self, **data):
    super().__init__(**data)
    self._session = data.get("session")

column_id

column_id: str

The ID of the column.

name

name: str | None = None

The header name of the column. Optional. Default is None.

type

type: CellType | str

The type of the column. Allowed values are the same as for CellType.

sheet

sheet: Sheet

The sheet the column belongs to.

inventory_id

inventory_id: str | None = None

For a formulation column, the underlying inventory ID (format INV...). Optional. Default is None.

locked

locked: bool = False

Whether the column is locked against edits. Default is False.

hidden

hidden: bool | None = None

Whether the column is hidden. Optional. Default is None.

pinned

pinned: str | None = None

The edge the column is pinned to ("left" or "right"), or None.

column_width

column_width: str | None = None

The display width of the column (e.g. "142px"), or None.

df_name

df_name: str

cells

cells: Series

This column's cells as a pandas Series keyed by row id.

Empty cells may appear as NaN floats (pandas padding); check isinstance(value, Cell) before using a value.

rename

rename(new_name)

Rename this column.

Example

column = sheet.get_column(column_name="Formulation A")
column.rename("Formulation A (rev 2)")

Parameters:

Name Type Description Default
new_name str

The new header name for the column.

required

Returns:

Type Description
Column

This column, with its name updated.

Source code in src/albert/resources/sheets.py
def rename(self, new_name):
    """Rename this column.

    !!! example
        ```python
        column = sheet.get_column(column_name="Formulation A")
        column.rename("Formulation A (rev 2)")
        ```

    Parameters
    ----------
    new_name : str
        The new header name for the column.

    Returns
    -------
    Column
        This column, with its name updated.
    """
    payload = {
        "data": [
            {
                "operation": "update",
                "attribute": "name",
                "colId": self.column_id,
                "oldValue": self.name,
                "newValue": new_name,
            }
        ]
    }

    self.session.patch(
        url=f"/api/v3/worksheet/sheet/{self.sheet.id}/columns",
        json=payload,
    )

    if self.sheet._grid is not None:  # if I have a grid loaded into memory, adjust it.
        self.sheet.grid = None
        # self.sheet._grid.rename(axis=1, mapper={self.name:new_name})
    self.name = new_name
    return self

recolor_cells

recolor_cells(color: CellColor)

Apply a background color to every cell in this column.

Example

from albert.resources.sheets import CellColor
column = sheet.get_column(column_name="Formulation A")
column.recolor_cells(CellColor.BLUE)

Parameters:

Name Type Description Default
color CellColor

The background color to apply.

required

Returns:

Type Description
tuple[list[Cell], list[Cell]]

A (updated, failed) pair, as returned by update_cells.

Source code in src/albert/resources/sheets.py
def recolor_cells(self, color: CellColor):
    """Apply a background color to every cell in this column.

    !!! example
        ```python
        from albert.resources.sheets import CellColor
        column = sheet.get_column(column_name="Formulation A")
        column.recolor_cells(CellColor.BLUE)
        ```

    Parameters
    ----------
    color : CellColor
        The background color to apply.

    Returns
    -------
    tuple[list[Cell], list[Cell]]
        A ``(updated, failed)`` pair, as returned by [`update_cells`][albert.resources.sheets.Sheet.update_cells].
    """
    new_cells = []
    for c in self.cells:
        cell_copy = c.model_copy(update={"format": {"bgColor": color.value}})
        new_cells.append(cell_copy)
    return self.sheet.update_cells(cells=new_cells)

Row

Row(**data)

Bases: BaseSessionResource

A row in a Sheet.

A Row is a live grid element that carries the session. Rows typically represent ingredients (inventory items) and their amounts, but a row can also be a total, lookup, app, or blank row per its type. Each row belongs to a specific Design section of the sheet. Its cells are read through cells and written back with update_cells.

Methods:

Name Description
recolor_cells

Apply a background color to every cell in the row.

Show JSON schema:
{
  "$defs": {
    "AuditFields": {
      "description": "The audit fields for a resource",
      "properties": {
        "by": {
          "default": null,
          "title": "By",
          "type": "string"
        },
        "byName": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Byname"
        },
        "at": {
          "anyOf": [
            {
              "format": "date-time",
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "At"
        }
      },
      "title": "AuditFields",
      "type": "object"
    },
    "CellType": {
      "description": "The kind of content a Cell, Column, or Row holds.\n\nCells, Columns, and Rows all carry a type drawn from this enum, which\ndetermines how the platform interprets their contents. The values most\nrelevant when building formulations are ``INVENTORY`` (an ingredient amount),\n``TOTAL`` (a computed total row), ``FORMULA`` and ``FOR`` (formulation\ncolumns), ``LKP`` (a lookup that displays an inventory attribute), and\n``BLANK`` (an empty cell). The remaining members correspond to specialized\ngrid content such as tags, prices, tasks, results, and apps.",
      "enum": [
        "INV",
        "APP",
        "BLK",
        "Formula",
        "TAG",
        "PRC",
        "PDC",
        "BAT",
        "TOT",
        "TAS",
        "DEF",
        "LKP",
        "FOR",
        "EXTINV",
        "BTI",
        "PRM",
        "PRG",
        "RSL",
        "FNC",
        "WFL",
        "DAC",
        "INT",
        "DAT",
        "NDR",
        "PIC"
      ],
      "title": "CellType",
      "type": "string"
    },
    "Design": {
      "description": "One section of a Sheet, backing the grid for a single [`DesignType`][albert.resources.sheets.DesignType].\n\nA Sheet is made up of stacked sections (Product Design, Process Design,\nResults, and Apps) and each section is a Design. Designs are largely an\ninternal detail: most work is done through the parent [`Sheet`][albert.resources.sheets.Sheet], which\nexposes its Designs as [`product_design`][albert.resources.sheets.Sheet.product_design],\n[`result_design`][albert.resources.sheets.Sheet.result_design], [`app_design`][albert.resources.sheets.Sheet.app_design], and\n[`process_design`][albert.resources.sheets.Sheet.process_design]. A Design is a live grid element that carries the\nsession and lazily loads its rows, columns, and grid on first access.\nMethods\n-------\ngroup_rows(name, child_row_ids, ...) -> RowGroup\n    Create a named row group within this design.\nget_groups(refresh=False) -> list[RowGroup]\n    Get all row groups in this design.",
      "properties": {
        "status": {
          "anyOf": [
            {
              "$ref": "#/$defs/Status"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The status of the resource, optional."
        },
        "Created": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the creation of the resource, optional."
        },
        "Updated": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the update of the resource, optional."
        },
        "state": {
          "anyOf": [
            {
              "$ref": "#/$defs/DesignState"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The display state of the design. Optional. Default is None."
        },
        "albertId": {
          "description": "The Albert ID of the design.",
          "title": "Albertid",
          "type": "string"
        },
        "designType": {
          "anyOf": [
            {
              "$ref": "#/$defs/DesignType"
            },
            {
              "type": "string"
            }
          ],
          "description": "The section of the Sheet this design backs. See [`DesignType`][albert.resources.sheets.DesignType]. Unknown legacy/tenant values parse as plain strings.",
          "title": "Designtype"
        }
      },
      "required": [
        "albertId",
        "designType"
      ],
      "title": "Design",
      "type": "object"
    },
    "DesignState": {
      "description": "The display state of a Design section within a Sheet.",
      "properties": {
        "status": {
          "anyOf": [
            {
              "$ref": "#/$defs/Status"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The status of the resource, optional."
        },
        "Created": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the creation of the resource, optional."
        },
        "Updated": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the update of the resource, optional."
        },
        "collapsed": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": false,
          "description": "Whether the Design section is collapsed in the Sheet view. Default is False.",
          "title": "Collapsed"
        }
      },
      "title": "DesignState",
      "type": "object"
    },
    "DesignType": {
      "description": "The section of a Sheet that a Design represents.\n\nA Sheet is organized into stacked sections, each backed by a Design\n([`Design`][albert.resources.sheets.Design]). The type identifies which section:\n\n- ``PRODUCTS``: Product Design, where formulations are built.\n- ``PROCESS``: Process Design.\n- ``RESULTS``: Results, holding Property Tasks and their data.\n- ``APPS``: Apps, holding insights, reporting, and notes.",
      "enum": [
        "apps",
        "products",
        "results",
        "process",
        "reagents"
      ],
      "title": "DesignType",
      "type": "string"
    },
    "RowConfig": {
      "description": "Configuration for an APP or location-type row.",
      "properties": {
        "option": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Option"
        },
        "value": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "title": "Value"
        }
      },
      "title": "RowConfig",
      "type": "object"
    },
    "Sheet": {
      "description": "An interactive grid within a Worksheet where formulations are built.\n\nA Sheet is one grid inside a Worksheet ([`Worksheet`][albert.resources.worksheets.Worksheet]).\nIt is organized into stacked sections, each a [`Design`][albert.resources.sheets.Design]: Product Design\n(where formulations are built), Process Design, Results (Property Tasks and\ntheir data), and Apps (insights and notes). Access those sections through\n[`product_design`][albert.resources.sheets.Sheet.product_design], [`process_design`][albert.resources.sheets.Sheet.process_design], [`result_design`][albert.resources.sheets.Sheet.result_design], and\n[`app_design`][albert.resources.sheets.Sheet.app_design].\n\nA Sheet Column can be a formulation (the most common case for the SDK), a\nlookup column that displays an inventory attribute, or an ingredient name.\nRows typically represent ingredients (inventory items) and their amounts.\nAdding a formulation to a Sheet is what registers a Formula inventory item.\n\nThe Sheet is a live grid element that carries the session; its cells, columns,\nand rows are themselves interactive. Retrieve a Sheet from a Worksheet's\n[`sheets`][albert.resources.worksheets.Worksheet.sheets], then edit it in place\nwith the methods below.\n\n!!! example\n    ```python\n    from albert import Albert\n    client = Albert()\n    worksheet = client.worksheets.get_by_project_id(project_id=\"PROA9999999\")\n    sheet = worksheet.sheets[0]\n    print(sheet.grid)\n    ```\nMethods\n-------\nrename(new_name) -> Sheet\n    Rename the sheet.\nadd_formulation(formulation_name, components, ...) -> Column\n    Build a formulation column from a list of components (registers a Formula).\nadd_components_to_formulation(components, ...) -> Column\n    Add components to an existing formulation column.\nadd_formulation_columns(formulation_names, ...) -> list[Column]\n    Add one or more empty formulation columns.\nadd_inventory_row(inventory_id, ...) -> Row\n    Add an ingredient (inventory) row.\nadd_blank_row(row_name, ...) -> Row\n    Add a blank row.\nadd_lookup_row(name, ...) -> Row\n    Add a lookup row.\nadd_app_row(app_id, name, ...) -> Row\n    Add an application row.\nadd_parameter_group_row(parameter_group_id, ...) -> Row\n    Add a parameter group (PRG) row to Process Design.\nadd_blank_column(name, ...) -> Column\n    Add a blank column.\nadd_lookup_column(name, ...) -> Column\n    Add a lookup column.\nadd_function_column(name, ...) -> Column\n    Add a function column.\nadd_property_column(name, attribute_id, ...) -> Column\n    Add a property/result column.\nget_column(...) -> Column\n    Retrieve a column by column ID, inventory ID, or name.\nupdate_cells(cells) -> tuple[list[Cell], list[Cell]]\n    Write changed cells back to the sheet.\npin_columns(col_ids, side) -> None\n    Pin columns to the left or right edge.\nunpin_columns(col_ids) -> None\n    Unpin columns.\nlock_column(...) -> Column\n    Lock or unlock a column.\nhide_column(col_id) -> None\n    Hide a column.\nshow_column(col_id) -> None\n    Show a hidden column.\nset_columns_width(col_ids, width) -> None\n    Set the display width of columns.\ndelete_column(column_id) -> None\n    Delete a column.\ndelete_row(row_id, design_id) -> None\n    Delete a row.",
      "properties": {
        "status": {
          "anyOf": [
            {
              "$ref": "#/$defs/Status"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The status of the resource, optional."
        },
        "Created": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the creation of the resource, optional."
        },
        "Updated": {
          "anyOf": [
            {
              "$ref": "#/$defs/AuditFields"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Audit fields for the update of the resource, optional."
        },
        "albertId": {
          "description": "The Albert ID of the sheet.",
          "title": "Albertid",
          "type": "string"
        },
        "name": {
          "description": "The name of the sheet.",
          "title": "Name",
          "type": "string"
        },
        "Formulas": {
          "description": "References to the formulations present on the sheet.",
          "items": {
            "$ref": "#/$defs/SheetFormulationRef"
          },
          "title": "Formulas",
          "type": "array"
        },
        "hidden": {
          "description": "Whether the sheet is hidden.",
          "title": "Hidden",
          "type": "boolean"
        },
        "isColumnRight": {
          "anyOf": [
            {
              "type": "boolean"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "When True, copied columns are placed to the right of the source column; when False, to the left.",
          "title": "Iscolumnright"
        },
        "colSizeMode": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Column width sizing mode. Allowed values are ``\"minimum\"`` and ``\"fitToColumn\"``. ``None`` resets to the default grid width.",
          "title": "Colsizemode"
        },
        "Designs": {
          "description": "The Designs (sections) of the sheet.",
          "items": {
            "$ref": "#/$defs/Design"
          },
          "title": "Designs",
          "type": "array"
        },
        "projectId": {
          "description": "The ID of the Project the sheet belongs to (format ``PRO...``).",
          "title": "Projectid",
          "type": "string"
        }
      },
      "required": [
        "albertId",
        "name",
        "hidden",
        "Designs",
        "projectId"
      ],
      "title": "Sheet",
      "type": "object"
    },
    "SheetFormulationRef": {
      "description": "A reference to a formulation in a sheet",
      "properties": {
        "id": {
          "description": "The Albert ID of the inventory item that is the formulation",
          "title": "Id",
          "type": "string"
        },
        "name": {
          "anyOf": [
            {
              "type": "string"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "The name of the formulation",
          "title": "Name"
        },
        "hidden": {
          "description": "Whether the formulation is hidden",
          "title": "Hidden",
          "type": "boolean"
        }
      },
      "required": [
        "id",
        "hidden"
      ],
      "title": "SheetFormulationRef",
      "type": "object"
    },
    "Status": {
      "description": "The status of a resource.\n\nAttributes\n----------\nACTIVE : str\n    The resource is fully operational and visible in normal operations.\nINACTIVE : str\n    The resource is hidden from normal operations and disabled from use.",
      "enum": [
        "active",
        "inactive"
      ],
      "title": "Status",
      "type": "string"
    }
  },
  "description": "A row in a Sheet.\n\nA Row is a live grid element that carries the session. Rows typically\nrepresent ingredients (inventory items) and their amounts, but a row can also\nbe a total, lookup, app, or blank row per its [`type`][albert.resources.sheets.Row.type]. Each row belongs\nto a specific [`Design`][albert.resources.sheets.Design] section of the [`sheet`][albert.resources.sheets.Row.sheet]. Its cells are read\nthrough [`cells`][albert.resources.sheets.Row.cells] and written back with [`update_cells`][albert.resources.sheets.Sheet.update_cells].\nMethods\n-------\nrecolor_cells(color) -> tuple[list[Cell], list[Cell]]\n    Apply a background color to every cell in the row.",
  "properties": {
    "status": {
      "anyOf": [
        {
          "$ref": "#/$defs/Status"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The status of the resource, optional."
    },
    "Created": {
      "anyOf": [
        {
          "$ref": "#/$defs/AuditFields"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Audit fields for the creation of the resource, optional."
    },
    "Updated": {
      "anyOf": [
        {
          "$ref": "#/$defs/AuditFields"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Audit fields for the update of the resource, optional."
    },
    "rowId": {
      "description": "The ID of the row.",
      "title": "Rowid",
      "type": "string"
    },
    "type": {
      "anyOf": [
        {
          "$ref": "#/$defs/CellType"
        },
        {
          "type": "string"
        }
      ],
      "description": "The type of the row. Allowed values are the same as for [`CellType`][albert.resources.sheets.CellType].",
      "title": "Type"
    },
    "design": {
      "$ref": "#/$defs/Design",
      "description": "The Design (section) the row belongs to."
    },
    "sheet": {
      "$ref": "#/$defs/Sheet",
      "description": "The sheet the row belongs to."
    },
    "name": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The display name of the row. Optional. Default is None.",
      "title": "Name"
    },
    "id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "For an ingredient row, the inventory ID of the item (format ``INV...``). Optional. Default is None.",
      "title": "Id"
    },
    "manufacturer": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The manufacturer of the row's inventory item. Optional. Default is None.",
      "title": "Manufacturer"
    },
    "config": {
      "anyOf": [
        {
          "$ref": "#/$defs/RowConfig"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "Configuration for APP or location-scoped rows. Optional. Default is None."
    },
    "parent_row_id": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "description": "The row ID of the group header this row belongs to. None if not grouped.",
      "title": "Parent Row Id"
    },
    "child_row_ids": {
      "description": "Row IDs of rows grouped under this row. Non-empty only on group header rows.",
      "items": {
        "type": "string"
      },
      "title": "Child Row Ids",
      "type": "array"
    }
  },
  "required": [
    "rowId",
    "type",
    "design",
    "sheet"
  ],
  "title": "Row",
  "type": "object"
}

Fields:

Validators:

Source code in src/albert/core/shared/models/base.py
def __init__(self, **data):
    super().__init__(**data)
    self._session = data.get("session")

row_id

row_id: str

The ID of the row.

type

type: CellType | str

The type of the row. Allowed values are the same as for CellType.

design

design: Design

The Design (section) the row belongs to.

sheet

sheet: Sheet

The sheet the row belongs to.

name

name: str | None = None

The display name of the row. Optional. Default is None.

inventory_id

inventory_id: str | None = None

For an ingredient row, the inventory ID of the item (format INV...). Optional. Default is None.

manufacturer

manufacturer: str | None = None

The manufacturer of the row's inventory item. Optional. Default is None.

config

config: RowConfig | None = None

Configuration for APP or location-scoped rows. Optional. Default is None.

parent_row_id

parent_row_id: str | None = None

The row ID of the group header this row belongs to. None if not grouped.

child_row_ids

child_row_ids: list[str]

Row IDs of rows grouped under this row. Non-empty only on group header rows.

row_unique_id

row_unique_id

is_group_header

is_group_header: bool

True when this row is the header of a collapsed row group.

cells

cells: Series

This row's cells as a pandas Series keyed by column df-name.

Empty cells may appear as NaN floats (pandas padding); check isinstance(value, Cell) before using a value.

recolor_cells

recolor_cells(color: CellColor)

Apply a background color to every cell in this row.

Example

from albert.resources.sheets import CellColor
row = sheet.rows[0]
row.recolor_cells(CellColor.RED)

Parameters:

Name Type Description Default
color CellColor

The background color to apply.

required

Returns:

Type Description
tuple[list[Cell], list[Cell]]

A (updated, failed) pair, as returned by update_cells.

Source code in src/albert/resources/sheets.py
def recolor_cells(self, color: CellColor):
    """Apply a background color to every cell in this row.

    !!! example
        ```python
        from albert.resources.sheets import CellColor
        row = sheet.rows[0]
        row.recolor_cells(CellColor.RED)
        ```

    Parameters
    ----------
    color : CellColor
        The background color to apply.

    Returns
    -------
    tuple[list[Cell], list[Cell]]
        A ``(updated, failed)`` pair, as returned by [`update_cells`][albert.resources.sheets.Sheet.update_cells].
    """
    new_cells = []
    for c in self.cells:
        cell_copy = c.model_copy(update={"format": {"bgColor": color.value}})
        cell_copy.format = {"bgColor": color.value}
        new_cells.append(cell_copy)
    return self.sheet.update_cells(cells=new_cells)