소개

SpreadJS는 서식 있는 텍스트를 지원합니다. 위 첨자, 아래 첨자 및 서로 다른 텍스트 스타일을 하나의 셀에 표시할 수 있습니다. 오른쪽 편집기를 사용하여 다양한 스타일의 텍스트를 만든 다음, ‘서식 있는 텍스트 설정’ 버튼을 사용하여 셀에서 설정할 수 있습니다.

서식 있는 텍스트 데이터는 익명 객체이며, JSON 스키마를 따라야 합니다. 다음 코드를 사용하여 지정된 시트 영역에서 지정된 셀의 값을 설정할 수 있습니다. 다음 코드를 사용하여 지정된 시트 영역의 지정된 셀에서 서식 없는 데이터를 가져올 수 있습니다. 업데이트됨: 현재 지원하는 서식 있는 텍스트 목록
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="ko-kr" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-designer/styles/gc.spread.sheets.designer.min.css"> <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-shapes/dist/gc.spread.sheets.shapes.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-charts/dist/gc.spread.sheets.charts.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-print/dist/gc.spread.sheets.print.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-barcode/dist/gc.spread.sheets.barcode.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-pdf/dist/gc.spread.sheets.pdf.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-pivot-addon/dist/gc.spread.pivot.pivottables.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-slicers/dist/gc.spread.sheets.slicers.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-formula-panel/dist/gc.spread.sheets.formulapanel.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-sheets-io/dist/gc.spread.sheets.io.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ko/purejs/node_modules/@mescius/spread-excelio/dist/gc.spread.excelio.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$/ko/purejs/node_modules/@mescius/spread-sheets-designer-resources-ko/dist/gc.spread.sheets.designer.resource.ko.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/ko/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%; }