Conditional Formatting
Conditional Formatting
Section titled “Conditional Formatting”The ConditionalFormattingPlugin applies visual formatting rules to cells based on their values. It supports four condition types: value-based styling, gradient color scales, data bars, and icon sets.
View source code
import { useRef, useEffect, useState } from 'react';import { Spreadsheet } from '@witqq/spreadsheet-react';import type { SpreadsheetRef } from '@witqq/spreadsheet-react';import type { ColumnDef } from '@witqq/spreadsheet';import { ConditionalFormattingPlugin } from '@witqq/spreadsheet-plugins';import { DemoWrapper } from './DemoWrapper';import { useSiteTheme } from './useSiteTheme';
interface StudentRow { name: string; math: number; science: number; english: number; average: number;}
const columns: ColumnDef[] = [ { key: 'name', title: 'Student', width: 140 }, { key: 'math', title: 'Math', width: 100, type: 'number' }, { key: 'science', title: 'Science', width: 100, type: 'number' }, { key: 'english', title: 'English', width: 100, type: 'number' }, { key: 'average', title: 'Average', width: 100, type: 'number' },];
function makeStudent(name: string, math: number, science: number, english: number): StudentRow { return { name, math, science, english, average: Math.round((math + science + english) / 3) };}
const data: StudentRow[] = [ makeStudent('Alice Johnson', 92, 88, 95), makeStudent('Bob Smith', 45, 72, 38), makeStudent('Carol Davis', 78, 91, 82), makeStudent('Dan Wilson', 31, 55, 67), makeStudent('Eve Martinez', 88, 64, 71), makeStudent('Frank Lee', 56, 83, 49), makeStudent('Grace Kim', 97, 95, 99), makeStudent('Hank Brown', 63, 41, 58), makeStudent('Ivy Chen', 74, 78, 86), makeStudent('Jake Taylor', 85, 69, 44),];
export function ConditionalFormatDemo() { const { witTheme } = useSiteTheme(); const tableRef = useRef<SpreadsheetRef>(null); const [status, setStatus] = useState('Loading...');
useEffect(() => { const engine = tableRef.current?.getInstance(); if (!engine) return;
const plugin = new ConditionalFormattingPlugin(); engine.installPlugin(plugin);
plugin.addRule(ConditionalFormattingPlugin.createGradientScale( { startRow: 0, startCol: 1, endRow: 9, endCol: 1 }, [ { value: 0, color: '#ef4444' }, { value: 50, color: '#eab308' }, { value: 100, color: '#22c55e' }, ] ));
plugin.addRule(ConditionalFormattingPlugin.createDataBar( { startRow: 0, startCol: 2, endRow: 9, endCol: 2 }, '#3b82f6' ));
plugin.addRule(ConditionalFormattingPlugin.createIconSet( { startRow: 0, startCol: 3, endRow: 9, endCol: 3 }, 'arrows' ));
engine.requestRender(); setStatus('Gradient: Math | Data Bars: Science | Icons: English'); }, []);
return ( <DemoWrapper title="Live Demo" description="Gradient scales on Math (red→yellow→green), data bars on Science (blue), and icon sets on English (arrows)." height={420}> <div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}> <div style={{ padding: '0.5rem 0.75rem', borderBottom: '1px solid #e2e8f0', flexShrink: 0, display: 'flex', gap: '0.5rem', alignItems: 'center' }}> <span style={{ fontSize: '0.8rem', color: '#64748b' }}>{status}</span> </div> <div style={{ flex: 1 }}> <Spreadsheet theme={witTheme} ref={tableRef} columns={columns} data={data} showRowNumbers editable={false} style={{ width: '100%', height: '100%' }} /> </div> </div> </DemoWrapper> );}Installation
Section titled “Installation”import { ConditionalFormattingPlugin } from '@witqq/spreadsheet-plugins';
const cfPlugin = new ConditionalFormattingPlugin();engine.installPlugin(cfPlugin);Condition Types
Section titled “Condition Types”Value Condition
Section titled “Value Condition”Apply a style when a cell value matches a comparison:
interface ValueCondition { type: 'value'; operator: ComparisonOperator; value: number; value2?: number; // Required for 'between' / 'notBetween'}Gradient Scale
Section titled “Gradient Scale”Interpolate colors across a numeric range:
interface GradientScaleCondition { type: 'gradientScale'; stops: readonly { value: number; color: string }[];}Data Bar
Section titled “Data Bar”Fill a portion of the cell background proportional to the value:
interface DataBarCondition { type: 'dataBar'; minValue?: number; maxValue?: number; color: string; showValue?: boolean;}Icon Set
Section titled “Icon Set”Display an icon based on value thresholds:
interface IconSetCondition { type: 'iconSet'; iconSet: IconSetName; // 'arrows' | 'circles' | 'flags' | 'stars' thresholds: readonly { value: number; icon: string }[]; showValue?: boolean;}Built-in icon sets:
- arrows —
▲▶▼ - circles — colored circles
- flags — flag indicators
- stars — star ratings
Comparison Operators
Section titled “Comparison Operators”type ComparisonOperator = | 'greaterThan' | 'lessThan' | 'greaterThanOrEqual' | 'lessThanOrEqual' | 'equal' | 'notEqual' | 'between' | 'notBetween';Static Factory Methods
Section titled “Static Factory Methods”ConditionalFormattingPlugin provides convenience factories to create rules:
createValueRule
Section titled “createValueRule”const rule = ConditionalFormattingPlugin.createValueRule( { startRow: 0, startCol: 2, endRow: 99, endCol: 2 }, // range 'greaterThan', // operator 1000, // threshold '#c6efce', // bgColor { textColor: '#006100', priority: 1 });cfPlugin.addRule(rule);createGradientScale
Section titled “createGradientScale”const rule = ConditionalFormattingPlugin.createGradientScale( { startRow: 0, startCol: 3, endRow: 99, endCol: 3 }, [ { value: 0, color: '#f8696b' }, // red (low) { value: 50, color: '#ffeb84' }, // yellow (mid) { value: 100, color: '#63be7b' }, // green (high) ]);cfPlugin.addRule(rule);createDataBar
Section titled “createDataBar”const rule = ConditionalFormattingPlugin.createDataBar( { startRow: 0, startCol: 4, endRow: 99, endCol: 4 }, '#638ec6', { minValue: 0, maxValue: 100, showValue: true });cfPlugin.addRule(rule);createIconSet
Section titled “createIconSet”const rule = ConditionalFormattingPlugin.createIconSet( { startRow: 0, startCol: 5, endRow: 99, endCol: 5 }, 'arrows', { showValue: true });cfPlugin.addRule(rule);Managing Rules
Section titled “Managing Rules”cfPlugin.addRule(rule); // Add a rulecfPlugin.removeRule(rule.id); // Remove by IDcfPlugin.clearRules(); // Remove all rulesconst rules = cfPlugin.getRules(); // Get all rules (readonly)Rules are evaluated in priority order (lower number = higher priority). Set stopIfTrue: true to prevent further rule evaluation after a match.
Color Scale by Value
Section titled “Color Scale by Value”Highlight high revenue cells in green, low in red:
import { ConditionalFormattingPlugin } from '@witqq/spreadsheet-plugins';import { Spreadsheet, SpreadsheetRef } from '@witqq/spreadsheet-react';
function App() { const ref = useRef<SpreadsheetRef>(null);
useEffect(() => { const cf = new ConditionalFormattingPlugin(); ref.current?.installPlugin(cf);
cf.addRule( ConditionalFormattingPlugin.createValueRule( { startRow: 0, startCol: 2, endRow: 999, endCol: 2 }, 'greaterThan', 5000, '#c6efce', { textColor: '#006100' } ) );
cf.addRule( ConditionalFormattingPlugin.createValueRule( { startRow: 0, startCol: 2, endRow: 999, endCol: 2 }, 'lessThan', 1000, '#ffc7ce', { textColor: '#9c0006' } ) ); }, []);
return <Spreadsheet ref={ref} columns={columns} data={data} />;}Data Bars for Progress
Section titled “Data Bars for Progress”const progressRule = ConditionalFormattingPlugin.createDataBar( { startRow: 0, startCol: 3, endRow: 49, endCol: 3 }, '#5b9bd5', { minValue: 0, maxValue: 100, showValue: true });cfPlugin.addRule(progressRule);Icon Sets for Status
Section titled “Icon Sets for Status”const statusRule = ConditionalFormattingPlugin.createIconSet( { startRow: 0, startCol: 4, endRow: 49, endCol: 4 }, 'arrows', { showValue: false });cfPlugin.addRule(statusRule);Internal Utilities
Section titled “Internal Utilities”The conditional formatting layer uses several internal utilities:
| Function | Description |
|---|---|
toNumber(value) | Convert cell value to number for comparison |
evaluateComparison(value, operator, threshold, threshold2?) | Evaluate a comparison condition |
interpolateColor(value, stops) | Interpolate between color stops for gradient scales |
getLayer() | Access the ConditionalFormatLayer render layer instance |
API Types
Section titled “API Types”ValueCondition
Section titled “ValueCondition”Apply a style when a cell value matches a numeric comparison.
interface ValueCondition { readonly type: 'value'; readonly operator: ComparisonOperator; readonly value: number; readonly value2?: number; // for 'between' / 'notBetween'}GradientScaleCondition
Section titled “GradientScaleCondition”Interpolate background colors across a numeric range using color stops.
interface GradientScaleCondition { readonly type: 'gradientScale'; readonly stops: readonly GradientStop[];}
interface GradientStop { readonly value: number; readonly color: string;}DataBarCondition
Section titled “DataBarCondition”Render a horizontal bar proportional to the cell value.
interface DataBarCondition { readonly type: 'dataBar'; readonly minValue?: number; readonly maxValue?: number; readonly color: string; readonly showValue?: boolean;}IconSetCondition
Section titled “IconSetCondition”Display an icon determined by value thresholds.
interface IconSetCondition { readonly type: 'iconSet'; readonly iconSet: IconSetName; readonly thresholds: readonly IconSetThreshold[]; readonly showValue?: boolean;}IconSetName
Section titled “IconSetName”Union of built-in icon set identifiers.
type IconSetName = 'arrows' | 'circles' | 'flags' | 'stars';IconSetThreshold
Section titled “IconSetThreshold”A single threshold entry mapping a minimum value to an icon character.
interface IconSetThreshold { readonly value: number; readonly icon: string;}