概述

SpreadJS支持富文本。您可以在一个单元格中显示上标、下标和不同的文本样式。右侧的编辑器可用于创建具有不同样式的文本。

富文本数据是一个匿名对象,应该对应的遵循富文本JSON Schema。 您可以使用以下代码在指定的单元格和指定的工作表区域设置值: 您可以使用以下代码从指定的单元格和指定的工作表区域获取未格式化的数据: 更新:富文本现在支持列表
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块牛里脊牛排(每块约6盎司)" }] }, { type: GC.Spread.Sheets.ListType.disc, richText: [{ text: "盐和黑胡椒,按个人口味添加" }] }, { type: GC.Spread.Sheets.ListType.disc, richText: [{ text: "2汤匙橄榄油" }] }, { type: GC.Spread.Sheets.ListType.disc, richText: [{ text: "2汤匙第戎芥末酱" }] }, { type: GC.Spread.Sheets.ListType.disc, richText: [{ text: "8片意大利熏火腿或帕尔玛火腿" }] }, { type: GC.Spread.Sheets.ListType.disc, richText: [{ text: "1包(17.3盎司)酥皮,解冻" }] }, { type: GC.Spread.Sheets.ListType.disc, richText: [{ text: "1个打散的鸡蛋(用于刷蛋液)" }] }, { type: GC.Spread.Sheets.ListType.disc, richText: [{ text: "蘑菇酱:" }] }, { type: GC.Spread.Sheets.ListType.circle, level: 1, richText: [{ text: "2汤匙黄油" }] }, { type: GC.Spread.Sheets.ListType.circle, level: 1, richText: [{ text: "1个小洋葱,切碎" }] }, { type: GC.Spread.Sheets.ListType.circle, level: 1, richText: [{ text: "8盎司蘑菇,切碎" }] }, { type: GC.Spread.Sheets.ListType.circle, level: 1, richText: [{ text: "2瓣大蒜,切末" }] }, { type: GC.Spread.Sheets.ListType.circle, level: 1, richText: [{ text: "2枝新鲜百里香,只取叶子" }] }, { type: GC.Spread.Sheets.ListType.circle, level: 1, richText: [{ text: "盐和黑胡椒,按个人口味添加" }] }] }; const instructions = { richText: [{ type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "将烤箱预热至400°F(200°C)。" }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "在牛里脊牛排的两面撒上盐和黑胡椒调味。" }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "在平底锅中用大火加热橄榄油。将牛排每面煎1 - 2分钟,直到表面变成褐色。从火上移开,让牛排冷却。" }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "制作蘑菇酱:在同一个平底锅中,用中火融化黄油。加入小洋葱,煮至变软。加入蘑菇、大蒜和百里香。煮至蘑菇释放出水分并蒸发。用盐和黑胡椒调味。从火上移开,让其冷却。" }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "在干净的表面上,将意大利熏火腿或帕尔玛火腿片稍微重叠铺成一个足够大的矩形,以便包裹每块牛排。" }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "在冷却后的牛排上均匀涂抹一层薄薄的第戎芥末酱。将每块牛排放在熏火腿矩形上。" }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "将蘑菇酱均匀地舀在每块牛排上。" }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "小心地用酥皮将裹有熏火腿和蘑菇酱的牛排包起来,确保接缝密封。修剪掉多余的酥皮。" }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "将包好的牛排放在铺有羊皮纸的烤盘上。在酥皮上刷上打散的鸡蛋,使其表面金黄。" }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "放入预热好的烤箱中烤约20 - 25分钟,或直到酥皮变成金黄色,牛排达到你喜欢的熟度。半熟牛排的内部温度应在130 - 135°F(55 - 57°C)左右。" }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "从烤箱中取出,让惠灵顿牛排静置几分钟后再上桌。" }] }, { type: GC.Spread.Sheets.ListType.decimal, richText: [{ text: "将惠灵顿牛排切片上桌,搭配你喜欢的配菜,如烤土豆、蒸蔬菜或蔬菜沙拉享用。" }] }] }; spread.suspendPaint(); const sheet = spread.sheets[0]; sheet.setColumnWidth(0, 720); sheet.setValue(0, 0, '万有引力定律:', 3); sheet.setValue(1, 0, lawOfUniversalGravitation, 3); sheet.setRowHeight(1, 40); sheet.getCell(1, 0).vAlign(spreadNS.VerticalAlign.center); sheet.setValue(3, 0, '氢氧化钡与磷酸的反应:', 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('基本用法'); const listSheet = new GC.Spread.Sheets.Worksheet('列表用法'); spread.addSheet(1, listSheet); listSheet.setColumnWidth(0, 720); listSheet.setValue(0, 0, '惠灵顿牛排食材'); listSheet.setValue(1, 0, ingredients); listSheet.getCell(1, 0).wordWrap(true); listSheet.autoFitRow(1); listSheet.setValue(3, 0, '惠灵顿牛排制作步骤'); 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, oldValue; 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 oldValue; } oldSheetName = activeSheet.name(); oldRow = activeRow; oldCol = activeCol; const richTextItems = richEditorHelper.getRichTextItemsForRichEditor(activeSheet, activeRow, activeCol); oldValue = { value: { value: { richText: richTextItems }, style: activeSheet.getActualStyle(activeRow, activeCol) } }; return oldValue; } } 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" /> <meta name="spreadjs culture" content="zh-cn" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-designer/styles/gc.spread.sheets.designer.min.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-shapes/dist/gc.spread.sheets.shapes.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-charts/dist/gc.spread.sheets.charts.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-print/dist/gc.spread.sheets.print.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-barcode/dist/gc.spread.sheets.barcode.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-pivot-addon/dist/gc.spread.pivot.pivottables.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-slicers/dist/gc.spread.sheets.slicers.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-tablesheet/dist/gc.spread.sheets.tablesheet.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-formula-panel/dist/gc.spread.sheets.formulapanel.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-sheets-io/dist/gc.spread.sheets.io.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/spread-excelio/dist/gc.spread.excelio.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$/zh/purejs/node_modules/@grapecity-software/spread-sheets-designer-resources-cn/dist/gc.spread.sheets.designer.resource.cn.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/zh/purejs/node_modules/@grapecity-software/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%; }