概述

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 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" /> <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%; }