Overview

SpreadJS supports rich text. You can show superscript, subscript and different text styles in one cell. The editor on the right can be used to create text with different styles.

Rich text data is an anonymous object, you should follow the JSON Schema. You can set the value for the specified cell in the specified sheet area using the following code: You can get the unformatted data from the specified cell in the specified sheet area using the following code: Updated: Rich text now support list
const spreadNS = GC.Spread.Sheets; window.onload = function () { init(); }; function initSpread(spread) { const lawOfUniversalGravitation = { richText: [ { style: { font: "normal 24px Calibri" }, text: "F = (G * M" }, { style: { font: "normal 24px Calibri", vertAlign: 2 }, text: "1" }, { style: { font: "normal 24px Calibri" }, text: " * M" }, { style: { font: "normal 24px Calibri", vertAlign: 2 }, text: "2" }, { style: { font: "normal 24px Calibri" }, text: ") / R" }, { style: { font: "normal 24px Calibri", vertAlign: 1 }, text: "2" } ] }; const reaction = { richText: [ { style: { font: "normal 24px Calibri" }, text: "3 Ba(OH)" }, { style: { font: "normal 24px Calibri", vertAlign: 2 }, text: "2" }, { style: { font: "normal 24px Calibri" }, text: " + 2 H" }, { style: { font: "normal 24px Calibri", vertAlign: 2 }, text: "3" }, { style: { font: "normal 24px Calibri" }, text: "PO" }, { style: { font: "normal 24px Calibri", vertAlign: 2 }, text: "4" }, { style: { font: "normal 24px Calibri" }, text: " → 6 H" }, { style: { font: "normal 24px Calibri", vertAlign: 2 }, text: "2" }, { style: { font: "normal 24px Calibri" }, text: "O + Ba" }, { style: { font: "normal 24px Calibri", vertAlign: 2 }, text: "3" }, { style: { font: "normal 24px Calibri" }, text: "(PO" }, { style: { font: "normal 24px Calibri", vertAlign: 2 }, text: "4" }, { style: { font: "normal 24px Calibri" }, text: ")" }, { style: { font: "normal 24px Calibri", vertAlign: 2 }, text: "2" }, { style: { font: "normal 24px Calibri" }, text: "↓" } ] }; const google = { richText: [ { style: { font: "bold 36px Calibri", foreColor: "rgb(78,133,242)" }, text: "G" }, { style: { font: "bold 36px Calibri", foreColor: "rgb(228,65,52)" }, text: "o" }, { style: { font: "bold 36px Calibri", foreColor: "rgb(247,188,32)" }, text: "o" }, { style: { font: "bold 36px Calibri", foreColor: "rgb(78,133,242)" }, text: "g" }, { style: { font: "bold 36px Calibri", foreColor: "rgb(65,168,87)" }, text: "l" }, { style: { font: "bold 36px Calibri", foreColor: "rgb(228,65,52)" }, text: "e" } ] }; const ingredients = { richText: [{ type: GC.Spread.Sheets.ListType.disc, richText: [{ text: "4 beef fillet steaks (about 6 ounces each)" }] }, { type: GC.Spread.Sheets.ListType.disc, richText: [{ text: "Salt and black pepper, to taste" }] }, { type: GC.Spread.Sheets.ListType.disc, richText: [{ text: "2 tablespoons olive oil" }] }, { type: GC.Spread.Sheets.ListType.disc, richText: [{ text: "2 tablespoons Dijon mustard" }] }, { type: GC.Spread.Sheets.ListType.disc, richText: [{ text: "8 slices of prosciutto or Parma ham" }] }, { type: GC.Spread.Sheets.ListType.disc, richText: [{ text: "1 package (17.3 ounces) puff pastry, thawed" }] }, { type: GC.Spread.Sheets.ListType.disc, richText: [{ text: "1 egg, beaten (for egg wash)" }] }, { type: GC.Spread.Sheets.ListType.disc, richText: [{ text: "Mushroom Duxelles:" }] }, { type: GC.Spread.Sheets.ListType.circle, level: 1, richText: [{ text: "2 tablespoons butter" }] }, { type: GC.Spread.Sheets.ListType.circle, level: 1, richText: [{ text: "1 shallot, finely chopped" }] }, { type: GC.Spread.Sheets.ListType.circle, level: 1, richText: [{ text: "8 ounces mushrooms, finely chopped" }] }, { type: GC.Spread.Sheets.ListType.circle, level: 1, richText: [{ text: "2 cloves garlic, minced" }] }, { type: GC.Spread.Sheets.ListType.circle, level: 1, richText: [{ text: "2 sprigs fresh thyme, leaves only" }] }, { type: GC.Spread.Sheets.ListType.circle, level: 1, richText: [{ text: "Salt and black pepper, to taste" }] }] }; const instructions = { richText: [{ type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "Preheat the oven to 400°F (200°C)." }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "Season the beef fillet steaks with salt and black pepper on both sides." }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "Heat olive oil in a skillet over high heat. Sear the steaks for about 1-2 minutes on each side until browned. Remove from heat and let them cool." }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "Prepare the mushroom duxelles: In the same skillet, melt butter over medium heat. Add the shallot and cook until softened. Add the mushrooms, garlic, and thyme. Cook until the mushrooms release their moisture and it evaporates. Season with salt and black pepper. Remove from heat and let it cool." }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "On a clean surface, spread out the slices of prosciutto or Parma ham in a slightly overlapping manner to form a rectangle large enough to wrap each steak." }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "Spread a thin layer of Dijon mustard over the cooled steaks. Place each steak on top of a prosciutto rectangle." }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "Spoon the mushroom duxelles evenly over each steak." }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "Carefully wrap the prosciutto and mushroom-covered steaks with the puff pastry, ensuring the seams are sealed. Trim off any excess pastry." }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "Place the wrapped steaks on a baking sheet lined with parchment paper. Brush the puff pastry with beaten egg to create a golden crust." }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "Bake in the preheated oven for about 20-25 minutes, or until the puff pastry is golden brown and the steak is cooked to your desired doneness. For medium-rare, the internal temperature should be around 130-135°F (55-57°C)." }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "Remove from the oven and let the Steak Wellington rest for a few minutes before serving." }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "Serve the Steak Wellington sliced, and enjoy it with your favorite sides like roasted potatoes, steamed vegetables, or a green salad." }] }] }; spread.suspendPaint(); const sheet = spread.sheets[0]; sheet.setColumnWidth(0, 720); sheet.setValue(0, 0, 'Law of universal gravitation:', 3); sheet.setValue(1, 0, lawOfUniversalGravitation, 3); sheet.setRowHeight(1, 40); sheet.getCell(1, 0).vAlign(spreadNS.VerticalAlign.center); sheet.setValue(3, 0, 'The reaction of barium hydroxide with phosphoric acid:', 3); sheet.setValue(4, 0, reaction, 3); sheet.setRowHeight(4, 40); sheet.getCell(4, 0).vAlign(spreadNS.VerticalAlign.center); sheet.setValue(6, 0, google, 3); sheet.setRowHeight(6, 50); sheet.name('Basic Usage'); const listSheet = new GC.Spread.Sheets.Worksheet('List Usage'); spread.addSheet(1, listSheet); spread.setActiveSheet('List Usage'); listSheet.setColumnWidth(0, 720); listSheet.setValue(0, 0, 'Steak Wellington Ingredients'); listSheet.setValue(1, 0, ingredients); listSheet.getCell(1, 0).wordWrap(true); listSheet.autoFitRow(1); listSheet.setValue(3, 0, 'Steak Wellington Instructions'); listSheet.setValue(4, 0, instructions); listSheet.getCell(4, 0).wordWrap(true); listSheet.autoFitRow(4); spread.resumePaint(); spread.options.tabStripRatio = 0.8; } function getDesignerConfig () { GC.Spread.Sheets.Designer.registerTemplate("richEditor", { content: [{ type: "RichTextEditor", bindingPath: "value", editorWidth: "640px", editorHeight: "542px", onChange: (value, spread) => { if (!spread || !value) { return; } let sheet = spread.getActiveSheet(); sheet.setValue(sheet.getActiveRowIndex(), sheet.getActiveColumnIndex(), value.value); } }] }); const richEditorPanel = { position: "right", width: "640px", command: "richEditor", uiTemplate: "richEditor" }; let oldSheetName, oldRow, oldCol; const richEditorCommand = { commandName: 'richEditor', getState: (context) => { const spread = context.getWorkbook(), activeSheet = spread.getActiveSheet(), activeRow = activeSheet.getActiveRowIndex(), activeCol = activeSheet.getActiveColumnIndex(); // only when change active cell, need to reset editor content if (oldSheetName === activeSheet.name() && oldRow === activeRow && oldCol === activeCol) { return; } oldSheetName = activeSheet.name(); oldRow = activeRow; oldCol = activeCol; const richTextItems = richEditorHelper.getRichTextItemsForRichEditor(activeSheet, activeRow, activeCol); return { value: { value: { richText: richTextItems }, style: activeSheet.getActualStyle(activeRow, activeCol) } }; } } return { contextMenu: [], ribbon: [], sidePanels: [richEditorPanel], commandMap: { richEditor: richEditorCommand } }; } function init() { const designer = new spreadNS.Designer.Designer(document.getElementById('ribbonHost'), getDesignerConfig()); const spread = designer.getWorkbook(); initSpread(spread); } const richEditorHelper = { toHexColor (color) { let reg = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/; if (/^(rgb|RGB)/.test(color)) { let aColor = color.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(","); let strHex = "#"; for (let i = 0; i < aColor.length; i++) { let hex = Number(aColor[i]).toString(16); if (hex.length < 2) { hex = '0' + hex; } strHex += hex; } if (strHex.length !== 7) { strHex = color; } return strHex; } else if (reg.test(color)) { let aNum = color.replace(/#/, "").split(""); if (aNum.length === 6) { return color; } else if (aNum.length === 3) { let numHex = "#"; for (let i = 0; i < aNum.length; i += 1) { numHex += (aNum[i] + aNum[i]); } return numHex; } } return color; }, getStandardFont (unStandardFont) { if (!unStandardFont) { return; } let style = new spreadNS.Style(); style.font = unStandardFont; let { fontWeight, fontSize } = style; if (!isNaN(fontWeight)) { style.fontWeight = +fontWeight >= 700 ? "bold" : "normal"; } style.fontSize = (fontSize.indexOf("px") > 0) ? (Math.round((+(fontSize.split("px")[0])) * 3 / 4) + "pt") : fontSize; return style.font; }, setDefaultStyleToRichItem (richText, font, foreColor, textDecoration) { richText.style = { font, foreColor, textDecoration }; }, isNullOrUndefined (value) { return value === undefined || value === null; }, composeCurrentRichItemStyleWithActiveCellStyle (richText, cellStyle, theme) { const currentItemStyle = richText.style; if (currentItemStyle.foreColor === undefined && !richEditorHelper.isNullOrUndefined(cellStyle.foreColor)) { currentItemStyle.foreColor = cellStyle.foreColor; } if (currentItemStyle.font === undefined && !richEditorHelper.isNullOrUndefined(cellStyle.font)) { currentItemStyle.font = cellStyle.font; } else if (currentItemStyle.font) { currentItemStyle.font = richEditorHelper.getStandardFont(currentItemStyle.font); } if (currentItemStyle.textDecoration === undefined && !richEditorHelper.isNullOrUndefined(cellStyle.textDecoration)) { currentItemStyle.textDecoration = cellStyle.textDecoration; } currentItemStyle.foreColor = richEditorHelper.toHexColor(theme.getColor(currentItemStyle.foreColor)); }, splitRichTextByLineBreaker (richText, newRichTexts) { const currentItemStyle = richText.style; const wrappedTexts = richText.text.split(/\r?\n/g); for (let j = 0, wrapperLen = wrappedTexts.length; j < wrapperLen; j++) { let obj = {}; obj.text = wrappedTexts[j]; obj.style = currentItemStyle; if (obj.text) { newRichTexts.push(obj); } if (j !== wrapperLen - 1) { newRichTexts.push({ text: '\r\n', style: currentItemStyle }); } } }, createRichTextsFromPlainText (sheet, row, col, font, foreColor, textDecoration) { const text = sheet.getText(row, col); const wrappedTexts = text.split("\n"); const richTexts = []; for (let i = 0, len = wrappedTexts.length; i < len; i++) { if (wrappedTexts[i]) { richTexts.push({ text: wrappedTexts[i], style: { font, foreColor, textDecoration } }); } if (i !== len - 1) { richTexts.push({ text: '\r\n', style: richTexts[i].style }); } } return richTexts; }, getRichStyleFromCellStyle (cellStyle, theme) { return { font: cellStyle.font, textDecoration: cellStyle.textDecoration, foreColor: cellStyle.foreColor } }, getRichTextItemsForRichEditor (sheet, row, col) { const value = sheet.getValue(row, col, spreadNS.SheetArea.viewport, spreadNS.ValueType.richText); const cellStyle = sheet.getActualStyle(row, col); const theme = sheet.currentTheme(); if (cellStyle.foreColor && theme) { cellStyle.foreColor = richEditorHelper.toHexColor(theme.getColor(cellStyle.foreColor)); } if (!value) { return [{ text: "", style: richEditorHelper.getRichStyleFromCellStyle(cellStyle) }]; } let richTexts = value.richText; let foreColor = cellStyle.foreColor || "#000000"; let textDecoration = cellStyle.textDecoration; let font = cellStyle.font ? richEditorHelper.getStandardFont(cellStyle.font) : "11pt Calibri"; if (richTexts) { let newRichTexts = []; for (let i = 0, len = richTexts.length; i < len; i++) { if (!richTexts[i]) { continue; } if (!richTexts[i].style) { richEditorHelper.setDefaultStyleToRichItem(richTexts[i], font, foreColor, textDecoration); } else if (richTexts[i].style) { richEditorHelper.composeCurrentRichItemStyleWithActiveCellStyle(richTexts[i], cellStyle, theme); } if (richTexts[i].text && richTexts[i].text !== "\r\n" && richTexts[i].text !== '\n' && richTexts[i].text.split(/\r?\n/g).length > 1) { richEditorHelper.splitRichTextByLineBreaker(richTexts[i], newRichTexts); } else { newRichTexts.push(richTexts[i]); } } return newRichTexts; } else { return richEditorHelper.createRichTextsFromPlainText(sheet, row, col, font, foreColor, textDecoration); } } }
<!doctype html> <html style="height:100%;font-size:14px;"> <head> <meta name="spreadjs culture"/> <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"> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-designer/styles/gc.spread.sheets.designer.min.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$/en/purejs/node_modules/@mescius/spread-sheets-shapes/dist/gc.spread.sheets.shapes.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-charts/dist/gc.spread.sheets.charts.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-print/dist/gc.spread.sheets.print.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-barcode/dist/gc.spread.sheets.barcode.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-pivot-addon/dist/gc.spread.pivot.pivottables.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-slicers/dist/gc.spread.sheets.slicers.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-tablesheet/dist/gc.spread.sheets.tablesheet.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-formula-panel/dist/gc.spread.sheets.formulapanel.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-io/dist/gc.spread.sheets.io.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-excelio/dist/gc.spread.excelio.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-designer-resources-en/dist/gc.spread.sheets.designer.resource.en.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-designer/dist/gc.spread.sheets.designer.all.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/js/designer/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="container"> <div class="spreadSheet"> <div id="ribbonHost"></div> <div id="ss"></div> </div> </div> </body> </html>
.sample-tutorial { position: relative; height: 100%; overflow: hidden; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; } .container { height: 100%; } .spreadSheet { height: 100%; } #ribbonHost { height: 100%; } .description { margin: 10px; width: 40%; }