Structured Cell Renderer
Create your own custom schema on cell and render custom cells like Sparklines, document objects etc
The Structured Cell Renderer allows you to render custom visualizations and content within spreadsheet cells. Instead of displaying plain text, you can render rich content like sparklines, charts, or any custom component.
Overview
Structured results are special cell values that contain both data and rendering instructions. The spreadsheet automatically detects these structured values and renders them using the StructuredResultRenderer component.
Supported Structured Results
Sparklines
Sparklines are small inline charts that fit within a cell, perfect for visualizing trends in data.
import type { SparkLineResult } from "@rowsncolumns/common-types";
const sparklineValue: SparkLineResult = {
kind: "sparkline",
data: [1, 5, 3, 7, 4, 9, 6],
formattedValue: "Trend", // Fallback text
};The sparkline will automatically render as a mini chart within the cell.
Custom Structured Results
You can create your own structured result types by extending the StructuredResult interface:
import type { StructuredResult } from "@rowsncolumns/common-types";
type MyCustomResult = {
kind: "custom";
data: any;
formattedValue: string;
} & StructuredResult;Using Structured Cells
1. Define Your Custom Cell Data Type
import type { CellData, StructuredResult } from "@rowsncolumns/spreadsheet";
type MyStructuredResult = {
kind: "sparkline" | "custom";
data: any[];
formattedValue: string;
} & StructuredResult;
type MyCustomCellData = CellData<MyStructuredResult>;2. Create Structured Cell Values
import { useSpreadsheetState } from "@rowsncolumns/spreadsheet-state";
const { onChangeBatch } = useSpreadsheetState({
// ... other props
});
// Add a sparkline to a cell
onChangeBatch(
sheetId,
{
startRowIndex: 1,
endRowIndex: 1,
startColumnIndex: 1,
endColumnIndex: 1,
},
[{
ev: {
structuredValue: {
kind: "sparkline",
data: [1, 5, 3, 7, 4, 9, 6],
formattedValue: "Trend",
}
}
}]
);3. Custom Renderer (Optional)
If you need custom rendering logic beyond sparklines, you can provide your own StructuredResult component to CanvasGrid:
import { Text } from "react-konva";
import type { StructuredResultProps } from "@rowsncolumns/spreadsheet";
const MyStructuredRenderer = (props: StructuredResultProps) => {
const { structuredValue, ...rest } = props;
if (structuredValue?.kind === "custom") {
return (
<Text
{...rest}
text={`Custom: ${structuredValue.formattedValue}`}
fill="blue"
/>
);
}
// Fallback to default renderer
return null;
};
// Use in CanvasGrid
<CanvasGrid
StructuredResult={MyStructuredRenderer}
// ... other props
/>Getting Structured Values
You can access structured cell values through the spreadsheet state:
const { getUserEnteredExtendedValue, getEffectiveExtendedValue } = useSpreadsheetState({
// ... props
});
// Get the user-entered structured value
const userValue = getUserEnteredExtendedValue(sheetId, rowIndex, columnIndex);
console.log(userValue?.structuredValue);
// Get the computed/formatted structured value
const effectiveValue = getEffectiveExtendedValue(sheetId, rowIndex, columnIndex);
console.log(effectiveValue?.structuredValue);Formulas and Structured Results
You can create formulas that return structured results:
import type FormulaParser from "@rowsncolumns/fast-formula-parser";
import type { FunctionArgument } from "@rowsncolumns/calculator";
const SPARKLINE = (parser: FormulaParser, dataRange: FunctionArgument) => {
// Extract values from the range
const values = dataRange.value; // Array of cell values
return {
kind: "sparkline",
data: values.map(Number),
formattedValue: `Sparkline(${values.length} points)`,
};
};
// Register the function
const functions = {
...defaultFunctions,
SPARKLINE,
};
// Use in a cell
// =SPARKLINE(A1:A10)Complete Example
import React, { useState } from "react";
import {
SpreadsheetProvider,
CanvasGrid,
type CellData,
type StructuredResult,
} from "@rowsncolumns/spreadsheet";
import { useSpreadsheetState } from "@rowsncolumns/spreadsheet-state";
type MyStructuredResult = {
kind: "sparkline";
data: number[];
formattedValue: string;
} & StructuredResult;
type MyCustomCellData = CellData<MyStructuredResult>;
function SpreadsheetWithStructuredCells() {
const [sheets, setSheets] = useState([
{ sheetId: 1, rowCount: 100, columnCount: 26, title: "Sheet 1" }
]);
const [sheetData, setSheetData] = useState<SheetData<MyCustomCellData>>({
1: [
null,
{
values: [
null,
{
ev: {
structuredValue: {
kind: "sparkline",
data: [1, 5, 3, 7, 4, 9, 6, 8, 5],
formattedValue: "Sales Trend",
},
},
},
],
},
],
});
const {
activeCell,
activeSheetId,
selections,
getCellData,
// ... other hook values
} = useSpreadsheetState({
sheets,
sheetData,
onChangeSheets: setSheets,
onChangeSheetData: setSheetData,
});
return (
<SpreadsheetProvider>
<CanvasGrid
sheetId={activeSheetId}
activeCell={activeCell}
selections={selections}
getCellData={getCellData}
// ... other props
/>
</SpreadsheetProvider>
);
}Use Cases
Visualizing Trends
Sparklines are perfect for showing trends in financial data, metrics, or time series:
// Sales data with inline trend visualization
const salesData = {
ev: {
structuredValue: {
kind: "sparkline",
data: monthlySales, // [100, 120, 115, 140, ...]
formattedValue: "$1,234 total",
},
},
};Custom Indicators
Create custom visual indicators for status, progress, or ratings:
type StatusResult = {
kind: "status";
status: "good" | "warning" | "error";
formattedValue: string;
} & StructuredResult;Performance Considerations
Structured results are rendered using canvas (react-konva), providing excellent performance even with many cells
Complex visualizations should be optimized to avoid rendering bottlenecks
Consider using
formattedValueas a text fallback for export and copy operations
Limitations
Structured results are visual-only and don't affect cell value calculations
When copying cells with structured results, the
formattedValueis used as textExcel export will show the
formattedValueas plain text
Last updated
Was this helpful?