Skip to content

Documentation

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');