Conditional Formatting — cell value rules, color scales, data bars, top N

level: intermediate / verified: 2026-10-01 / tabs: Node.js・Python・Java・WebAssembly / 日本語

What you want to do

Set conditional formatting rules programmatically, such as "make only cells greater than 60 red" or "show the magnitude of values with a gradient or a bar". Also read back the count, type, thresholds and applied ranges of the registered rules and remove them.

Conditional formatting is handled by the FormatConditions class obtained via ws.getFormatConditions(). The flow is always these 3 steps:

  1. Create a condition object from dto (e.g. CellValueObject) and set its apply range and format
  2. Register it with fc.set…Condition(priority, obj) (priority is the evaluation order,

1-based and unique per sheet)

  1. Call fc.apply() after all conditions are registered (required)

Classes used

FormatConditions (main methods)

Condition typeSetRead backCondition object
Cell value (greater, less, ...)setCellValueCondition(p, obj)getCellValueCondition(p)dto.CellValueObject
Cell value range (between)setCellValueRangeCondition(p, obj)getCellValueRangeCondition(p)dto.CellValueRangeObject
Color scalesetColorScaleFormatCondition(p, obj)getColorScaleFormatCondition(p)dto.ColorScaleObject
Data barsetDataBarFormatCondition(p, obj)getDataBarFormatCondition(p)dto.DataBarObject
Top / bottom NsetTop10FormatCondition(p, obj)getTop10FormatCondition(p)dto.Top10Object
Above/below averagesetAboveAverageCondition(p, obj)getAboveAverageCondition(p)dto.AboveAverageObject
Icon setsetIconsetFormatCondition(p, obj)getIconsetFormatCondition(p)dto.IconsetConditionObject
Unique valuessetUniqueValuesFormatCondition(p, obj)getUniqueValuesFormatCondition(p)dto.UniqueValuesObject
Other methodsDescription
apply()Evaluates and reflects the conditions. Always call after setting all conditions.
getConditionTypes()List of all rules; a nested map { priority: { cellRange: conditionType } }.
removeCondition(p) / removeAllCondition()Remove one rule / all rules.
getAppliedFontObject(range) etc.Get the cells that met a condition and actually received formatting (use after apply()).

Methods common to all condition objects

They all have setA1C1(applyRange) and setFont(dto.FontObject) / setPatternFill(dto.PatternFillObject). Colors are set on a dto.ColorObject via setHexColor() with a 6-digit hex string without # (e.g. "9C0006").

Code

Output:

// conditional-format.js — adding, reading back and removing conditional format rules
const { nodeosbxl, enums, dto } = require("nodeosbxl");

const app = new nodeosbxl.App();
const wb = app.createWorkBook("condfmt.xlsx");
const ws = wb.openWorkSheet("Sheet1");

// color helper: ColorObject takes a 6-digit hex without "#"
const color = (hex) => {
    const c = new dto.ColorObject();
    c.setHexColor(hex);
    return c;
};

// ---------- data table ----------
// col B: cell value rule / col C: color scale / col D: data bar / col E: top 3 + above average
["Month", "Cell value rule", "Color scale", "Data bar", "Top/Average"].forEach((h, i) => {
    const col = "ABCDE"[i];
    ws.getRange(`${col}1:${col}1`).setValue(h);
});
const sales = [45, 78, 23, 91, 56, 34, 87, 12, 65, 49];
sales.forEach((v, i) => {
    ws.getRange(`A${i + 2}:A${i + 2}`).setNumberValue(i + 1);
    for (const col of ["B", "C", "D", "E"]) {
        ws.getRange(`${col}${i + 2}:${col}${i + 2}`).setNumberValue(v);
    }
});

const fc = ws.getFormatConditions();

// ---------- (1) cell value rule: greater than 60 -> dark red bold + light red fill ----------
const cellVal = new dto.CellValueObject();
cellVal.setValueCondition(60, enums.XlFormatConditionOperator.FormatConditionGreater);
cellVal.setA1C1("B2:B11");
const redFont = new dto.FontObject();
redFont.setBold(true);
redFont.setColorObject(color("9C0006"));
cellVal.setFont(redFont);
const pinkFill = new dto.PatternFillObject();
pinkFill.setPattern(enums.XlPatternType.PatternSolid);
pinkFill.setCellColor(color("FFC7CE"));
cellVal.setPatternFill(pinkFill);
fc.setCellValueCondition(1, cellVal);

