Progress Sparkline

The Progress Sparkline demo shows how PROGRESSSPARKLINE can summarize progress in compact worksheet cells across an overview worksheet and several business-style worksheet layouts.

SpreadJS supports PROGRESSSPARKLINE as a formula-based sparkline for displaying progress directly inside a cell. It is useful when you want compact status indicators in worksheets, dashboards, or KPI tables without inserting a full chart object. This demo shows how the same function can render linear, discrete, arc, and radial progress styles across multiple worksheets so you can compare overview samples with more contextual worksheet layouts. Formula signature: value: The progress value displayed by the sparkline. In this demo the sample values are fixed so different modes can be compared consistently. mode: Selects the visual style. This sample covers 0..14, including bar, segmented, dotted, arc, and radial variants. barColor: Optional foreground color for the completed progress area. Default: Accent 1. Supports both theme color tokens such as Accent 1 and CSS color values such as #4F81BD. bandColor: Optional track color behind the progress area. Default: Accent 1 80. Supports both theme color tokens such as Accent 1 80 and CSS color values such as #D9E2F3. showValue: Optional boolean that controls whether the value text is shown. Default: TRUE. Common ways to use it: Change mode to switch between linear, discrete, arc, and radial styles. Change barColor and bandColor to match a worksheet theme or use custom CSS colors to highlight a status level. Set showValue to FALSE when you want a cleaner visual without inline text. Example code: In this demo, the overview worksheet lists every supported mode together with its formula and preview, and the additional worksheets show how progress sparklines can be used in compact business-style layouts.
var spreadNS = window.GC && GC.Spread && GC.Spread.Sheets; var HA = spreadNS.HorizontalAlign; var VA = spreadNS.VerticalAlign; var CF = spreadNS.ConditionalFormatting; window.onload = function () { initializeDemo(); }; function initializeDemo() { var spread = new spreadNS.Workbook(document.getElementById("ss"), { sheetCount: 4 }); spread.suspendPaint(); configureOverviewSheet(spread.getSheet(0)); configureReleaseReadinessSheet(spread.getSheet(1)); configureServiceHealthSheet(spread.getSheet(2)); configureLearningProgressSheet(spread.getSheet(3)); spread.setActiveSheetIndex(0); spread.resumePaint(); } function configureSheetBase(sheet, name, rowCount, columnCount) { sheet.name(name); sheet.setRowCount(rowCount); sheet.setColumnCount(columnCount); } function styleHeaderRow(sheet, row, columnCount, backColor, foreColor) { sheet.getRange(row, 0, 1, columnCount) .font("bold 13px Segoe UI") .backColor(backColor || "#f3f6fb") .foreColor(foreColor || "#314155") .hAlign(HA.center) .vAlign(VA.center); } function applyRangeStyle(range, options) { if (options.font) { range.font(options.font); } if (options.backColor !== undefined) { range.backColor(options.backColor); } if (options.foreColor !== undefined) { range.foreColor(options.foreColor); } if (options.hAlign !== undefined) { range.hAlign(options.hAlign); } if (options.vAlign !== undefined) { range.vAlign(options.vAlign); } if (options.wordWrap !== undefined) { range.wordWrap(options.wordWrap); } if (options.formatter !== undefined) { range.formatter(options.formatter); } } function setHeaderValues(sheet, row, values) { sheet.setArray(row, 0, [values]); } function setColumnWidths(sheet, widths) { for (var col = 0; col < widths.length; col++) { sheet.setColumnWidth(col, widths[col]); } } function setUniformColumnWidths(sheet, startCol, colCount, width) { for (var col = startCol; col < startCol + colCount; col++) { sheet.setColumnWidth(col, width); } } function setRowHeights(sheet, heights) { for (var row in heights) { if (Object.prototype.hasOwnProperty.call(heights, row)) { sheet.setRowHeight(Number(row), heights[row]); } } } function registerCustomNames(sheet, names) { for (var name in names) { if (Object.prototype.hasOwnProperty.call(names, name) && !sheet.getCustomName(name)) { sheet.addCustomName(name, names[name]); } } } function createForeColorStyle(color) { var style = new spreadNS.Style(); style.foreColor = color; return style; } function applySpecificTextColorRules(sheet, ranges, ruleColors) { for (var text in ruleColors) { if (Object.prototype.hasOwnProperty.call(ruleColors, text)) { sheet.conditionalFormats.addSpecificTextRule( CF.TextComparisonOperators.contains, text, createForeColorStyle(ruleColors[text]), ranges ); } } } function toColumnMatrix(items, valueSelector) { return items.map(function (item) { return [valueSelector(item)]; }); } function buildServiceHealthFormula(currentRef, targetRef, warningThreshold) { return '=IF(' + currentRef + '>=' + targetRef + ',"Healthy",IF(' + currentRef + '>=' + warningThreshold + ',"Warning","Critical"))'; } function registerServiceHealthNames(sheet) { registerCustomNames(sheet, { HealthyColor: '="#16a34a"', WarningColor: '="#d97706"', CriticalColor: '="#dc2626"', HealthyBandColor: '="#dcfce7"', WarningBandColor: '="#fef3c7"', CriticalBandColor: '="#fee2e2"' }); } function buildServiceHealthSparklineFormula(currentRef, targetRef, warningThreshold) { return '=PROGRESSSPARKLINE(' + currentRef + ',9,IF(' + currentRef + '>=' + targetRef + ',HealthyColor,IF(' + currentRef + '>=' + warningThreshold + ',WarningColor,CriticalColor)),IF(' + currentRef + '>=' + targetRef + ',HealthyBandColor,IF(' + currentRef + '>=' + warningThreshold + ',WarningBandColor,CriticalBandColor)),TRUE)'; } function buildLiteralFormula(value, mode, barColor, bandColor, showValue) { var formula = "=PROGRESSSPARKLINE(" + value + "," + mode; if (barColor !== undefined || bandColor !== undefined || showValue !== undefined) { if (barColor !== undefined && barColor !== null) { formula += ',"' + escapeFormulaText(barColor) + '"'; } else { formula += ","; } } if (bandColor !== undefined || showValue !== undefined) { if (bandColor !== undefined && bandColor !== null) { formula += ',"' + escapeFormulaText(bandColor) + '"'; } else { formula += ","; } } if (showValue !== undefined) { formula += "," + (showValue ? "TRUE" : "FALSE"); } formula += ")"; return formula; } function buildCellFormula(valueColumnIndex, row, mode, barColor, bandColor, showValue) { var valueRef = columnName(valueColumnIndex) + (row + 1); return buildLiteralFormula(valueRef, mode, barColor, bandColor, showValue); } function escapeFormulaText(value) { return String(value).replace(/"/g, '""'); } function columnName(index) { return String.fromCharCode("A".charCodeAt(0) + index); } function createBorder(color) { return new spreadNS.LineBorder(color, spreadNS.LineStyle.thin); } function createReleaseReadinessSource() { return RELEASE_READINESS_ROWS.map(function (item) { return { workstream: item.workstream, owner: item.owner, milestone: item.milestone, targetDate: item.targetDate }; }); } function registerReleaseReadinessNames(sheet) { registerCustomNames(sheet, { AlertColor: '="#dc2626"', AtRiskColor: '="#d97706"', OnTrackColor: '="#4E7BEF"', TrackColor: '="#DCE7FB"' }); } function buildReleaseReadinessRiskFormula(value) { return '=LET(progress,' + value + ',IF(progress<0.3,"Alert",IF(progress<0.5,"At Risk","On Track")))'; } function buildReleaseReadinessSparklineFormula(value) { return '=LET(progress,' + value + ',PROGRESSSPARKLINE(progress,0,IF(progress<0.3,AlertColor,IF(progress<0.5,AtRiskColor,OnTrackColor)),TrackColor,TRUE))'; } var OVERVIEW_MODE_DEFINITIONS = [ { mode: 0, label: "Bar", value: 0.28, rowHeight: 50, barColor: "#e74c3c", bandColor: "#fce4e4" }, { mode: 1, label: "Striped", value: 0.46, rowHeight: 50, barColor: "#27ae60", bandColor: null }, { mode: 2, label: "Segmented", value: 0.71, rowHeight: 50, barColor: "Accent 4", bandColor: "Accent 4 80" }, { mode: 3, label: "Radial", value: 0.89, rowHeight: 60, barColor: "#2980b9", bandColor: "#d4e6f1" }, { mode: 4, label: "Arc", value: 0.55, rowHeight: 60, barColor: "#8e44ad", bandColor: "#e8d5f5" }, { mode: 5, label: "Hatched", value: 0.50, rowHeight: 50, barColor: "#c0392b", bandColor: "#e6b0aa" }, { mode: 6, label: "Bubble", value: 0.40, rowHeight: 50, barColor: "#16a085", bandColor: null }, { mode: 7, label: "Dotted", value: 0.33, rowHeight: 50, barColor: "#d35400", bandColor: "#edbb99" }, { mode: 8, label: "Checkbox", value: 0.70, rowHeight: 50, barColor: "#1abc9c", bandColor: "#d5dbdb" }, { mode: 9, label: "Radial-gap", value: 0.37, rowHeight: 60, barColor: "#c0392b", bandColor: "#bdc3c7" }, { mode: 10, label: "Radial-thick", value: 0.37, rowHeight: 60, barColor: "#e67e22", bandColor: "#d5d5d5" }, { mode: 11, label: "Radial-ticks", value: 0.37, rowHeight: 60, barColor: "#27ae60", bandColor: "#d5d5d5" }, { mode: 12, label: "Radial-dash", value: 0.37, rowHeight: 60, barColor: "#2c3e9b", bandColor: "#d5d5d5" }, { mode: 13, label: "Radial-dots", value: 0.37, rowHeight: 60, barColor: "#8e44ad", bandColor: "#d5d5d5" }, { mode: 14, label: "Radial-knob", value: 0.37, rowHeight: 60, barColor: "#e74c3c", bandColor: "#d5d5d5" } ]; function configureOverviewSheet(sheet) { var rows = { header: 0, dataStart: 1 }; var cols = { mode: 0, value: 1, sparkline: 2, formula: 3 }; var rowCount = OVERVIEW_MODE_DEFINITIONS.length; var totalRows = rows.dataStart + rowCount; var border = createBorder("#d7dee7"); sheet.suspendPaint(); try { configureSheetBase(sheet, "All Progress Modes", totalRows, 4); setColumnWidths(sheet, [140, 84, 300, 440]); styleHeaderRow(sheet, rows.header, 4, "#f3f6fb", "#314155"); setHeaderValues(sheet, rows.header, ["Mode", "Value", "Sparkline", "Formula"]); sheet.setRowHeight(rows.header, 30); applyRangeStyle(sheet.getRange(rows.dataStart, cols.mode, rowCount, 1), { font: "13px Segoe UI", foreColor: "#1f2937", hAlign: HA.center, vAlign: VA.center }); applyRangeStyle(sheet.getRange(rows.dataStart, cols.value, rowCount, 1), { font: "13px Segoe UI", foreColor: "#1f2937", hAlign: HA.center, vAlign: VA.center, formatter: "0%" }); applyRangeStyle(sheet.getRange(rows.dataStart, cols.sparkline, rowCount, 1), { backColor: "#ffffff", hAlign: HA.center, vAlign: VA.center }); applyRangeStyle(sheet.getRange(rows.dataStart, cols.formula, rowCount, 1), { font: "13px Consolas", foreColor: "#44556b", backColor: "#fbfcfd", wordWrap: true, hAlign: HA.left, vAlign: VA.center }); OVERVIEW_MODE_DEFINITIONS.forEach(function (item, index) { var row = rows.dataStart + index; var formula = buildCellFormula(cols.value, row, item.mode, item.barColor, item.bandColor, true); sheet.setRowHeight(row, item.rowHeight + 8); sheet.setValue(row, cols.mode, item.mode + " " + item.label); sheet.setValue(row, cols.value, item.value); sheet.setFormula(row, cols.sparkline, formula); sheet.setValue(row, cols.formula, formula); }); sheet.getRange(rows.header, 0, OVERVIEW_MODE_DEFINITIONS.length + 1, 4).setBorder(border, { all: true }); sheet.getRange(0, 0, totalRows, 4).vAlign(VA.center); } finally { sheet.resumePaint(); } } var RELEASE_READINESS_ROWS = [ { workstream: "Checkout", owner: "Iris", milestone: "Tax & totals parity", targetDate: "Apr 08", value: 0.82 }, { workstream: "Identity", owner: "Nolan", milestone: "SSO callback hardening", targetDate: "Apr 11", value: 0.64 }, { workstream: "Migration", owner: "Mia", milestone: "Legacy workbook import", targetDate: "Apr 14", value: 0.58 }, { workstream: "QA", owner: "Owen", milestone: "Regression sign-off", targetDate: "Apr 15", value: 0.75 }, { workstream: "Notifications", owner: "Ethan", milestone: "Template approval", targetDate: "Apr 18", value: 0.43 }, { workstream: "Billing", owner: "Chloe", milestone: "Gateway certification", targetDate: "Apr 19", value: 0.27 }, { workstream: "Audit", owner: "Liam", milestone: "Retention policy review", targetDate: "Apr 22", value: 0.56 }, { workstream: "Accessibility", owner: "Sofia", milestone: "VPAT evidence package", targetDate: "Apr 24", value: 0.91 } ]; function configureReleaseReadinessSheet(sheet) { var headerRow = 0; var dataStartRow = 1; var riskColumn = 4; var readinessColumn = 5; var rowCount = RELEASE_READINESS_ROWS.length; var totalRows = dataStartRow + rowCount; var border = createBorder("#d7dee7"); var source = { rows: createReleaseReadinessSource() }; sheet.suspendPaint(); try { configureSheetBase(sheet, "Release Readiness", totalRows, 6); registerReleaseReadinessNames(sheet); setColumnWidths(sheet, [240, 124, 250, 116, 108, 290]); var table = sheet.tables.add("releaseReadinessTable", headerRow, 0, totalRows, 6, spreadNS.Tables.TableThemes.light2); var tableColumns = [ new spreadNS.Tables.TableColumn(1, "workstream", "Workstream"), new spreadNS.Tables.TableColumn(2, "owner", "Owner"), new spreadNS.Tables.TableColumn(3, "milestone", "Milestone"), new spreadNS.Tables.TableColumn(4, "targetDate", "Target Date"), new spreadNS.Tables.TableColumn(5, null, "Risk"), new spreadNS.Tables.TableColumn(6, null, "Readiness") ]; table.autoGenerateColumns(false); table.bind(tableColumns, "rows", source); table.style(spreadNS.Tables.TableThemes["none"]); table.highlightFirstColumn(false); table.highlightLastColumn(false); styleHeaderRow(sheet, headerRow, 6, "#f3f6fb", "#314155"); sheet.setRowHeight(headerRow, 30); applyRangeStyle(sheet.getRange(dataStartRow, 0, rowCount, 1), { font: "bold 13px Segoe UI", foreColor: "#0f172a", hAlign: HA.left, vAlign: VA.center }); applyRangeStyle(sheet.getRange(dataStartRow, 1, rowCount, 2), { font: "13px Segoe UI", foreColor: "#334155", hAlign: HA.left, vAlign: VA.center }); applyRangeStyle(sheet.getRange(dataStartRow, 3, rowCount, 1), { font: "13px Segoe UI", foreColor: "#334155", hAlign: HA.center, vAlign: VA.center }); applyRangeStyle(sheet.getRange(dataStartRow, riskColumn, rowCount, 1), { font: "bold 13px Segoe UI", backColor: "#ffffff", hAlign: HA.center, vAlign: VA.center }); applyRangeStyle(sheet.getRange(dataStartRow, readinessColumn, rowCount, 1), { backColor: "#ffffff", hAlign: HA.center, vAlign: VA.center }); var riskRange = [new spreadNS.Range(dataStartRow, riskColumn, rowCount, 1)]; applySpecificTextColorRules(sheet, riskRange, { "On Track": "#475569", "At Risk": "#d97706", Alert: "#dc2626" }); RELEASE_READINESS_ROWS.forEach(function (item, index) { var row = dataStartRow + index; var riskFormula = buildReleaseReadinessRiskFormula(item.value); var readinessFormula = buildReleaseReadinessSparklineFormula(item.value); sheet.setRowHeight(row, 44); sheet.setFormula(row, riskColumn, riskFormula); sheet.setFormula(row, readinessColumn, readinessFormula); }); sheet.getRange(headerRow, 0, RELEASE_READINESS_ROWS.length + 1, 6).setBorder(border, { all: true }); } finally { sheet.resumePaint(); } } var SERVICE_HEALTH_CARDS = [ { title: "API Availability", subtitle: "7-day uptime", value: 0.99, target: 0.99, warningThreshold: 0.97, note: "2 auto-recovered incidents" }, { title: "Incident SLA", subtitle: "P1 response time", value: 0.86, target: 0.95, warningThreshold: 0.8, note: "3 of 22 alerts breached" }, { title: "Error Budget", subtitle: "Monthly remaining", value: 0.64, target: 0.75, warningThreshold: 0.55, note: "No release freeze needed" }, { title: "CPU Headroom", subtitle: "Peak cluster reserve", value: 0.72, target: 0.7, warningThreshold: 0.6, note: "Scale-out window still open" }, { title: "Patch Compliance", subtitle: "Servers patched", value: 0.91, target: 0.9, warningThreshold: 0.8, note: "2 edge nodes waiting reboot" }, { title: "Queue Drain", subtitle: "Backlog cleared", value: 0.58, target: 0.7, warningThreshold: 0.5, note: "Billing queue remains elevated" }, { title: "Backup Completion", subtitle: "Nightly jobs", value: 0.97, target: 0.95, warningThreshold: 0.85, note: "One archive retry pending" }, { title: "Certificate Renewal", subtitle: "Expiring in 30 days", value: 0.42, target: 0.8, warningThreshold: 0.6, note: "3 gateways still unrotated" } ]; function configureServiceHealthSheet(sheet) { var headerRow = 0; var metricRows = { subtitle: 1, current: 2, target: 3, health: 4, note: 5, progress: 6 }; var serviceStartColumn = 1; var cardCount = SERVICE_HEALTH_CARDS.length; var totalRows = 7; var totalColumns = serviceStartColumn + cardCount; var border = createBorder("#d8e0ea"); sheet.suspendPaint(); try { configureSheetBase(sheet, "Service Health", totalRows, totalColumns); registerServiceHealthNames(sheet); sheet.options.gridline.showVerticalGridline = true; sheet.options.gridline.showHorizontalGridline = true; sheet.setColumnWidth(0, 165); setUniformColumnWidths(sheet, serviceStartColumn, cardCount, 210); styleHeaderRow(sheet, headerRow, totalColumns, "#f3f6fb", "#314155"); sheet.getRange(headerRow, 0, 1, totalColumns).font("bold 14px Segoe UI"); sheet.addSpan(headerRow, 0, 2, 1); sheet.setValue(headerRow, 0, "Metric"); setRowHeights(sheet, { 0: 38, 1: 30, 2: 38, 3: 34, 4: 34, 5: 54, 6: 116 }); sheet.getCell(headerRow, 0) .hAlign(HA.center) .vAlign(VA.center); applyRangeStyle(sheet.getRange(metricRows.subtitle, serviceStartColumn, 1, cardCount), { backColor: "#f8fafc", foreColor: "#64748b", font: "12px Segoe UI", wordWrap: true, hAlign: HA.center, vAlign: VA.center }); sheet.setArray(metricRows.current, 0, [["Current"], ["Target"], ["Health"], ["Note"], ["Progress"]]); [metricRows.current, metricRows.target, metricRows.health, metricRows.note, metricRows.progress].forEach(function (row) { sheet.getCell(row, 0) .font("bold 14px Segoe UI") .foreColor("#475569") .backColor("#f8fafc") .hAlign(HA.center) .vAlign(VA.center); }); applyRangeStyle(sheet.getRange(metricRows.current, serviceStartColumn, 1, cardCount), { font: "bold 13px Segoe UI", foreColor: "#0f172a", hAlign: HA.center, vAlign: VA.center, formatter: "0%" }); applyRangeStyle(sheet.getRange(metricRows.target, serviceStartColumn, 1, cardCount), { font: "13px Segoe UI", foreColor: "#475569", hAlign: HA.center, vAlign: VA.center, formatter: "0%" }); applyRangeStyle(sheet.getRange(metricRows.health, serviceStartColumn, 1, cardCount), { font: "bold 13px Segoe UI", backColor: "#ffffff", hAlign: HA.center, vAlign: VA.center }); applyRangeStyle(sheet.getRange(metricRows.note, serviceStartColumn, 1, cardCount), { font: "13px Segoe UI", foreColor: "#64748b", backColor: "#ffffff", wordWrap: true, hAlign: HA.left, vAlign: VA.center }); applyRangeStyle(sheet.getRange(metricRows.progress, serviceStartColumn, 1, cardCount), { backColor: "#ffffff", hAlign: HA.center, vAlign: VA.center }); var healthRange = [new spreadNS.Range(metricRows.health, serviceStartColumn, 1, cardCount)]; applySpecificTextColorRules(sheet, healthRange, { Healthy: "#15803d", Warning: "#d97706", Critical: "#dc2626" }); sheet.setArray(headerRow, serviceStartColumn, [SERVICE_HEALTH_CARDS.map(function (card) { return card.title; })]); sheet.setArray(metricRows.subtitle, serviceStartColumn, [SERVICE_HEALTH_CARDS.map(function (card) { return card.subtitle; })]); sheet.setArray(metricRows.current, serviceStartColumn, [SERVICE_HEALTH_CARDS.map(function (card) { return card.value; })]); sheet.setArray(metricRows.target, serviceStartColumn, [SERVICE_HEALTH_CARDS.map(function (card) { return card.target; })]); sheet.setArray(metricRows.note, serviceStartColumn, [SERVICE_HEALTH_CARDS.map(function (card) { return card.note; })]); for (var index = 0; index < SERVICE_HEALTH_CARDS.length; index++) { var card = SERVICE_HEALTH_CARDS[index]; var col = serviceStartColumn + index; var currentValueRef = columnName(col) + (metricRows.current + 1); var targetValueRef = columnName(col) + (metricRows.target + 1); var healthFormula = buildServiceHealthFormula(currentValueRef, targetValueRef, card.warningThreshold); var sparklineFormula = buildServiceHealthSparklineFormula(currentValueRef, targetValueRef, card.warningThreshold); sheet.setFormula(metricRows.health, col, healthFormula); sheet.setFormula(metricRows.progress, col, sparklineFormula); } sheet.getRange(headerRow, 0, metricRows.progress - headerRow + 1, totalColumns).setBorder(border, { all: true }); } finally { sheet.resumePaint(); } } var TRAINING_ROWS = [ { learner: "Emma Johnson", program: "Admin Certification", modulesDone: 11, totalModules: 12, nextStep: "Book final exam" }, { learner: "Liam Smith", program: "API Integration Track", modulesDone: 8, totalModules: 12, nextStep: "Finish capstone lab" }, { learner: "Olivia Davis", program: "Template Design Bootcamp", modulesDone: 6, totalModules: 10, nextStep: "Review module 7" }, { learner: "Noah Wilson", program: "Migration Specialist", modulesDone: 4, totalModules: 9, nextStep: "Attend coaching session" }, { learner: "Ava Martinez", program: "Dashboard Authoring", modulesDone: 12, totalModules: 12, nextStep: "Submit certification badge" }, { learner: "Ethan Brown", program: "Designer Power User", modulesDone: 7, totalModules: 8, nextStep: "Schedule practical review" }, { learner: "Sophia Lee", program: "Workbook Automation", modulesDone: 5, totalModules: 11, nextStep: "Complete lab workbook" }, { learner: "Mason Taylor", program: "Report Authoring", modulesDone: 9, totalModules: 14, nextStep: "Prepare peer assessment" }, { learner: "Isabella Wang", program: "Governance & Audit", modulesDone: 10, totalModules: 10, nextStep: "Archive completion record" }, { learner: "Lucas Chen", program: "Calculation Engine", modulesDone: 3, totalModules: 8, nextStep: "Catch up on core formulas" } ]; var LEARNING_PROGRESS_FORMATTER = '=PROGRESSSPARKLINE(@,2,"#6B7C93","#E7EDF5",TRUE)'; function configureLearningProgressSheet(sheet) { var headerRow = 0; var dataStartRow = 1; var rowCount = TRAINING_ROWS.length; var totalRows = dataStartRow + rowCount; var border = createBorder("#d7dee7"); sheet.suspendPaint(); try { configureSheetBase(sheet, "Learning Progress", totalRows, 6); setColumnWidths(sheet, [170, 210, 110, 110, 320, 210]); styleHeaderRow(sheet, headerRow, 6, "#f3f6fb", "#314155"); setHeaderValues(sheet, headerRow, ["Learner", "Program", "Modules Done", "Total Modules", "Completion", "Next Step"]); sheet.setRowHeight(headerRow, 30); applyRangeStyle(sheet.getRange(dataStartRow, 0, rowCount, 1), { font: "bold 13px Segoe UI", foreColor: "#0f172a", hAlign: HA.left, vAlign: VA.center }); applyRangeStyle(sheet.getRange(dataStartRow, 1, rowCount, 1), { font: "12px Segoe UI", foreColor: "#475569", hAlign: HA.left, vAlign: VA.center }); applyRangeStyle(sheet.getRange(dataStartRow, 2, rowCount, 2), { font: "12px Consolas", foreColor: "#334155", hAlign: HA.right, vAlign: VA.center }); applyRangeStyle(sheet.getRange(dataStartRow, 4, rowCount, 1), { backColor: "#ffffff", hAlign: HA.center, vAlign: VA.center, formatter: LEARNING_PROGRESS_FORMATTER }); applyRangeStyle(sheet.getRange(dataStartRow, 5, rowCount, 1), { font: "12px Segoe UI", foreColor: "#475569", backColor: "#ffffff", hAlign: HA.left, vAlign: VA.center }); sheet.setArray(dataStartRow, 0, toColumnMatrix(TRAINING_ROWS, function (item) { return item.learner; })); sheet.setArray(dataStartRow, 1, toColumnMatrix(TRAINING_ROWS, function (item) { return item.program; })); sheet.setArray(dataStartRow, 2, TRAINING_ROWS.map(function (item) { return [item.modulesDone, item.totalModules]; })); sheet.setArray(dataStartRow, 5, toColumnMatrix(TRAINING_ROWS, function (item) { return item.nextStep; })); TRAINING_ROWS.forEach(function (item, index) { var row = dataStartRow + index; var modulesDoneRef = columnName(2) + (row + 1); var totalModulesRef = columnName(3) + (row + 1); var formula = '=IF(' + totalModulesRef + '=0,0,' + modulesDoneRef + '/' + totalModulesRef + ')'; sheet.setRowHeight(row, 44); sheet.setFormula(row, 4, formula); }); sheet.getRange(headerRow, 0, TRAINING_ROWS.length + 1, 6).setBorder(border, { all: true }); } finally { sheet.resumePaint(); } }
<!doctype html> <html style="height: 100%; font-size: 14px;"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets/dist/gc.spread.sheets.all.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 id="ss" class="sample-spreadsheets" aria-live="polite"></div> <noscript> <div class="load-error">JavaScript is required to load this demo.</div> </noscript> </body> </html>
html, body { height: 100%; margin: 0; } body { position: absolute; inset: 0; background: #ffffff; } .sample-spreadsheets { width: 100%; height: 100%; overflow: hidden; background: #ffffff; }