リボンコンテナに追加されるカスタマイズメニューの一覧は以下の通りになります。
項目
説明
日付設定
日付と設定したセルと連動し、日付の設定と変更ができます。
計算
電卓ボタンを押下すると、ポップアップで電卓が表示されます。計算結果はセルの値と連動しています。
シート保護
ワークブックあるいはワークシートを保護します。保護されたシートは編集することができません。
保護解除
保護されたワークシートやワークブックの保護を解除し、編集可能に設定します。
進捗設定
「処理済み」をチェックした場合、選択行の背景色がグレーに設定されます。
高評価/低評価ボタン
ボタンが押下されるとアラートが表示されます。
ステータスバー
メールアドレスをクリックすると、メーラーが起動します。宛先と本文が設定済みです。
コンテキストメニュー
コンテキストメニューに追加される「デフォルトスタイルの設定」をクリックするとセル選択ダイアログが表示されます。選択されたセル範囲の背景色が水色、フォント色が赤色に設定されます。また、ダイアログを開いてからのセル選択もできます。
<template>
<div class="sample-tutorial">
<gc-spread-sheets-designer :styleInfo="styleInfo" :config="config" @designerInitialized="initDesigner" />
</div>
</template>
<script setup>
import GC from "@mescius/spread-sheets";
import "@mescius/spread-sheets-resources-ja";
import { ref } from "vue";
import "@mescius/spread-sheets-print";
import "@mescius/spread-sheets-shapes";
import "@mescius/spread-sheets-slicers";
import "@mescius/spread-sheets-pivot-addon";
import "@mescius/spread-sheets-tablesheet";
import "@mescius/spread-sheets-designer-resources-ja";
import "@mescius/spread-sheets-designer";
import * as GC2 from '@mescius/inputman';
import {registerlic} from '$DEMOROOT$/spread/source/js/designer/react_vue/license.js'
registerlic(GC);
const spreadNS = GC.Spread.Sheets;
const InputMan = GC2.InputMan;
GC.Spread.Common.CultureManager.culture("ja-jp");
const styleInfo = {
height: '100%'
}
const spreadRef = ref();
/* コンポーネントのクラス構造を定義 */
const defineDatePickerComponent = () => {
let gcDateTime;
function DatePicker() {
GC.Spread.Sheets.Designer.AtomicComponentBase.call(this, ...arguments);
}
DatePicker.prototype = new GC.Spread.Sheets.Designer.AtomicComponentBase();
DatePicker.prototype.getTemplate = function () {
return `
<div class="container" style="margin-top: 30px;">
<input style="width:150px" id="gcDateTime" class ='form_date'>
</div>
`;
};
DatePicker.prototype.onMounted = function () {
// InputManJS日付ピッカーを定義する
gcDateTime = new InputMan.GcDateTime(document.getElementById("gcDateTime"), {
displayFormatPattern: "yyy年M月d日",
formatPattern: "yyyy/MM/dd",
autoDropDown: true,
});
gcDateTime.setValue(null);
let picker = gcDateTime.addDropDown(
InputMan.DropDownButtonAlignment.RightSide,
InputMan.DateDropDownType.Calendar
);
gcDateTime.setDropDownButtonVisible(false);
gcDateTime.onValueChanged((sender, eArgs) => {
this.raiseValueChanged();
});
};
DatePicker.prototype.onValueChanged = function (prevValue, nextValue, host) {
if (nextValue != null && typeof nextValue === "object") {
gcDateTime.setValue(nextValue);
} else {
gcDateTime.setValue(null);
}
};
DatePicker.prototype.updateValue = function () {
if (gcDateTime.getValue() != null) {
let value = gcDateTime.getValue().toLocaleDateString("ja-jp", {
year: "numeric",
month: "numeric",
day: "numeric",
});
return new Date(value);
}
};
return DatePicker;
};
/* コンポーネントのクラス構造を定義 */
const defineCalculatorComponent = () => {
let gcCalculator;
function Calculator() {
GC.Spread.Sheets.Designer.AtomicComponentBase.call(this, ...arguments);
}
Calculator.prototype = new GC.Spread.Sheets.Designer.AtomicComponentBase();
Calculator.prototype.getTemplate = function () {
return `
<div class="container" style="margin-top: 30px;">
<input style="width:150px" id="calculator">
</div>
`;
};
Calculator.prototype.onMounted = function () {
// InputManJSポップアップ電卓を定義する
gcCalculator = new InputMan.GcNumber(document.getElementById("calculator"), {
showCalculatorAsPopup: true,
calculatorButtonPosition: InputMan.DropDownButtonAlignment.LeftSide,
});
gcCalculator.onValueChanged((sender, eArgs) => {
this.raiseValueChanged();
});
gcCalculator.onFocusOut(function (sender, args) {
let dropdown = sender.getDropDownWindow();
if (dropdown && dropdown.isOpened()) {
setTimeout(function () {
spreadRef.value.focus(false);
sender.setFocus();
});
}
});
};
Calculator.prototype.onValueChanged = function (prevValue, nextValue, host) {
if (nextValue != null && typeof nextValue === "number") {
gcCalculator.value = nextValue;
} else {
gcCalculator.value = 0;
}
};
Calculator.prototype.updateValue = function () {
if (gcCalculator.value != null) {
return Number(gcCalculator.value);
}
};
return Calculator;
};
const initRibbon = () => {
let config = GC.Spread.Sheets.Designer.DefaultConfig;
// 既存タブを非表示
for (let i = 0; i < config.ribbon.length; i++) {
config.ribbon.shift();
}
// 操作タブを追加
let newTab = {
id: "operate",
text: "オリジナル",
buttonGroups: [],
};
// 新しいタブ追加
config.ribbon.unshift(newTab);
var newTab2 = {
id: 'aboutSample',
text: 'サンプルについて',
iconClass: "ribbon-button-item-text",
buttonGroups: [
{
commandGroup: {
children: [
{
type: "textBlock",
text: '本サンプルでは Bootstrap Icons を使用しています。\r\n\r\nCopyright (c) 2019-2023 The Bootstrap Authors',
}
]
}
}
]
};
config.ribbon.push(newTab2);
// リボンコンテナのボタンを追加
let reactionGood = {
label: "評価",
thumbnailClass: "評価",
commandGroup: {
children: [
{
commands: ["cmdReactionGood", "cmdReactionBad"],
},
],
},
};
// チェックボックスの追加
let progressCheckbox = {
label: "進捗設定",
thumbnailClass: "",
direction: "vertical",
commandGroup: {
children: [
{
direction: "vertical",
commands: ["cmdCompletionCheckbox"],
},
],
},
};
// ドロップダウンリストを追加
let protectDropdownList = {
label: "保護",
thumbnailClass: "シートの保護",
commandGroup: {
children: [
{
command: "cmdProtectDropdownList",
type: "dropdown",
children: ["cmdProtectSheet", "cmdProtectBook"],
},
{
command: "cmdUnProtect",
children: ["cmdUnProtect"],
},
],
},
};
// カスタムコンポーネント日付ピッカーを追加
let DatePicker = defineDatePickerComponent();
GC.Spread.Sheets.Designer.Designer.RegisterComponent("DatePicker", DatePicker);
// カスタムコンポーネント電卓を追加
let Calculator = defineCalculatorComponent();
GC.Spread.Sheets.Designer.Designer.RegisterComponent("Calculator", Calculator);
// カスタムコンポーネントを追加
let customComponent = {
label: "InputManJS コンポーネント",
commandGroup: {
children: [
{
commands: ["cmdDatePicker"],
},
{
type: "separator",
},
{
commands: ["cmdCalculator"],
},
],
},
};
// デフォルトスタイル設定メニュー
let setDefaultStyle = {
templateName: "setDefaultStyle ",
title: "設定ダイアログ",
content: [
{
type: "FlexContainer",
children: [
{
type: "TextBlock",
margin: "5px -4px",
text: "設定範囲を選択します",
},
{
type: "RangeSelect",
title: "範囲を選択します",
absoluteReference: true,
needSheetName: false,
margin: "5px -5px",
bindingPath: "range",
},
],
},
],
};
// configコマンド作成
config.commandMap = {
// 高評価ボタン
cmdReactionGood: {
title: "高評価",
text: "高評価",
iconClass: "cmdReactionGood",
bigButton: "true",
commandName: "cmdReactionGood",
execute: async () => {
alert("高評価!押しました。");
},
},
// 低評価ボタン
cmdReactionBad: {
title: "低評価",
text: "低評価",
iconClass: "cmdReactionBad",
bigButton: "true",
commandName: "cmdReactionBad",
execute: async () => {
alert("低評価!押しました。");
},
},
// 処理済みチェックボックス
cmdCompletionCheckbox: {
title: "処理済み",
text: "処理済み",
type: "checkbox",
commandName: "cmdCompletionCheckbox",
execute: async (context, propertyName) => {
let state = context.getData("stateCompletionCheckbox");
context.setData("stateCompletionCheckbox", !state);
let sheet = context.getWorkbook().getActiveSheet();
// 名前付きスタイルを設定
let rowStyle = new GC.Spread.Sheets.Style();
rowStyle.backColor = "#cccccc";
rowStyle.name = "rowStyle";
sheet.addNamedStyle(rowStyle);
if (!state) {
sheet.setStyle(
sheet.getActiveRowIndex(),
-1,
sheet.getNamedStyle("rowStyle"),
GC.Spread.Sheets.SheetArea.viewport
);
} else {
sheet.setStyle(sheet.getActiveRowIndex(), -1, null, GC.Spread.Sheets.SheetArea.viewport);
}
},
getState: (context) => {
let sheet = context.getWorkbook().getActiveSheet();
let row = sheet.getActiveRowIndex();
if (sheet.getStyleName(row, -1, GC.Spread.Sheets.SheetArea.viewport) === "rowStyle") {
context.setData("stateCompletionCheckbox", true);
} else {
context.setData("stateCompletionCheckbox", false);
}
return context.getData("stateCompletionCheckbox");
},
},
// カスタムコンポーネント(日付設定)
cmdDatePicker: {
title: "日付を設定する",
text: "日付を設定する",
commandName: "cmdDatePicker",
type: "DatePicker",
execute: async (context, propertyName, value) => {
let sheet = context.getWorkbook().getActiveSheet();
//tips: valueをチェックしないと、入力以外の部分をクリックすると値クリアされる
if (sheet && value) {
let row = sheet.getActiveRowIndex();
let col = sheet.getActiveColumnIndex();
sheet.setValue(row, col, value);
}
},
getState: (designer) => {
let spread = designer.getWorkbook();
let sheet = spread.getActiveSheet();
let row = sheet.getActiveRowIndex();
let col = sheet.getActiveColumnIndex();
let value = sheet.getValue(row, col);
return value;
},
},
// カスタムコンポーネント(電卓)
cmdCalculator: {
title: "計算",
text: "計算",
commandName: "cmdCalculator",
type: "Calculator",
execute: async (context, propertyName, value) => {
let sheet = context.getWorkbook().getActiveSheet();
if (sheet && value) {
let row = sheet.getActiveRowIndex();
let col = sheet.getActiveColumnIndex();
sheet.setValue(row, col, value);
}
},
getState: (designer) => {
let spread = designer.getWorkbook();
let sheet = spread.getActiveSheet();
let row = sheet.getActiveRowIndex();
let col = sheet.getActiveColumnIndex();
let value = sheet.getValue(row, col);
return value;
},
},
// 保護解除ボタン
cmdUnProtect: {
iconClass: "cmdUnProtect",
text: "保護解除",
bigButton: "true",
direction: '=IF(ribbonHeight>toolbarHeight, "vertical", "horizontal")',
commandName: "cmdUnProtect",
execute: async function (designer) {
let workbook = designer.getWorkbook();
for (let i = 0; i < workbook.getSheetCount(); i++) {
let sheet = workbook.getSheet(i);
sheet.options.isProtected = false;
}
alert("保護を解除しました");
},
},
// シートの保護
cmdProtectDropdownList: {
text: "シートの保護",
iconClass: "cmdProtectSheet",
commandName: "cmdProtectDropdownList",
bigButton: "true",
subCommands: ["cmdProtectSheet", "cmdProtectBook"],
},
cmdProtectSheet: {
iconClass: "cmdProtectSheets",
bigButton: "=AND(ribbonHeight>toolbarHeight,NOT(inDropdown))",
text: "ワークシートの保護",
direction: '=IF(ribbonHeight>toolbarHeight, "vertical", "horizontal")',
commandName: "cmdProtectSheet",
execute: async function (designer) {
let workbook = designer.getWorkbook();
let sheet = workbook.getActiveSheet();
sheet.options.isProtected = true;
alert("ワークシートを保護しました");
},
},
cmdProtectBook: {
iconClass: "cmdProtectBook",
text: "ワークブックの保護",
commandName: "cmdProtectBook",
execute: async function (designer) {
let workbook = designer.getWorkbook();
for (let i = 0; i < workbook.getSheetCount(); i++) {
let sheet = workbook.getSheet(i);
sheet.options.isProtected = true;
}
alert("ワークブックを保護しました");
},
},
// デフォルトスタイル設定ダイアログ
cmdDefaultStyleDialog: {
text: "デフォルトスタイルの設定",
commandName: "cmdDefaultStyleDialog",
// visibleContext:ClickRowHeader/ClickColHeader/ClickViewport
visibleContext: "ClickViewport",
execute: (context, propertyName) => {
let sheet = context.getWorkbook().getActiveSheet();
let dialogOption = {
range: GC.Spread.Sheets.CalcEngine.rangesToFormula(sheet.getSelections()),
};
GC.Spread.Sheets.Designer.showDialog(
"defaultStyleDialog",
dialogOption,
(result) => {
if (!result) {
return;
}
let selectedRange = GC.Spread.Sheets.CalcEngine.formulaToRanges(sheet, result.range);
if (
selectedRange[0] &&
selectedRange[0].ranges &&
selectedRange[0].ranges[0] instanceof GC.Spread.Sheets.Range
) {
selectedRange[0].ranges.forEach((element) => {
let style = new GC.Spread.Sheets.Style();
style.hAlign = GC.Spread.Sheets.HorizontalAlign.center;
style.backColor = "#ebf6f7";
style.foreColor = "red";
sheet
.getRange(element.row, element.col, element.rowCount, element.colCount)
.setStyle(style);
});
}
},
(error) => {
console.error(error);
}
);
},
},
};
// リアクションボタン追加
config.ribbon[0].buttonGroups.unshift(reactionGood);
// チェックボックス追加
config.ribbon[0].buttonGroups.unshift(progressCheckbox);
// ドロップダウンリスト追加
config.ribbon[0].buttonGroups.unshift(protectDropdownList);
// カスタムコンポーネント追加
config.ribbon[0].buttonGroups.unshift(customComponent);
// コンテキストメニューを追加
if (config && config.contextMenu) {
config.contextMenu.unshift("cmdDefaultStyleDialog");
}
GC.Spread.Sheets.Designer.registerTemplate("defaultStyleDialog", setDefaultStyle);
// リボンコンテナのローカライズのカスタマイズ
let resources = GC.Spread.Sheets.Designer.getResources();
resources.ribbon.home.home = "home!";
resources.ok = "確定!";
resources.cancel = "キャンセル!";
resources.formatDialog.title = "書式設定ダイアログ!";
resources.ribbon.home.clear = "クリア!";
resources.ribbon.home.paste = "ペースト";
GC.Spread.Sheets.Designer.setResources(resources);
return config;
};
const config = ref(initRibbon());
const initSheet = (spread) => {
spread.suspendPaint();
let sheet = spread.getActiveSheet();
let salesData = [
["種類", "製品名", "販売数(箱)", "売上(万円)", "利益(万円)", "販売日"],
["酒", "日本酒", 15, 290.4, 120.3],
["酒", "ワイン", 20, 549.3, 320.8],
["酒", "ビール", 150, 400.5, 210.5],
["酒", "焼酎", 21, 212.8, 60.4],
["飲料", "お茶", 100, 90.8, 10.4],
["飲料", "炭酸水", 90, 30.8, 9.5],
["飲料", "ジュース", 65, 103.5, 29.5],
];
sheet.setArray(0, 0, salesData);
sheet.setColumnWidth(0, 120);
sheet.setColumnWidth(1, 120);
sheet.setColumnWidth(2, 100);
sheet.setColumnWidth(3, 100);
sheet.setColumnWidth(4, 100);
sheet.setColumnWidth(5, 120);
sheet.setRowHeight(0, 30);
sheet.setValue(0, 6, "👈タイトルのスタイルはコンテキストメニューよりデフォルトスタイルで設定できます");
// コメント追加
sheet.comments.add(0, 5, "リボンコンテナの日付設定より簡単に設定できます");
sheet.comments.add(8, 3, "電卓を使って計算できます");
sheet.comments.add(8, 2, "電卓を使って計算できます");
spread.resumePaint();
setTimeout(initStatusBar, 1000);
};
const initStatusBar = () => {
// ステータスバー
let statusBar = spreadNS.StatusBar.findControl(document.getElementsByClassName("gc-statusBar"));
let StatusItem = GC.Spread.Sheets.StatusBar.StatusItem;
function SendMail(name, options) {
StatusItem.call(this, name, options);
}
SendMail.prototype = new StatusItem();
SendMail.prototype.onCreateItemView = function (container) {
let item = document.createElement("div");
item.innerText = this.value;
item.id = this.name;
container.appendChild(item);
container.addEventListener("click", function () {
let address = item.id == "SendMailSales" ? "sales@sample-spreadjs.com" : "support@sample-spreadjs.com";
let subject = "SpreadJSについてのお問い合わせ";
let body = "お問い合わせ";
location.href = "mailto:" + address + "?subject=" + subject + "&body=" + body;
});
};
let spanItem = new SendMail("SendMailSales", {
menuContent: "セールス",
value: "E-mail: sales@sample-spreadjs.com",
tipText: "sales",
});
let spanItem2 = new SendMail("SendMailSupport", {
menuContent: "サポート",
value: "E-mail: support@sample-spreadjs.com",
tipText: "サポート",
});
statusBar.add(spanItem);
statusBar.add(spanItem2);
}
const initDesigner = (designer) => {
spreadRef.value = designer.getWorkbook();
initSheet(spreadRef.value);
}
</script>
<style scoped>
.sample-tutorial {
position: relative;
height: 98vh;
overflow: hidden;
}
body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
#app {
height: 100%;
}
.description {
margin: 10px;
width: 40%;
}
.gcim-dropdown table {
font-family: arial, sans-serif;
border-collapse: collapse;
width: 100%;
}
.gcim-dropdown td,
th {
border: 1px solid #dddddd;
text-align: left;
padding: 8px;
}
.gcim-dropdown th {
background-color: #dcdcdc;
}
.gcim-dropdown tr:nth-child(even) {
background-color: #f5f5f5;
}
.cmdReactionGood {
background-image: url("icons/hand-thumbs-up.svg");
}
.cmdReactionBad {
background-image: url("icons/hand-thumbs-down.svg");
}
.cmdProtectSheet {
background-image: url("icons/lock.svg");
background-size: 35px 35px;
}
.cmdUnProtect {
background-image: url("icons/unlock.svg");
}
.cmdProtectSheets {
background-image: url("icons/file-earmark-spreadsheet.svg");
}
.cmdProtectBook {
background-image: url("icons/book.svg");
}
</style>
<!DOCTYPE html>
<html lang="en" style="height:100%;font-size:14px;">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>SpreadJS VUE</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css"
href="$DEMOROOT$/ja/vue3/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css">
<link rel="stylesheet" type="text/css" href="$DEMOROOT$/ja/vue3/node_modules/@mescius/spread-sheets-designer/styles/gc.spread.sheets.designer.min.css">
<link rel="stylesheet" type="text/css" href="$DEMOROOT$/ja/vue3/node_modules/@mescius/inputman/CSS/gc.inputman-js.css">
<script src="$DEMOROOT$/ja/vue3/node_modules/systemjs/dist/system.src.js"></script>
<script src="./systemjs.config.js"></script>
<script src="./compiler.js" type="module"></script>
<script>
var System = SystemJS;
System.import("./src/app.js");
System.import('$DEMOROOT$/ja/lib/vue3/license.js').then(() => {
System.import('$DEMOROOT$/spread/source/js/inputman/react_vue/license.js');
});
</script>
</head>
<body>
<div id="app"></div>
</body>
</html>
(function (global) {
SystemJS.config({
transpiler: 'plugin-babel',
babelOptions: {
es2015: true
},
paths: {
// paths serve as alias
'npm:': 'node_modules/'
},
packageConfigPaths: [
'./node_modules/*/package.json',
"./node_modules/@mescius/*/package.json",
"./node_modules/@grapecity/*/package.json",
"./node_modules/@babel/*/package.json",
"./node_modules/@vue/*/package.json"
],
map: {
'vue': "npm:vue/dist/vue.esm-browser.js",
'tiny-emitter': 'npm:tiny-emitter/index.js',
'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js',
"systemjs-babel-build": "npm:systemjs-plugin-babel/systemjs-babel-browser.js",
'@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js',
'@mescius/spread-sheets-resources-ja': 'npm:@mescius/spread-sheets-resources-ja/index.js',
'@mescius/spread-sheets-vue': 'npm:@mescius/spread-sheets-vue/index.js',
'@mescius/spread-excelio': 'npm:@mescius/spread-excelio/index.js',
'@mescius/spread-sheets-shapes': 'npm:@mescius/spread-sheets-shapes/index.js',
'@mescius/spread-sheets-charts': 'npm:@mescius/spread-sheets-charts/index.js',
'@mescius/spread-sheets-print': 'npm:@mescius/spread-sheets-print/index.js',
'@mescius/spread-sheets-barcode': 'npm:@mescius/spread-sheets-barcode/index.js',
'@mescius/spread-sheets-formula-panel': 'npm:@mescius/spread-sheets-formula-panel/index.js',
'@mescius/spread-sheets-pdf': 'npm:@mescius/spread-sheets-pdf/index.js',
'@mescius/spread-sheets-languagepackages': 'npm:@mescius/spread-sheets-languagepackages/index.js',
'@mescius/spread-sheets-pivot-addon': 'npm:@mescius/spread-sheets-pivot-addon/index.js',
'@mescius/spread-sheets-tablesheet': 'npm:@mescius/spread-sheets-tablesheet/index.js',
'@mescius/spread-sheets-io': 'npm:@mescius/spread-sheets-io/index.js',
'@mescius/spread-sheets-slicers': 'npm:@mescius/spread-sheets-slicers/index.js',
'@mescius/spread-sheets-designer': 'npm:@mescius/spread-sheets-designer/index.js',
'@mescius/spread-sheets-designer-resources-ja': 'npm:@mescius/spread-sheets-designer-resources-ja/index.js',
'@mescius/spread-sheets-designer-vue': 'npm:@mescius/spread-sheets-designer-vue/index.js',
'@grapecity/jsob-test-dependency-package/react-components': 'npm:@grapecity/jsob-test-dependency-package/react-components/index.js',
'@mescius/inputman': 'npm:@mescius/inputman/index.js',
},
meta: {
'*.css': { loader: 'systemjs-plugin-css' },
'*.vue': { loader: "../plugin-vue/index.js" }
}
});
})(this);