Skip to main content

spreadsheet_mcp/rules/
conditional_format.rs

1use umya_spreadsheet::{
2    ConditionalFormatValues, ConditionalFormatting, ConditionalFormattingOperatorValues,
3    ConditionalFormattingRule, Formula, PatternValues, Style, Worksheet,
4};
5
6/// Build a minimal style intended for conditional formatting (OOXML `dxf`).
7///
8/// Note: umya-spreadsheet materializes/deduplicates `dxf` records at write time based on
9/// the style hash. Keeping this style deterministic helps reuse the same `dxf`.
10pub fn build_simple_dxf_style(fill_argb: &str, font_argb: &str, bold: bool) -> Style {
11    let mut style = Style::default();
12
13    style
14        .get_fill_mut()
15        .get_pattern_fill_mut()
16        .set_pattern_type(PatternValues::Solid)
17        .get_foreground_color_mut()
18        .set_argb(fill_argb);
19
20    let font = style.get_font_mut();
21    font.set_bold(bold);
22    font.get_color_mut().set_argb(font_argb);
23
24    style
25}
26
27/// Compute the next conditional-formatting rule priority for a worksheet.
28///
29/// Excel expects priorities to be unique within a worksheet.
30pub fn next_cf_priority(sheet: &Worksheet) -> i32 {
31    let mut max_priority: i32 = 0;
32    for cf in sheet.get_conditional_formatting_collection() {
33        for rule in cf.get_conditional_collection() {
34            max_priority = max_priority.max(*rule.get_priority());
35        }
36    }
37
38    max_priority.saturating_add(1).max(1)
39}
40
41/// Append an `expression` conditional formatting rule for `sqref`.
42///
43/// Returns the priority assigned to the new rule.
44pub fn append_cf_expression_rule(
45    sheet: &mut Worksheet,
46    sqref: &str,
47    expression: &str,
48    dxf_style: Style,
49) -> i32 {
50    let mut cf = ConditionalFormatting::default();
51    cf.get_sequence_of_references_mut().set_sqref(sqref);
52
53    let priority = next_cf_priority(sheet);
54    let mut rule = ConditionalFormattingRule::default();
55    rule.set_type(ConditionalFormatValues::Expression);
56    rule.set_priority(priority);
57
58    let mut formula = Formula::default();
59    formula.set_string_value(expression);
60    rule.set_formula(formula);
61    rule.set_style(dxf_style);
62
63    cf.add_conditional_collection(rule);
64    sheet.add_conditional_formatting_collection(cf);
65
66    priority
67}
68
69/// Append a `cellIs` conditional formatting rule for `sqref`.
70///
71/// Returns the priority assigned to the new rule.
72pub fn append_cf_cellis_rule(
73    sheet: &mut Worksheet,
74    sqref: &str,
75    operator: ConditionalFormattingOperatorValues,
76    formula_value: &str,
77    dxf_style: Style,
78) -> i32 {
79    let mut cf = ConditionalFormatting::default();
80    cf.get_sequence_of_references_mut().set_sqref(sqref);
81
82    let priority = next_cf_priority(sheet);
83    let mut rule = ConditionalFormattingRule::default();
84    rule.set_type(ConditionalFormatValues::CellIs);
85    rule.set_operator(operator);
86    rule.set_priority(priority);
87
88    let mut formula = Formula::default();
89    formula.set_string_value(formula_value);
90    rule.set_formula(formula);
91    rule.set_style(dxf_style);
92
93    cf.add_conditional_collection(rule);
94    sheet.add_conditional_formatting_collection(cf);
95
96    priority
97}