【经验分享】在帆软 Report 中实现 Excel 级“三色刻度”动态色阶

楼主
我是社区第1170937位番薯,欢迎点我头像关注我哦~

一、 核心需求分析

在做报表开发时,业务部门常希望实现类似 Excel 的三色刻度(Color Scales)功能:根据单元格数值的大小,自动在“红-黄-绿”之间进行颜色渐变。

虽然帆软内置的“条件属性”可以设置背景,但通常只能实现阶梯式变色(如 >90 绿,<60 红),无法实现平滑的线性过渡。为了追求极致的视觉体验,我们利用 JavaScript 结合帆软的 DOM 特性,完美还原了 Excel 的中位数色阶算法。

二、 技术原理

该方案的核心在于分段线性插值算法:

 * 区间定位:将数据分为 [最小值, 中位数] 和 [中位数, 最大值] 两个逻辑区间。

 * 动态采样:自动获取当前列或指定区域的极值,确保色阶随数据刷新自动调整。

 * RGB 插值:根据数值在区间内的百分比位置,计算出对应的 R、G、B 通道值,实现色彩的无缝平滑。

 * 视觉优化:引入亮度感知算法,当背景颜色过深时,自动切换文字颜色(黑/白),保证易读性。

三、 核心代码实现

本方案采用通用函数封装,支持扩展单元格和固定区域两种模式。只需在“模板 > 模板 Web 属性 > 分页预览设置 > 加载结束事件”中添加即可。

注:要添加功能的单元格需要设置自定义内容提示,在“单元格属性 > 其他 > 内容提示 > 自定义”输入'=$$$'即可

/**

 * 帆软报表 Excel 级动态色阶插件逻辑

 * 适用场景:动态扩展列、固定单元格区域

 */

function applyExcelColorScale(target, colors, mode) {

    // 1. 定位单元格 (支持扩展单元格名称或固定数组)

    var selector = (mode === 'expansion') 

        ? "td[cef='" + target + "']" 

        : target.map(function(n) { return "td[cef='" + n + "']"; }).join(",");

    

    var $cells = $(selector);

    var values = [];



    // 2. 原始数据采集 (从 title 属性规避格式化干扰)

    $cells.each(function() {

        var val = parseFloat($(this).attr("title"));

        if (!isNaN(val)) values.push(val);

    });



    if (values.length < 2) return;



    // 3. 计算 Excel 50百分位 (中位数) 逻辑

    values.sort(function(a, b) { return a - b; });

    var min = values[0], max = values[values.length - 1];

    var lowMid = Math.floor((values.length - 1) / 2);

    var highMid = Math.ceil((values.length - 1) / 2);

    var mid = (values[lowMid] + values[highMid]) / 2;



    // 4. 颜色渲染

    $cells.each(function() {

        var val = parseFloat($(this).attr("title"));

        if (isNaN(val)) return;



        var r, g, b, p, start, end;

        if (val <= mid) {

            p = (mid === min) ? 1 : (val - min) / (mid - min);

            start = colors.min; end = colors.mid;

        } else {

            p = (max === mid) ? 1 : (val - mid) / (max - mid);

            start = colors.mid; end = colors.max;

        }



        r = Math.floor(start.r + (end.r - start.r) * p);

        g = Math.floor(start.g + (end.g - start.g) * p);

        b = Math.floor(start.b + (end.b - start.b) * p);



        // 文字颜色自适应算法

        var brightness = (r * 299 + g * 587 + b * 114) / 1000;

        $(this).css({

            "background-color": "rgb(" + r + "," + g + "," + b + ")",

            "background-image": "none",

            "color": brightness < 110 ? "#FFFFFF" : "#000000"

        });

    });

}



// 调用示例

setTimeout(function() {

    var config = {

        min: { r: 248, g: 105, b: 107 }, // 红

        mid: { r: 255, g: 235, b: 132 }, // 黄

        max: { r: 99, g: 190, b: 123 }   // 绿

    };

    

    // 模式 A: G13 扩展出的整列

    applyExcelColorScale("G13", config, 'expansion');

    

    // 模式 B: 指定的固定区域 S2:S8

    applyExcelColorScale(["S2","S3","S4","S5","S6","S7","S8"], config, 'fixed');

}, 300);

 

四、 方案优势

 * 对标 Excel:采用中位数逻辑,有效解决了长尾数据(极值干扰)导致的颜色分配不均问题。

 * 抗干扰力强:直接读取单元格 title 原始值,不受千分位、单位、公式格式化的影响。

 * 自适应排版:内置背景亮度检测,即便背景是深红色,文字也能清晰可见。

 * 复用性强:一次封装,多列调用,不同列可配置不同的配色方案(如:红-黄-绿 或 白-蓝-深蓝)。

分享扩散:

沙发
发表于 2025-12-22 17:54:36
不生效啊大佬
板凳
发表于 5 天前
学习了,貌似只适配了分析预览
地板
发表于 5 天前
学习了!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

6回帖数 1关注人数 397浏览人数
最后回复于:5 天前

返回顶部 返回列表