// ---------- (2) color scale: 3-color gradient on column C ----------
const colorScale = new dto.ColorScaleObject();
colorScale.setA1C1("C2:C11");
colorScale.setMinimumCondition(color("F8696B"), enums.XlConditionValueType.ConditionValueTypeMinimum);
colorScale.setMediumCondition(color("FFEB84"), enums.XlConditionValueType.ConditionValueTypePercentile, 50);
colorScale.setMaximumCondition(color("63BE7B"), enums.XlConditionValueType.ConditionValueTypeMaximum);
fc.setColorScaleFormatCondition(2, colorScale);

// ---------- (3) data bar: column D ----------
const dataBar = new dto.DataBarObject();
dataBar.setA1C1("D2:D11");
dataBar.setDataBarColor(color("638EC6"));
dataBar.setMinimumCondition(enums.XlConditionValueType.ConditionValueTypeMinimum);
dataBar.setMaximumCondition(enums.XlConditionValueType.ConditionValueTypeMaximum);
fc.setDataBarFormatCondition(3, dataBar);

// ---------- (4) top 3 + above average: column E ----------
const top3 = new dto.Top10Object();
top3.setRank(3, true);                       // true = top (false = bottom)
top3.setA1C1("E2:E11");
const blueFont = new dto.FontObject();
blueFont.setBold(true);
blueFont.setColorObject(color("0070C0"));
top3.setFont(blueFont);
fc.setTop10FormatCondition(4, top3);

const aboveAvg = new dto.AboveAverageObject();
aboveAvg.setAboveBelow(enums.XlAboveBelow.XlAboveAverage);
aboveAvg.setA1C1("E2:E11");
const greenFont = new dto.FontObject();
greenFont.setBold(true);
greenFont.setColorObject(color("006100"));
aboveAvg.setFont(greenFont);
fc.setAboveAverageCondition(5, aboveAvg);

fc.apply();                                  // apply() is required after setting all conditions
console.log("[1] Registered 5 rules and called apply()");

// ---------- read back the rule list ----------
const typeName = Object.fromEntries(
    Object.entries(enums.XlFormatConditionType).map(([name, val]) => [val, name]));
console.log(`[2] rule count = ${Object.keys(fc.getConditionTypes()).length}`);
for (const [prio, ranges] of Object.entries(fc.getConditionTypes())) {
    for (const [range, type] of Object.entries(ranges)) {
        console.log(`    priority ${prio}: ${range} → ${typeName[type]} (type=${type})`);
    }
}

// ---------- read back each rule's details ----------
console.log("[3] Reading back rule details");
const g1 = fc.getCellValueCondition(1);
console.log(`    cell value : ${g1.getA1C1()} value=${g1.getConditionValue()}` +
    ` operator=${g1.getConditionOperetor()} (Greater=${enums.XlFormatConditionOperator.FormatConditionGreater})` +
    ` fontColor=${g1.getFont().getColorObject().getHexColor()} bold=${g1.getFont().isBold()}` +
    ` fill=${g1.getPatternFill().getCellColor().getHexColor()}`);
const g2 = fc.getColorScaleFormatCondition(2);
console.log(`    color scale: min=${g2.getMinimumColor().getHexColor()} (type=${g2.getMinimumValueType()})` +
    ` mid=${g2.getMediumColor().getHexColor()} (type=${g2.getMediumValueType()}, threshold=${g2.getMediumValue()})` +
    ` max=${g2.getMaximumColor().getHexColor()} (type=${g2.getMaximumValueType()})`);
const g3 = fc.getDataBarFormatCondition(3);
console.log(`    data bar: color=${g3.getDataBarColor().getHexColor()}` +
    ` minType=${g3.getMinimumCondition()} maxType=${g3.getMaximumCondition()}`);
