概述
本 Demo 展示了组成瀑布迷你图(CASCADESPARKLINE)的三种应用方式:使用动态数组创建带项目类型的瀑布图、创建水平瀑布图和创建垂直瀑布图。Demo 通过三个工作表分别演示了如何使用 itemTypeRange 参数标识不同类型的数据列(正向变化、负向变化、总计),以及如何灵活控制瀑布图的方向和样式。
实现思路
启用动态数组功能(第一个工作表需要)
第一个工作表:使用 SEQUENCE 函数自动生成索引,结合 itemTypeRange 参数创建财务损益表风格的瀑布图
第二个工作表:通过循环为每个数据点设置公式,创建水平瀑布图展示费用变化
第三个工作表:通过循环创建垂直瀑布图,设置 vertical 参数为 true
代码解析
启用动态数组并创建带类型的瀑布图
这段代码使用 SEQUENCE(COUNTA(D5:D20),1,1,1) 动态生成从 1 开始的索引数组,无需手动为每个单元格设置不同的索引值。itemTypeRange 参数(A5:A20)指定了每列的类型("+"、"-"、"="),用于标识正向变化、负向变化和总计列。
创建水平瀑布图
通过 ROW()-1 动态计算当前行的索引,使用绝对引用 $C$2:$C$15 确保所有单元格引用相同的数据范围。vertical 参数设为 false(默认值),创建水平瀑布图。
创建垂直瀑布图
通过 COLUMN() 动态获取当前列索引,将 vertical 参数设为 true,使瀑布图垂直显示。这种方式适合横向展示数据的变化趋势。
运行效果
第一个工作表显示两张财务损益表风格的瀑布图,不同类型的数据列(正向、负向、总计)使用不同颜色区分
第二个工作表显示水平瀑布图,展示推销员费用与薪酬的累积变化
第三个工作表显示垂直瀑布图,数据从上到下流动,适合横向展示趋势
所有瀑布图都自动计算累积值并使用绿色表示正向增长、红色表示负向减少
API 参考
CASCADESPARKLINE 函数
pointsRange:数据区域引用,例如 "B2:B8"
pointIndex:数据点索引,从 1 开始
labelsRange(可选):标签区域
minimum、maximum(可选):显示区域的最小值和最大值
colorPositive(可选):正向值的颜色,默认 "#8CBF64"
colorNegative(可选):负向值的颜色,默认 "#D6604D"
vertical(可选):是否垂直显示,默认 false
itemTypeRange(可选):项目类型数组,值为 "+"(正向)、"-"(负向)、"="(总计)
colorTotal(可选):总计列的颜色
SEQUENCE 函数
rows:要返回的行数
columns(可选):要返回的列数,默认 1
start(可选):序列起始值,默认 1
step(可选):递增值,默认 1
注意:SEQUENCE 函数仅在 allowDynamicArray 为 true 时有效。
var spreadNS = GC.Spread.Sheets;
window.onload = function () {
var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"));
spread.fromJSON(dataSource);
initSpread(spread);
};
function initSpread(spread) {
spread.options.newTabVisible = false;
spread.options.allowDynamicArray = true;
initCascadeSparklineWithType(spread.sheets[0]);
initHorizontalSparkline(spread.sheets[1]);
initVerticalSparkline(spread.sheets[2]);
}
function initCascadeSparklineWithType (sheet) {
sheet.suspendPaint();
sheet.setFormula(4, 4, '=CASCADESPARKLINE(D5:D20, SEQUENCE(COUNTA(D5:D20),1,1,1),P5:P20,,,"#8CBF64","#D6604D",false,A5:A20)');
sheet.setFormula(4, 8, '=CASCADESPARKLINE(H5:H20, SEQUENCE(COUNTA(H5:H20),1,1,1),Q5:Q20,,,"#8CBF64","#D6604D",false,A5:A20)');
sheet.setFormula(4, 15,'=TEXT(D5:D20,"#,##0,,")&" M"');
sheet.setFormula(4, 16,'=TEXT(H5:H20,"#,##0,,")&" M"');
//hide auxiliary columns
sheet.setColumnVisible(3, false);
sheet.setColumnVisible(7, false);
sheet.setColumnVisible(15, false);
sheet.setColumnVisible(16, false);
sheet.resumePaint();
}
function initHorizontalSparkline(sheet) {
sheet.suspendPaint();
//cascade sparkline located at column E
for (var i = 1; i <= 14; i++) {
sheet.setFormula(i, 4, '=CASCADESPARKLINE($C$2:$C$15,ROW()-1,$B$2:$B$15,,,"#8CBF64","#D6604D",false)');
}
sheet.resumePaint();
}
function initVerticalSparkline(sheet) {
sheet.suspendPaint();
//cascade sparkline located at 4th row
for (var c = 0; c < 5; c++) {
sheet.setColumnWidth(c, 100);
sheet.setFormula(3, c, '=CASCADESPARKLINE($A$3:$E$3,COLUMN(),$A$2:$E$2,,,"#8CBF64","#D6604D",true)');
}
sheet.resumePaint();
}
<!doctype html>
<html style="height:100%;font-size:14px;">
<head>
<meta name="spreadjs culture" content="zh-cn" />
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css"
href="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets/styles/gc.spread.sheets.excel2013white.css">
<script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets/dist/gc.spread.sheets.all.min.js"
type="text/javascript"></script>
<script
src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-resources-zh/dist/gc.spread.sheets.resources.zh.min.js"
type="text/javascript"></script>
<script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script>
<script src="app.js" type="text/javascript"></script>
<script src="$DEMOROOT$/spread/source/data/statement-for-cascade.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<div class="sample-tutorial">
<div id="ss" style="width:100%;height:100%"></div>
</div>
</body>
</html>
.sample-tutorial {
position: relative;
height: 100%;
overflow: hidden;
}
body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}