PHP SDK: Worksheet: read Excel and CSV sheets
Get a worksheet with $document->sheet(). Cell addresses and row numbers start at one; sheet-selection indexes start at zero. A file may contain several sections, merged cells, and empty rows. Reading does not remove them. These methods work with data already extracted from the file. Check $document->complete() before processing a whole file.
name
name(): string
The sheet's name in the original file.
$document = $ctx->documents()->fromBytes("SKU;Stock\nTEST-001;17", 'report.csv');
$sheet = $document->sheet();
$ctx->log($sheet->name());
rows
rows(): array
All rows, without assuming where headers are. Empty rows and gaps are preserved. Array rows and columns use zero-based indexes.
$document = $ctx->documents()->fromBytes("SKU;Stock\nTEST-001;17", 'report.csv');
$sheet = $document->sheet();
$rows = $sheet->rows();
rowCount
rowCount(): int
The number of extracted rows, including empty ones. This is not a record count: a file can have headers, totals, and multiple sections.
$document = $ctx->documents()->fromBytes("SKU;Stock\nTEST-001;17", 'report.csv');
$sheet = $document->sheet();
$count = $sheet->rowCount();
columnCount
columnCount(): int
The width of the longest extracted row. Missing cells in shorter rows remain empty.
$document = $ctx->documents()->fromBytes("SKU;Stock\nTEST-001;17", 'report.csv');
$sheet = $document->sheet();
$count = $sheet->columnCount();
cell
cell(string $address, bool $resolveMerged = false): string|int|float|bool|null
Read a value at an A1 address, including absolute addresses such as $A$1. Returns the original scalar type or null. With resolveMerged=true, reads the top-left cell's value for a merged area. Merged cells are not filled by default. Addresses outside the extracted area return null, so check complete() first.
$document = $ctx->documents()->fromBytes("SKU;Stock\nTEST-001;17", 'report.csv');
$sheet = $document->sheet();
$stock = $sheet->cell('B2');
$title = $sheet->cell('C1', true);
row
row(int $number): array
Read a row by its one-based number. Rows outside the sheet return an empty array; zero or negative numbers raise an error.
$document = $ctx->documents()->fromBytes("SKU;Stock\nTEST-001;17", 'report.csv');
$sheet = $document->sheet();
$values = $sheet->row(2);
column
column(int|string $column, int $startRow = 1, ?int $endRow = null): array
Read a column by letters or one-based number. startRow and endRow are inclusive. Missing values stay null.
$document = $ctx->documents()->fromBytes("SKU;Stock\nTEST-001;17", 'report.csv');
$sheet = $document->sheet();
$stocks = $sheet->column('B', 2);
range
range(string $range, bool $resolveMerged = false): array
Read a rectangular matrix such as A1:C10, including empty cells. The limit is 50,000 cells. resolveMerged=true repeats the merged area's anchor value only in the returned matrix. Reversed or invalid ranges raise an error.
$document = $ctx->documents()->fromBytes("SKU;Stock\nTEST-001;17", 'report.csv');
$sheet = $document->sheet();
$values = $sheet->range('A1:B2');
nonEmptyRows
nonEmptyRows(): array
Non-empty rows keyed by their original one-based row numbers. Values 0 and false count as data.
$document = $ctx->documents()->fromBytes("SKU;Stock\nTEST-001;17", 'report.csv');
$sheet = $document->sheet();
$rows = $sheet->nonEmptyRows();
find
find(string $text, bool $exact = false, int $limit = 100): array
Search values without regard to case. exact=true requires a whole-value match. Returns address and value, at most limit matches (1–1000). Formula expressions are not executed or searched in place of their values.
$document = $ctx->documents()->fromBytes("SKU;Stock\nTEST-001;17", 'report.csv');
$sheet = $document->sheet();
$matches = $sheet->find('TEST-', false, 20);
findHeader
findHeader(array $labels, int $maxRows = 50): ?int
Find the first row containing all requested labels. Comparison ignores case and surrounding spaces. The first 50 rows are checked by default; maxRows can be 1–5,000. Returns null if no header is found. Use explicit ranges for a multi-level header.
$document = $ctx->documents()->fromBytes("SKU;Stock\nTEST-001;17", 'report.csv');
$sheet = $document->sheet();
$header = $sheet->findHeader(['SKU', 'Stock']);
merged
merged(): array
Merged XLSX/XLS ranges, such as A1:C1. Values in other cells are not duplicated by default. CSV files have no merged cells.
$document = $ctx->documents()->fromBytes("SKU;Stock\nTEST-001;17", 'report.csv');
$sheet = $document->sheet();
$ranges = $sheet->merged();
formula
formula(string $address): ?string
The original XLSX formula with a leading =, or null. Read the calculated value with cell() and the expression with formula(). Shared formulas in dependent cells may not contain the full expression; consult the cached value when needed.
$document = $ctx->documents()->fromBytes("SKU;Stock\nTEST-001;17", 'report.csv');
$sheet = $document->sheet();
$formula = $sheet->formula('B2');
error
error(string $address): ?string
The stored XLSX error, such as #DIV/0!, or null. Errors are not silently replaced with zero.
$document = $ctx->documents()->fromBytes("SKU;Stock\nTEST-001;17", 'report.csv');
$sheet = $document->sheet();
$error = $sheet->error('B2');
records
records(int $headerRow = 1, ?int $startRow = null, ?int $endRow = null): array
Turn a selected section into records. headerRow is the one-based header row; startRow and endRow set an inclusive data range. headerRow=0 uses column letters A, B, C as keys. Empty rows are skipped. Blank labels become column letters, and duplicate labels get _2, _3, and so on without losing fields. Totals and notes are not detected automatically; set the range explicitly.
$document = $ctx->documents()->fromBytes("SKU;Stock\nTEST-001;17", 'report.csv');
$sheet = $document->sheet();
$records = $sheet->records(1, 2);
foreach ($records as $record) $ctx->emit(['sku' => $record['SKU'], 'stock' => (int) $record['Stock']]);
structure
structure(): array
An anonymized layout for AI planning: rows, columns, merged, and a sample of the first 24×16 cells. The sample contains only e (empty), s (string), n (number), and b (Boolean). Sheet names, headers, values, links, and formulas are omitted. This method does not call a model.
$document = $ctx->documents()->fromBytes("SKU;Stock\nTEST-001;17", 'report.csv');
$sheet = $document->sheet();
$layout = $sheet->structure();
calculation
calculation(string $address): string
XLSX calculation status: calculated, unsupported, external_reference, circular_reference, error, or limit. not_calculated means a formula exists but was not recalculated; not_formula means this is a regular cell. Unsupported formulas give an explicit error, not zero or an undisclosed fallback to an old value.
$document = $ctx->documents()->fromBytes("Name;Quantity\nItem;17", 'report.csv');
$sheet = $document->sheet();
$status = $sheet->calculation('B2');
cachedValue
cachedValue(string $address): string|int|float|bool|null
The value saved in an XLSX file by its author before recalculation. It may be missing or stale. For a regular cell it matches cell(). Use it only as an explicit fallback; the SDK returns recalculated values by default.
$document = $ctx->documents()->fromBytes("Name;Quantity\nItem;17", 'report.csv');
$sheet = $document->sheet();
$saved = $sheet->cachedValue('B2');