테이블 시트 사용자 지정 뷰는 열 정보를 만들 때 conditionalFormats, validator, style을 지정하여 조건부 서식, 데이터 유효성 검사, 열 스타일을 지원합니다.
"Product Conditional Format" 시트는 Unit Price 열에 수식 기반 조건부 서식과 데이터 유효성 검사가 적용된 테이블 시트를 보여 줍니다.
"Sparkline Rule" 시트는 테이블 시트의 새로운 스파크라인 조건부 서식 규칙 기능을 보여 줍니다. ruleType: "sparklineRule"과 함께 conditionalFormats 열 속성을 사용하여 두 가지 스파크라인 규칙 유형을 시연합니다.
불릿 스파크라인 규칙: 각 지역의 실제 매출을 회사 전체 기준값(목표, 좋음, 나쁨 임계값)과 비교해 시각화하므로 지역별 성과를 한눈에 쉽게 평가할 수 있습니다.
롤리팝 편차 스파크라인 규칙: 각 지역의 목표 매출과 실제 매출 간 백분율 편차를 표시하며, 녹색은 목표 초과, 주황색은 목표 미달 성과를 나타냅니다.
다음은 테이블 시트 뷰의 조건부 서식 샘플 코드입니다.
다음은 테이블 시트 뷰의 스파크라인 조건부 서식 규칙 샘플 코드입니다.
/*REPLACE_MARKER*/
/*DO NOT DELETE THESE COMMENTS*/
window.onload = function () {
var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 0 });
initSpread(spread);
};
function initSpread(spread) {
spread.suspendPaint();
spread.options.autoFitType = GC.Spread.Sheets.AutoFitType.cellWithHeader;
spread.options.highlightInvalidData = true;
initProductSheet(spread);
initSparklineRuleSheet(spread);
spread.setActiveSheetIndex(0);
spread.resumePaint();
}
function initProductSheet(spread) {
//init a data manager
var baseApiUrl = getBaseApiUrl();
var dataManager = spread.dataManager();
//add product table
var productTable = dataManager.addTable("productTable", {
remote: {
read: {
url: baseApiUrl + "/Product"
}
}
});
//init a table sheet
var sheet = spread.addSheetTab(0, "Conditional Format", GC.Spread.Sheets.SheetType.tableSheet);
sheet.options.allowAddNew = false; //hide new row
sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader);
//bind a view to the table sheet
var numericStyle = {};
numericStyle.formatter = "$ 0.00";
var formulaRule = {
ruleType: "formulaRule",
formula: "@>=50",
style: {
font:"bold 12pt Calibri",
backColor: "#F7D3BA",
foreColor :"#F09478"
}
};
var positiveNumberValidator = {
type: "formula",
formula: '@<50',
inputTitle: 'Data validation:',
inputMessage: 'Enter a number smaller than 50.',
highlightStyle: {
type: 'icon',
color: "#F09478",
position: 'outsideRight',
}
};
var myView = productTable.addView("myView", [
{ value: "Id", caption: "ID", width: 46},
{ value: "ProductName", caption: "Name", width: 250 },
{ value: "QuantityPerUnit", caption: "Quantity Per Unit", width: 140},
{ value: "UnitPrice", caption: "Unit Price", width: 140, conditionalFormats: [formulaRule], validator: positiveNumberValidator, style: numericStyle },
{ value: "UnitsInStock", caption: "Units In Stock", width: 140},
{ value: "UnitsOnOrder", caption: "Units On Order", width: 140},
{ value: "Discontinued", width: 120, style: { formatter:"[green]✔;;[red]✘", hAlign: GC.Spread.Sheets.HorizontalAlign.center }}
]);
myView.fetch().then(function () {
sheet.setDataView(myView);
});
}
function initSparklineRuleSheet(spread) {
var dataManager = spread.dataManager();
// Regional sales data with a mix of above/below target results
var salesTable = dataManager.addTable("salesTable", {
data: [
{ region: "North America", target: 850, actual: 920, forecast: 880, actual1: 920, actual2: 920 },
{ region: "Europe", target: 720, actual: 680, forecast: 700, actual1: 680, actual2: 680 },
{ region: "Asia Pacific", target: 650, actual: 710, forecast: 670, actual1: 710, actual2: 710 },
{ region: "Latin America", target: 380, actual: 350, forecast: 360, actual1: 350, actual2: 350 },
{ region: "Middle East", target: 280, actual: 310, forecast: 290, actual1: 310, actual2: 310 },
{ region: "Africa", target: 180, actual: 165, forecast: 170, actual1: 165, actual2: 165 },
{ region: "Oceania", target: 150, actual: 160, forecast: 155, actual1: 160, actual2: 160 },
{ region: "South Asia", target: 220, actual: 195, forecast: 210, actual1: 195, actual2: 195 },
]
});
// Create a table sheet for sparkline rules
var sheet = spread.addSheetTab(1, "Sparkline Rule", GC.Spread.Sheets.SheetType.tableSheet);
sheet.options.allowAddNew = false;
sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader);
sheet.setDefaultRowHeight(40);
var bulletRule = {
ruleType: "sparklineRule",
sparklineType: "BULLETSPARKLINE",
sparklineOptions: {
measure: '@', // current cell value = actual revenue
target: 500, // company-wide benchmark target ($500K)
maxi: 1000, // maximum scale ($1000K)
good: 700, // "exceeding expectations" threshold
bad: 250, // "needs improvement" threshold
forecast: 600, // company average forecast
colorScheme: '#2F5496'
},
showSparklineOnly: true
};
var lollipopRule = {
ruleType: "sparklineRule",
sparklineType: "LOLLIPOPVARISPARKLINE",
sparklineOptions: {
plannedValue: '[target]',
actualValue: '$CF_RANGE$',
index: '@', // 0-based index of current cell within rule range
reference: 0, // reference line at 0% variance
mini: -0.3, // minimum variance scale (-30%)
maxi: 0.3, // maximum variance scale (+30%)
tickUnit: 0.1, // tick marks every 10%
legend: true, // show legend labels
colorPositive: '#70AD47', // green for above target
colorNegative: '#ED7D31', // orange for below target
lollipopHeaderColor: '#2F5496' // dot color
},
showSparklineOnly: true
};
var numericStyle = { formatter: "$#,##0" };
var salesView = salesTable.addView("salesView", [
{ value: "region", caption: "Region", width: 130 },
{ value: "target", caption: "Target ($K)", width: 100, style: numericStyle },
{ value: "actual", caption: "Actual ($K)", width: 100, style: numericStyle },
{ value: "forecast", caption: "Forecast ($K)", width: 100, style: numericStyle },
{ value: "actual1", caption: "Performance (Bullet)", width: 220, conditionalFormats: [bulletRule] },
{ value: "actual2", caption: "Variance (Lollipop)", width: 220, conditionalFormats: [lollipopRule] }
]);
salesView.fetch().then(function () {
sheet.setDataView(salesView);
});
}
function getBaseApiUrl() {
return window.location.href.match(/http.+spreadjs\/learn-spreadjs\//)[0] + 'server/api';
}
<!doctype html>
<html style="height:100%;font-size:14px;">
<head>
<meta name="spreadjs culture" content="ko-kr" />
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css" href="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css">
<!-- Promise Polyfill for IE, https://www.npmjs.com/package/promise-polyfill -->
<script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-tablesheet/dist/gc.spread.sheets.tablesheet.min.js" type="text/javascript"></script>
<script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-resources-ko/dist/gc.spread.sheets.resources.ko.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>
<link rel="stylesheet" type="text/css" href="styles.css">
</head>
<body>
<div class="sample-tutorial">
<div id="ss" class="sample-spreadsheets"></div>
<div id="optionContainer" class="optionContainer">
</div>
</div>
</html>
.sample-tutorial {
position: relative;
height: 100%;
overflow: hidden;
}
body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.sample-spreadsheets {
width: 100%;
height: 100%;
overflow: hidden;
float: left;
}