const g4 = fc.getTop10FormatCondition(4);
console.log(`    top N: rank=${g4.getRank()} isTop=${g4.getTopBottom()}`);
const g5 = fc.getAboveAverageCondition(5);
console.log(`    above average: aboveBelow=${g5.getAboveBelow()}` +
    ` (XlAboveAverage=${enums.XlAboveBelow.XlAboveAverage})`);

// ---------- cells that met the conditions and got formatted (available after apply()) ----------
const byRow = (a, b) => Number(a.slice(1)) - Number(b.slice(1));
console.log("[4] Cells that received formatting");
console.log(`    col B (>60)     : ${Object.keys(fc.getAppliedFontObject("B2:B11")).sort(byRow).join(" ")}`);
console.log(`    col E (top/avg) : ${Object.keys(fc.getAppliedFontObject("E2:E11")).sort(byRow).join(" ")}`);
const appliedBar = fc.getAppliedDataBar("D2:D11");
console.log(`    col D data bars : ${Object.values(appliedBar).filter(Boolean).length} cells`);

// ---------- removal ----------
fc.removeCondition(4);                       // remove only the top-3 rule
console.log(`[5] rule count after removeCondition(4) = ${Object.keys(fc.getConditionTypes()).length}`);
fc.removeAllCondition();                     // remove all rules
console.log(`[6] rule count after removeAllCondition() = ${Object.keys(fc.getConditionTypes()).length}`);

// re-register the cell value rule and save (so the effect is visible when the file is opened)
fc.setCellValueCondition(1, cellVal);
fc.apply();

wb.save();
wb.close();
console.log("[done] saved condfmt.xlsx (cell-value rule re-registered)");
[1] Registered 5 rules and called apply()
[2] rule count = 5
    priority 1: B2:B11 → CellValue (type=1)
    priority 2: C2:C11 → ColorScale (type=3)
    priority 3: D2:D11 → Databar (type=4)
    priority 4: E2:E11 → Top10 (type=5)
    priority 5: E2:E11 → AboveAverageCondition (type=12)
[3] Reading back rule details
    cell value : B2:B11 value=60 operator=5 (Greater=5) fontColor=9C0006 bold=true fill=FFC7CE
    color scale: min=F8696B (type=5) mid=FFEB84 (type=4, threshold=50) max=63BE7B (type=6)
    data bar: color=638EC6 minType=5 maxType=6
    top N: rank=3 isTop=true
    above average: aboveBelow=0 (XlAboveAverage=0)
[4] Cells that received formatting
    col B (>60)     : B3 B5 B8 B10
    col E (top/avg) : E3 E5 E6 E8 E10
    col D data bars : 10 cells
[5] rule count after removeCondition(4) = 4
[6] rule count after removeAllCondition() = 0
[done] saved condfmt.xlsx (cell-value rule re-registered)

B3 B5 B8 B10 in column B are the cells whose values are 78, 91, 87 and 65 (= greater than 60); E3 E5 E6 E8 E10 in column E are the union of "top 3" and "above the average (54.2)". Visual formatting cannot be verified programmatically, so the sample confirms the rules were set as intended by reading back the rule count, types, thresholds and the cells that got formatted and printing them.

Notes

priority (evaluation order)

What apply() does

Main enums

enumCommon values
XlFormatConditionOperatorFormatConditionGreater(5) / FormatConditionGreaterEqual(7) / FormatConditionLess(6) / FormatConditionLessEqual(8) / FormatConditionEqual(3) / FormatConditionBetween(1)
XlFormatConditionTypeCellValue(1) / ColorScale(3) / Databar(4) / Top10(5) / XlIconSet(6) / UniqueValues(8) / AboveAverageCondition(12)
XlConditionValueTypeConditionValueTypeMinimum(5) / ConditionValueTypeMaximum(6) / ConditionValueTypePercentile(4) / ConditionValueTypeNumeric(1)
XlAboveBelowXlAboveAverage(0) / XlBelowAverage(2) / XlAboveStdDev(1) / XlBelowStdDev(3)

Persistence

Conditional formatting is saved into the .xlsx by wb.save(), and reopening the file with app.openWorkBook() restores getConditionTypes() and the individual read-back methods (verified).

Caveats

See also