概述
本 Demo 展示了如何自定义 SpreadJS Designer 的 Ribbon 工具栏布局。通过修改 Designer 配置,实现了隐藏特定选项卡和按钮组、禁用功能按钮、自定义本地化文本以及移除右键菜单项等功能。
实现思路
获取 Designer 的默认配置对象 DefaultConfig
通过数组过滤方法隐藏不需要的 Ribbon 选项卡(仅保留 home、data、view)
在保留的选项卡中进一步过滤按钮组,只显示必要的功能区域
使用 commandMap 的 enableContext 属性禁用特定按钮
使用 getResources() 和 setResources() 方法自定义界面文本
从 contextMenu 数组中移除不需要的右键菜单项
使用自定义配置初始化 Designer 实例
代码解析
隐藏 Ribbon 选项卡
这段代码从默认配置中获取 ribbon 数组,使用 filter 方法移除 id 为 'insert'、'pageLayout'、'formulas' 和 'settings' 的选项卡,仅保留 home、data 和 view 选项卡。
隐藏按钮组
每个 Ribbon 选项卡包含多个 buttonGroups(按钮组)。这段代码先找到 home 选项卡,然后过滤掉标签为'数字'、'样式'和'编辑'的按钮组。
禁用按钮
通过在 commandMap 中设置命令的 enableContext 为字符串 'false',可以永久禁用这些按钮。decreaseIndent 和 increaseIndent 是减少缩进和增加缩进按钮,orientationList 是文字方向下拉列表。
自定义本地化文本
使用 getResources() 获取资源对象,修改选项卡名称、按钮文本等内容,然后通过 setResources() 设置回去。这里将主要选项卡的文本改为英文大写形式,同时修改了确定和取消按钮的文本。
移除右键菜单项
config.contextMenu 是一个包含所有右键菜单命令名称的数组。通过遍历数组并使用 splice 方法,可以移除不需要的菜单项。commandNames 对象包含了所有命令的名称常量。
运行效果
Designer 启动后只显示 3 个选项卡:HOME、DATA、VIEW
每个选项卡中只包含特定的按钮组,界面更加简洁
缩进按钮和文字方向下拉列表处于禁用状态,无法点击
选项卡名称和部分按钮文本显示为英文大写形式
右键菜单中不显示富文本、插入批注、定义名称等菜单项
API 参考
GC.Spread.Sheets.Designer.DefaultConfig
获取 Designer 的默认配置对象,包含 ribbon 选项卡、contextMenu 右键菜单等完整配置信息。
config.ribbon
Ribbon 选项卡数组,每个选项卡包含:
id: 选项卡唯一标识
text: 显示文本
buttonGroups: 按钮组数组
config.commandMap
命令映射对象,用于自定义命令行为:
enableContext: 控制按钮是否可用,设置为字符串 'false' 可永久禁用
visibleContext: 控制按钮是否可见
GC.Spread.Sheets.Designer.getResources()
返回当前的资源对象,包含所有界面文本的本地化字符串。
GC.Spread.Sheets.Designer.setResources(resources)
设置自定义的资源对象:
resources: 包含修改后的本地化字符串的对象
config.contextMenu
右键菜单命令名称数组,移除数组中的项即可隐藏对应的右键菜单项。
window.onload = function () {
initRibbon();
};
function initRibbon() {
var config = GC.Spread.Sheets.Designer.DefaultConfig,
commandNames = GC.Spread.Sheets.Designer.CommandNames;
// Hide tabs except "Insert", "Page Layout", "Formula" and "Settings"
config.ribbon = config.ribbon.filter(
(rb) => rb.id !== 'insert' && rb.id !== 'pageLayout' && rb.id !== 'formulas' && rb.id !== 'settings'
);
// Hide button except groups "Number", "Style" and "Edit" on Home tab
let homeTab = config.ribbon.find((r) => r.id === 'home');
homeTab.buttonGroups = homeTab.buttonGroups.filter(
(bg) => bg.label !== '数字' && bg.label !== '样式' && bg.label !== '编辑'
);
// Hide button except groups "Data Binding", "Query and Connection", "Outline" in Data tab
let dataTab = config.ribbon.find((r) => r.id === 'data');
dataTab.buttonGroups = dataTab.buttonGroups.filter(
(bg) => bg.label !== '数据绑定' && bg.label !== '查询和连接' && bg.label !== '分级显示'
);
// Hide button except groups "Zoom", "Viewport" and "Pane" in View tab
let viewTab = config.ribbon.find((r) => r.id === 'view');
viewTab.buttonGroups = viewTab.buttonGroups.filter(
(bg) => bg.label !== '显示比例' && bg.label !== '窗口' && bg.label !== '窗格'
);
// Hide "Format" except button in cell button group
let cellButtonGroup = homeTab.buttonGroups.find((bg) => bg.label === 'Cells');
if (cellButtonGroup) {
cellButtonGroup.commandGroup.children = cellButtonGroup.commandGroup.children.filter(
(cg) => cg.command !== 'cellsFormat'
);
}
// Disable some buttons
config.commandMap = {
// disable decreaseIndent
decreaseIndent: {
enableContext: 'false',
},
// disable increaseIndent
increaseIndent: {
enableContext: 'false',
},
// Disable orientationList
orientationList: {
enableContext: 'false',
},
};
// Customizing the localization of the ribbon container
var resources = GC.Spread.Sheets.Designer.getResources();
resources.ribbon.home.home = 'HOME';
resources.ribbon.data.data = 'DATA';
resources.ribbon.view.view = 'VIEW';
resources.ok = 'OK';
resources.cancel = 'CANCEL';
resources.formatDialog.title = 'FORMAT DIALOG';
resources.ribbon.home.wrapText = 'WRAP TEXT';
resources.ribbon.home.insert = 'INSERT';
resources.ribbon.home.Delete = 'DELETE';
GC.Spread.Sheets.Designer.setResources(resources);
// Remove unnecessary context menu
if (config.contextMenu) {
const deleteMenu = [
commandNames.RichText, // RichText
commandNames.InsertComment, // InsertComment
commandNames.DefineName, // DefineName
commandNames.CellTag, // CellTag
commandNames.RowTag, // RowTag
commandNames.ContextMenuOutlineColumn, // ContextMenuOutlineColumn
commandNames.DesignerPasteFormulaFormatting, // DesignerPasteFormulaFormatting
];
for (let i = 0; i < config.contextMenu.length; i++) {
var item = config.contextMenu[i];
if (deleteMenu.includes(item)) {
config.contextMenu.splice(i, 1);
}
}
}
new GC.Spread.Sheets.Designer.Designer('ribbonHost', config);
}
<!doctype html>
<html style="height:100%;font-size:14px;">
<head>
<meta name="spreadjs culture" content="zh-cn" />
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<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.light.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-languagepackages/dist/gc.spread.calcengine.languagepackages.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-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-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="sample-tutorial">
<div id="ribbonHost"></div>
<div id="ss"></div>
</div>
</body>
</html>
.sample-tutorial {
position: relative;
height: 97vh;
overflow: hidden;
}
body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
#ribbonHost {
height: 100%;
}
.description {
margin: 10px;
width: 40%;
}
table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
td,
th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
th {
background-color: #dcdcdc;
}
tr:nth-child(even) {
background-color: #f5f5f5;
}