SpreadJS 파일 형식 기능을 사용하려면 관련 js 파일 링크를 Spread 링크 아래의 문서 head 섹션에 추가해야 합니다.
SpreadJS는 sjs 파일 형식의 열기와 저장을 지원합니다. 또한 xlsx, xlsm, xltm, xltx, ssjson, csv 파일 형식의 가져오기와 내보내기도 지원합니다.
예:
class GC.Spread.Sheets.Workbook
GC.Spread.Sheets.SaveOptions
GC.Spread.Sheets.OpenOptions
GC.Spread.Sheets.ImportOptions
GC.Spread.Sheets.ExportOptions
GC.Spread.Sheets.ExcelFileType
GC.Spread.Sheets.ImportXlsxOptions
GC.Spread.Sheets.ExportXlsxOptions
GC.Spread.Sheets.ImportCsvOptions
.Spread.Sheets.ExportCsvOptions
GC.Spread.Sheets.ImportSSJsonOptions
GC.Spread.Sheets.ExportSSJsonOptions
import * as React from 'react';
import { createRoot } from 'react-dom/client';
import './styles.css';
import { AppFunc } from './app-func';
import { App } from './app-class';
// 1. Functional Component sample
createRoot(document.getElementById('app')).render(<AppFunc />);
// 2. Class Component sample
// createRoot(document.getElementById('app')).render(<App />);
import * as React from 'react';
import GC from '@mescius/spread-sheets';
import '@mescius/spread-sheets-print';
import '@mescius/spread-sheets-io';
import '@mescius/spread-sheets-shapes';
import '@mescius/spread-sheets-charts';
import '@mescius/spread-sheets-slicers';
import '@mescius/spread-sheets-pivot-addon';
import '@mescius/spread-sheets-reportsheet-addon';
import "@mescius/spread-sheets-tablesheet";
import "@mescius/spread-sheets-ganttsheet";
import '@mescius/spread-sheets-resources-ko';
GC.Spread.Common.CultureManager.culture('ko-kr');
import { SpreadSheets, Worksheet } from '@mescius/spread-sheets-react';
import './styles.css';
window.GC = GC;
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}
function getElementId(mode, fileType, propName) {
return mode + '-' + fileType + '-' + propName;
}
function formatOptionLabel(text) {
return text
.replace(/([a-z])([A-Z])/g, '$1 $2')
.replace(/([0-9])([A-Z][a-z])/g, '$1 $2')
.replace(/\b[a-z]/g, function (letter) {
return letter.toUpperCase();
});
}
function getFileType(file) {
if (!file) {
return;
}
var fileName = file.name;
var extensionName = fileName.substring(fileName.lastIndexOf(".") + 1);
if (extensionName === 'sjs') {
return FileType.SJS;
} else if (extensionName === 'xlsx' || extensionName === 'xlsm' || extensionName === 'xltm' || extensionName === 'xltx') {
return FileType.Excel;
} else if (extensionName === 'ssjson' || extensionName === 'json') {
return FileType.SSJson;
} else if (extensionName === 'csv') {
return FileType.Csv;
}
}
function mapExportFileType(fileType) {
if (fileType === FileType.SSJson) {
return GC.Spread.Sheets.FileType.ssjson;
} else if (fileType === FileType.Csv) {
return GC.Spread.Sheets.FileType.csv;
}
return GC.Spread.Sheets.FileType.excel;
}
function _getElementById(id) {
return document.getElementById(id);
}
var defaultOpenOptions = [
{ propName: "openMode", type: "select", displayText: "OpenMode", options: [{ name: 'normal', value: 0 }, { name: 'lazy', value: 1 }, { name: 'incremental', value: 2 }], default: 0 },
{ propName: "includeStyles", type: "boolean", default: true },
{ propName: "includeFormulas", type: "boolean", default: true },
{ propName: "fullRecalc", type: "boolean", default: false },
{ propName: "dynamicReferences", type: "boolean", default: true },
{ propName: "incrementalCalculation", type: "boolean", default: false },
{ propName: "includeUnusedStyles", type: "boolean", default: true },
];
var importXlsxOptions = [
{ propName: "openMode", type: "select", displayText: "OpenMode", options: [{ name: 'normal', value: 0 }, { name: 'lazy', value: 1 }, { name: 'incremental', value: 2 }], default: 0 },
{ propName: "includeStyles", type: "boolean", default: true },
{ propName: "includeFormulas", type: "boolean", default: true },
{ propName: "frozenColumnsAsRowHeaders", type: "boolean", default: false },
{ propName: "frozenRowsAsColumnHeaders", type: "boolean", default: false },
{ propName: "fullRecalc", type: "boolean", default: false },
{ propName: "dynamicReferences", type: "boolean", default: true },
{ propName: "incrementalCalculation", type: "boolean", default: false },
{ propName: "includeUnusedStyles", type: "boolean", default: true },
{ propName: "convertSheetTableToDataTable", type: "boolean", default: false },
];
var importSSJsonOptions = [
{ propName: "includeStyles", type: "boolean", default: true },
{ propName: "includeFormulas", type: "boolean", default: true },
{ propName: "frozenColumnsAsRowHeaders", type: "boolean", default: false },
{ propName: "frozenRowsAsColumnHeaders", type: "boolean", default: false },
{ propName: "fullRecalc", type: "boolean", default: false },
{ propName: "incrementalLoading", type: "boolean", default: false }
];
var importCsvOptions = [
{ propName: "encoding", type: "string", default: "UTF-8" },
{ propName: "rowDelimiter", type: "string", default: "\r\n" },
{ propName: "columnDelimiter", type: "string", default: "," }
];
var defaultSaveOptions = [
{ propName: "includeBindingSource", type: "boolean", default: false },
{ propName: "includeStyles", type: "boolean", default: true },
{ propName: "includeFormulas", type: "boolean", default: true },
{ propName: "saveAsView", type: "boolean", default: false },
{ propName: "includeAutoMergedCells", type: "boolean", default: false },
{ propName: "includeCalcModelCache", type: "boolean", default: false },
{ propName: "saveR1C1Formula", type: "boolean", default: false },
{ propName: "includeUnusedNames", type: "boolean", default: true },
{ propName: "includeEmptyRegionCells", type: "boolean", default: true },
];
var exportXlsxOptions = [
{ propName: "includeBindingSource", type: "boolean", default: false },
{ propName: "includeStyles", type: "boolean", default: true },
{ propName: "includeFormulas", type: "boolean", default: true },
{ propName: "saveAsView", type: "boolean", default: false },
{ propName: "rowHeadersAsFrozenColumns", type: "boolean", default: false },
{ propName: "columnHeadersAsFrozenRows", type: "boolean", default: false },
{ propName: "includeAutoMergedCells", type: "boolean", default: false },
{ propName: "includeUnusedNames", type: "boolean", default: true },
{ propName: "includeEmptyRegionCells", type: "boolean", default: true },
{ propName: "losslessEditing", type: "boolean", default: true },
];
var exportSSJsonOptions = [
{ propName: "includeBindingSource", type: "boolean", default: false },
{ propName: "includeStyles", type: "boolean", default: true },
{ propName: "includeFormulas", type: "boolean", default: true },
{ propName: "saveAsView", type: "boolean", default: false },
{ propName: "rowHeadersAsFrozenColumns", type: "boolean", default: false },
{ propName: "columnHeadersAsFrozenRows", type: "boolean", default: false },
{ propName: "includeAutoMergedCells", type: "boolean", default: false },
];
var exportCsvOptions = [
{ propName: "encoding", type: "string", default: "UTF-8" },
{ propName: "rowDelimiter", type: "string", default: "\r\n" },
{ propName: "columnDelimiter", type: "string", default: "," },
{ propName: "sheetIndex", type: "number", default: 0 },
{ propName: "row", type: "number", default: 0 },
{ propName: "column", type: "number", default: 0 },
{ propName: "rowCount", type: "number", default: 200 },
{ propName: "columnCount", type: "number", default: 20 },
];
var FileType = {
SJS: 'sjs',
Excel: 'xlsx',
SSJson: 'ssjson',
Csv: 'csv',
}
const ExcelFileType = {
xlsx: 'XLSX',
xlsm: 'XLSM',
xltm: 'XLTM',
xltx: 'XLTX',
}
export function AppFunc() {
const [spread, setSpread] = React.useState(null);
const [selectedFile, setSelectedFile] = React.useState(null);
const [openFileType, setOpenFileType] = React.useState('');
const [saveFileType, setSaveFileType] = React.useState(FileType.SJS);
const [excelFileType, setExcelFileType] = React.useState(ExcelFileType.xlsx);
const [openOptions, setOpenOptions] = React.useState({
sjs: {},
ssjson: {},
xlsx: {},
csv: {},
});
const [saveOptions, setSaveOptions] = React.useState({
sjs: {},
ssjson: {},
xlsx: {},
csv: {},
});
function initSpread(spread) {
setSpread(spread);
//init Status Bar
var statusBar = new GC.Spread.Sheets.StatusBar.StatusBar(document.getElementById('statusBar'));
statusBar.bind(spread);
}
function open() {
var file = selectedFile;
if (!file) {
return;
}
var fileType = getFileType(file);
var options = deepClone(openOptions[fileType]);
if (fileType === FileType.SJS) {
spread.open(file, function () { }, function () { }, options);
} else {
spread.import(file, function () { }, function () { }, options);
}
}
function save() {
var fileType = saveFileType;
var fileName = 'export.' + (fileType === FileType.Excel ? excelFileType.toLowerCase() : fileType);
var options = deepClone(saveOptions[fileType]);
if (fileType === FileType.SJS) {
spread.save(function (blob) { saveAs(blob, fileName); }, function () { }, options);
} else {
if (fileType === FileType.Csv) {
var { sheetIndex, row, rowCount, column, columnCount } = options;
options.range = {
sheetIndex: sheetIndex,
row: row,
rowCount: rowCount,
column: column,
columnCount: columnCount,
};
}
options.fileType = mapExportFileType(fileType);
spread.export(function (blob) { saveAs(blob, fileName); }, function () { }, options);
}
}
function onSelectedFileChange(e) {
let selectedFile = e.target.files[0];
let openFileType = getFileType(selectedFile);
setSelectedFile(selectedFile);
setOpenFileType(openFileType)
}
function onSaveFileTypeChange(e) {
let saveFileType = e.target.value;
setSaveFileType(saveFileType);
}
const onExcelFileTypeChange = (e) => {
const newExcelFileType = e.target.value;
setExcelFileType(newExcelFileType);
saveOptions.xlsx['excelFileType'] = newExcelFileType;
setSaveOptions(saveOptions);
}
function onPropChange(mode, fileType, prop, e) {
let element = e.target;
var value;
if (prop.type === 'boolean') {
value = element.checked;
} else if (prop.type === 'number') {
value = +element.value;
} else if (prop.type === 'string') {
value = element.value;
} else if (prop.type === 'select') {
value = +element.value;
}
if (mode === 'open') {
openOptions[fileType][prop.propName] = value;
setOpenOptions(openOptions);
} else if (mode === 'save') {
saveOptions[fileType][prop.propName] = value;
setSaveOptions(saveOptions);
}
}
function createOptions(options, fileType, mode) {
let selectFileType = mode === 'open' ? openFileType : saveFileType;
let display = selectFileType === fileType ? '' : 'none';
return <div className={fileType} style={{ display }}>
{options.map((prop) => createProp(mode, fileType, prop))}
</div>;
}
function createProp(mode, fileType, prop) {
let id = getElementId(mode, fileType, prop.propName);
if (prop.type === 'select') {
return <item className='item'>
<label for={id}>{formatOptionLabel(prop.displayText || prop.propName)}</label>
<select id={id} defaultValue={prop.default} onChange={(e) => onPropChange(mode, fileType, prop, e)}>
{prop.options.map((p) => <option value={p.value}>{p.name}</option>)}
</select>
</item>
} else if (prop.type === 'boolean') {
return <item className='item'>
<input id={id} type='checkbox' defaultChecked={prop.default} onChange={(e) => onPropChange(mode, fileType, prop, e)}></input>
<label for={id}>{formatOptionLabel(prop.displayText || prop.propName)}</label>
</item>
} else if (prop.type === 'number') {
return <item className='item'>
<label for={id}>{formatOptionLabel(prop.displayText || prop.propName)}</label>
<input id={id} type='number' defaultValue={prop.default} onChange={(e) => onPropChange(mode, fileType, prop, e)}></input>
</item>
} else {
return <item className='item'>
<label for={id}>{formatOptionLabel(prop.displayText || prop.propName)}</label>
<input id={id} type='text' defaultValue={prop.default} onChange={(e) => onPropChange(mode, fileType, prop, e)}></input>
</item>
}
}
return <div class="sample-tutorial">
<div class="sample-container">
<div class="sample-spreadsheets">
<SpreadSheets workbookInitialized={spread => initSpread(spread)}>
<Worksheet>
</Worksheet>
</SpreadSheets>
</div>
<div id="statusBar"></div>
</div>
<aside className="options-container" aria-label="SpreadJS file format settings">
<div class="panel-header">
<h1>File Format Settings</h1>
<p class="panel-description">Open and save SpreadJS file or Excel file with format-specific import and export options.</p>
</div>
<div className="option-row">
<section class="inputContainer control-section">
<h2>Open File</h2>
<div class="file-action-row">
<label for="selectedFile">Source File</label>
<input id="selectedFile" type="file" accept=".sjs, .xlsx, .xlsm, .xltm, .xltx, .ssjson, .json, .csv" onChange={onSelectedFileChange} />
<button class="settingButton" id="open" onClick={open}>Open</button>
</div>
<div class="open-options">
{[
createOptions(defaultOpenOptions, FileType.SJS, 'open'),
createOptions(importXlsxOptions, FileType.Excel, 'open'),
createOptions(importSSJsonOptions, FileType.SSJson, 'open'),
createOptions(importCsvOptions, FileType.Csv, 'open'),
]}
</div>
</section>
<section class="inputContainer control-section">
<h2>Save File</h2>
<div class="save-action-row">
<label for="saveFileType">File Type</label>
<select id="saveFileType" value={saveFileType} onChange={onSaveFileTypeChange}>
<option value="sjs">SJS</option>
<option value="xlsx">Excel</option>
<option value="ssjson">SSJSON</option>
<option value="csv">CSV</option>
</select>
<button class="settingButton" id="save" onClick={save}>Save</button>
</div>
{saveFileType === FileType.Excel && <div class="excelFileTypeContainer">
<label for="saveExcelFileType">Excel File Type</label>
<div>
<select id="saveExcelFileType" value={excelFileType} onChange={onExcelFileTypeChange}>
<option value="XLSX">Workbook (*.xlsx)</option>
<option value="XLSM">Macro-Enabled Workbook (*.xlsm)</option>
<option value="XLTM">Macro-Enabled Template (*.xltm)</option>
<option value="XLTX">Workbook Template (*.xltx)</option>
</select>
</div>
</div>}
<div class="save-options">
{[
createOptions(defaultSaveOptions, FileType.SJS, 'save'),
createOptions(exportXlsxOptions, FileType.Excel, 'save'),
createOptions(exportSSJsonOptions, FileType.SSJson, 'save'),
createOptions(exportCsvOptions, FileType.Csv, 'save'),
]}
</div>
</section>
</div>
</aside>
</div>;
}
import * as React from 'react';
import { createRoot } from 'react-dom/client';
import GC from '@mescius/spread-sheets';
import '@mescius/spread-sheets-print';
import '@mescius/spread-sheets-io';
import '@mescius/spread-sheets-shapes';
import '@mescius/spread-sheets-charts';
import '@mescius/spread-sheets-slicers';
import '@mescius/spread-sheets-pivot-addon';
import '@mescius/spread-sheets-reportsheet-addon';
import "@mescius/spread-sheets-tablesheet";
import "@mescius/spread-sheets-ganttsheet";
import '@mescius/spread-sheets-resources-ko';
GC.Spread.Common.CultureManager.culture('ko-kr');
import { SpreadSheets, Worksheet } from '@mescius/spread-sheets-react';
import './styles.css';
const Component = React.Component;
window.GC = GC;
var openOptions = [
{ propName: "openMode", type: "select", displayText: "OpenMode", options: [{name: 'normal', value: 0}, {name: 'lazy', value: 1}, {name: 'incremental', value: 2}], default: 0 },
{ propName: "includeStyles", type: "boolean", default: true },
{ propName: "includeFormulas", type: "boolean", default: true },
{ propName: "fullRecalc", type: "boolean", default: false },
{ propName: "dynamicReferences", type: "boolean", default: true },
{ propName: "incrementalCalculation", type: "boolean", default: false },
{ propName: "includeUnusedStyles", type: "boolean", default: true },
];
var importXlsxOptions = [
{ propName: "openMode", type: "select", displayText: "OpenMode", options: [{name: 'normal', value: 0}, {name: 'lazy', value: 1}, {name: 'incremental', value: 2}], default: 0 },
{ propName: "includeStyles", type: "boolean", default: true },
{ propName: "includeFormulas", type: "boolean", default: true },
{ propName: "frozenColumnsAsRowHeaders", type: "boolean", default: false },
{ propName: "frozenRowsAsColumnHeaders", type: "boolean", default: false },
{ propName: "fullRecalc", type: "boolean", default: false },
{ propName: "dynamicReferences", type: "boolean", default: true },
{ propName: "incrementalCalculation", type: "boolean", default: false },
{ propName: "includeUnusedStyles", type: "boolean", default: true },
{ propName: "convertSheetTableToDataTable", type: "boolean", default: false },
];
var importSSJsonOptions = [
{ propName: "includeStyles", type: "boolean", default: true },
{ propName: "includeFormulas", type: "boolean", default: true },
{ propName: "frozenColumnsAsRowHeaders", type: "boolean", default: false },
{ propName: "frozenRowsAsColumnHeaders", type: "boolean", default: false },
{ propName: "fullRecalc", type: "boolean", default: false },
{ propName: "incrementalLoading", type: "boolean", default: false }
];
var importCsvOptions = [
{ propName: "encoding", type: "string", default: "UTF-8" },
{ propName: "rowDelimiter", type: "string", default: "\r\n" },
{ propName: "columnDelimiter", type: "string", default: "," }
];
var saveOptions = [
{ propName: "includeBindingSource", type: "boolean", default: false },
{ propName: "includeStyles", type: "boolean", default: true },
{ propName: "includeFormulas", type: "boolean", default: true },
{ propName: "saveAsView", type: "boolean", default: false },
{ propName: "includeAutoMergedCells", type: "boolean", default: false },
{ propName: "includeCalcModelCache", type: "boolean", default: false },
{ propName: "saveR1C1Formula", type: "boolean", default: false },
{ propName: "includeUnusedNames", type: "boolean", default: true },
{ propName: "includeEmptyRegionCells", type: "boolean", default: true },
];
var exportXlsxOptions = [
{ propName: "includeBindingSource", type: "boolean", default: false },
{ propName: "includeStyles", type: "boolean", default: true },
{ propName: "includeFormulas", type: "boolean", default: true },
{ propName: "saveAsView", type: "boolean", default: false },
{ propName: "rowHeadersAsFrozenColumns", type: "boolean", default: false },
{ propName: "columnHeadersAsFrozenRows", type: "boolean", default: false },
{ propName: "includeAutoMergedCells", type: "boolean", default: false },
{ propName: "includeUnusedNames", type: "boolean", default: true },
{ propName: "includeEmptyRegionCells", type: "boolean", default: true },
{ propName: "losslessEditing", type: "boolean", default: true },
];
var exportSSJsonOptions = [
{ propName: "includeBindingSource", type: "boolean", default: false },
{ propName: "includeStyles", type: "boolean", default: true },
{ propName: "includeFormulas", type: "boolean", default: true },
{ propName: "saveAsView", type: "boolean", default: false },
{ propName: "rowHeadersAsFrozenColumns", type: "boolean", default: false },
{ propName: "columnHeadersAsFrozenRows", type: "boolean", default: false },
{ propName: "includeAutoMergedCells", type: "boolean", default: false },
];
var exportCsvOptions = [
{ propName: "encoding", type: "string", default: "UTF-8" },
{ propName: "rowDelimiter", type: "string", default: "\r\n" },
{ propName: "columnDelimiter", type: "string", default: "," },
{ propName: "sheetIndex", type: "number", default: 0 },
{ propName: "row", type: "number", default: 0 },
{ propName: "column", type: "number", default: 0 },
{ propName: "rowCount", type: "number", default: 200 },
{ propName: "columnCount", type: "number", default: 20 },
];
var FileType = {
SJS: 'sjs',
Excel: 'xlsx',
SSJson: 'ssjson',
Csv: 'csv',
}
const ExcelFileType = {
xlsx : 'XLSX',
xlsm : 'XLSM',
xltm : 'XLTM',
xltx : 'XLTX',
}
function deepClone (obj) {
return JSON.parse(JSON.stringify(obj));
}
function getElementId (mode, fileType, propName) {
return mode + '-' + fileType + '-' + propName;
}
function formatOptionLabel(text) {
return text
.replace(/([a-z])([A-Z])/g, '$1 $2')
.replace(/([0-9])([A-Z][a-z])/g, '$1 $2')
.replace(/\b[a-z]/g, function (letter) {
return letter.toUpperCase();
});
}
function getFileType (file) {
if (!file) {
return;
}
var fileName = file.name;
var extensionName = fileName.substring(fileName.lastIndexOf(".") + 1);
if (extensionName === 'sjs') {
return FileType.SJS;
} else if (extensionName === 'xlsx' || extensionName === 'xlsm' || extensionName === 'xltm' || extensionName === 'xltx') {
return FileType.Excel;
} else if (extensionName === 'ssjson' || extensionName === 'json') {
return FileType.SSJson;
} else if (extensionName === 'csv') {
return FileType.Csv;
}
}
function mapExportFileType (fileType) {
if (fileType === FileType.SSJson) {
return GC.Spread.Sheets.FileType.ssjson;
} else if (fileType === FileType.Csv) {
return GC.Spread.Sheets.FileType.csv;
}
return GC.Spread.Sheets.FileType.excel;
}
function _getElementById(id) {
return document.getElementById(id);
}
export class App extends Component {
constructor(props) {
super(props);
this.spread = null;
this.state = {
selectedFile: null,
openFileType: '',
saveFileType: FileType.SJS,
excelFileType: ExcelFileType.xlsx,
openOptions: {
sjs: {},
ssjson: {},
xlsx: {},
csv: {},
},
saveOptions: {
sjs: {},
ssjson: {},
xlsx: {},
csv: {},
}
};
this.open = this.open.bind(this);
this.save = this.save.bind(this);
this.onSelectedFileChange = this.onSelectedFileChange.bind(this);
this.onSaveFileTypeChange = this.onSaveFileTypeChange.bind(this);
this.onExcelFileTypeChange = this.onExcelFileTypeChange.bind(this);
this.onPropChange = this.onPropChange.bind(this);
}
render() {
return <div class="sample-tutorial">
<div class="sample-container">
<div class="sample-spreadsheets">
<SpreadSheets workbookInitialized={spread => this.initSpread(spread)}>
<Worksheet>
</Worksheet>
</SpreadSheets>
</div>
<div id="statusBar"></div>
</div>
<aside className="options-container" aria-label="SpreadJS file format settings">
<div class="panel-header">
<h1>File Format Settings</h1>
<p class="panel-description">Open and save SpreadJS file or Excel file with format-specific import and export options.</p>
</div>
<div className="option-row">
<section class="inputContainer control-section">
<h2>Open File</h2>
<div class="file-action-row">
<label for="selectedFile">Source File</label>
<input id="selectedFile" type="file" accept=".sjs, .xlsx, .xlsm, .xltm, .xltx, .ssjson, .json, .csv" onChange={this.onSelectedFileChange} />
<button class="settingButton" id="open" onClick={this.open}>Open</button>
</div>
<div class="open-options">
{[
this.createOptions(openOptions, FileType.SJS, 'open'),
this.createOptions(importXlsxOptions, FileType.Excel, 'open'),
this.createOptions(importSSJsonOptions, FileType.SSJson, 'open'),
this.createOptions(importCsvOptions, FileType.Csv, 'open'),
]}
</div>
</section>
<section class="inputContainer control-section">
<h2>Save File</h2>
<div class="save-action-row">
<label for="saveFileType">File Type</label>
<select id="saveFileType" value={this.state.saveFileType} onChange={this.onSaveFileTypeChange}>
<option value="sjs">SJS</option>
<option value="xlsx">Excel</option>
<option value="ssjson">SSJSON</option>
<option value="csv">CSV</option>
</select>
<button class="settingButton" id="save" onClick={this.save}>Save</button>
</div>
{
this.state.saveFileType === FileType.Excel && <div class="excelFileTypeContainer">
<label for="saveExcelFileType">Excel File Type</label>
<div>
<select id="saveExcelFileType" value={this.state.excelFileType} onChange={this.onExcelFileTypeChange}>
<option value="XLSX">Workbook (*.xlsx)</option>
<option value="XLSM">Macro-Enabled Workbook (*.xlsm)</option>
<option value="XLTM">Macro-Enabled Template (*.xltm)</option>
<option value="XLTX">Workbook Template (*.xltx)</option>
</select>
</div>
</div>
}
<div class="save-options">
{[
this.createOptions(saveOptions, FileType.SJS, 'save'),
this.createOptions(exportXlsxOptions, FileType.Excel, 'save'),
this.createOptions(exportSSJsonOptions, FileType.SSJson, 'save'),
this.createOptions(exportCsvOptions, FileType.Csv, 'save'),
]}
</div>
</section>
</div>
</aside>
</div>;
}
initSpread(spread) {
this.spread = spread;
//init Status Bar
var statusBar = new GC.Spread.Sheets.StatusBar.StatusBar(document.getElementById('statusBar'));
statusBar.bind(spread);
}
open() {
var file = this.state.selectedFile;
if (!file) {
return;
}
var fileType = getFileType(file);
var options = deepClone(this.state.openOptions[fileType]);
if (fileType === FileType.SJS) {
this.spread.open(file, function() {}, function() {}, options);
} else {
this.spread.import(file, function() {}, function() {}, options);
}
}
save() {
var fileType = this.state.saveFileType;
var fileName = 'export.' + (fileType === FileType.Excel ? this.state.excelFileType.toLowerCase() : fileType);
var options = deepClone(this.state.saveOptions[fileType]);
if (fileType === FileType.SJS) {
this.spread.save(function(blob) { saveAs(blob, fileName); }, function() {}, options);
} else {
if (fileType === FileType.Csv) {
var { sheetIndex, row, rowCount, column, columnCount } = options;
options.range = {
sheetIndex: sheetIndex,
row: row,
rowCount: rowCount,
column: column,
columnCount: columnCount,
};
}
options.fileType = mapExportFileType(fileType);
this.spread.export(function(blob) { saveAs(blob, fileName); }, function() {}, options);
}
}
onSelectedFileChange(e) {
let selectedFile = e.target.files[0];
let openFileType = getFileType(selectedFile);
this.setState({ ...this.state, selectedFile, openFileType });
}
onSaveFileTypeChange(e) {
let saveFileType = e.target.value;
this.setState({ ...this.state, saveFileType });
}
onExcelFileTypeChange (e) {
const excelFileType = e.target.value;
let saveOptions = deepClone(this.state.saveOptions);
saveOptions.xlsx['excelFileType'] = excelFileType;
this.setState({ ...this.state, excelFileType, saveOptions});
}
onPropChange (mode, fileType, prop, e) {
let element = e.target;
var value;
if (prop.type === 'boolean') {
value = element.checked;
} else if (prop.type === 'number') {
value = +element.value;
} else if (prop.type === 'string') {
value = element.value;
} else if (prop.type === 'select') {
value = +element.value;
}
if (mode === 'open') {
let openOptions = deepClone(this.state.openOptions);
openOptions[fileType][prop.propName] = value;
this.setState({...this.state, openOptions});
} else if (mode === 'save') {
let saveOptions = deepClone(this.state.saveOptions);
saveOptions[fileType][prop.propName] = value;
this.setState({...this.state, saveOptions});
}
}
createOptions (options, fileType, mode) {
let selectFileType = mode === 'open' ? this.state.openFileType : this.state.saveFileType;
let display = selectFileType === fileType ? '' : 'none';
return <div className={fileType} style={{display}}>
{ options.map((prop) => this.createProp(mode, fileType, prop)) }
</div>;
}
createProp (mode, fileType, prop) {
let id = getElementId(mode, fileType, prop.propName);
if (prop.type === 'select') {
return <item className='item'>
<label for={id}>{formatOptionLabel(prop.displayText || prop.propName)}</label>
<select id={id} defaultValue={prop.default} onChange={(e) => this.onPropChange(mode, fileType, prop, e)}>
{ prop.options.map((p) => <option value={p.value}>{p.name}</option>) }
</select>
</item>
} else if (prop.type === 'boolean') {
return <item className='item'>
<input id={id} type='checkbox' defaultChecked={prop.default} onChange={(e) => this.onPropChange(mode, fileType, prop, e)}></input>
<label for={id}>{formatOptionLabel(prop.displayText || prop.propName)}</label>
</item>
} else if (prop.type === 'number') {
return <item className='item'>
<label for={id}>{formatOptionLabel(prop.displayText || prop.propName)}</label>
<input id={id} type='number' defaultValue={prop.default} onChange={(e) => this.onPropChange(mode, fileType, prop, e)}></input>
</item>
} else {
return <item className='item'>
<label for={id}>{formatOptionLabel(prop.displayText || prop.propName)}</label>
<input id={id} type='text' defaultValue={prop.default} onChange={(e) => this.onPropChange(mode, fileType, prop, e)}></input>
</item>
}
}
}
createRoot(document.getElementById('app')).render(<App />);
<!doctype html>
<html style="height:100%;font-size:14px;">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css" href="$DEMOROOT$/ko/react/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css">
<script src="$DEMOROOT$/spread/source/js/FileSaver.js" type="text/javascript"></script>
<!-- SystemJS -->
<script src="$DEMOROOT$/ko/react/node_modules/systemjs/dist/system.src.js"></script>
<script src="systemjs.config.js"></script>
<script>
System.import('$DEMOROOT$/ko/lib/react/license.js').then(function () {
System.import('./src/app');
});
</script>
</head>
<body>
<div id="app"></div>
</body>
</html>
html,
body {
height: 100%;
margin: 0;
}
body {
position: absolute;
inset: 0;
color: #1f2933;
background: #f7f8fa;
}
#app {
height: 100%;
}
.sample-tutorial {
display: flex;
height: 100%;
overflow: hidden;
}
.sample-container {
display: flex;
flex: 1 1 auto;
flex-direction: column;
min-width: 0;
height: 100%;
}
.sample-spreadsheets {
flex: 1 1 auto;
min-height: 0;
overflow: hidden;
}
#statusBar {
flex: 0 0 25px;
width: 100%;
}
.options-container {
flex: 0 0 320px;
width: 320px;
height: 100%;
padding: 18px 16px;
box-sizing: border-box;
overflow: auto;
overflow-x: hidden;
background: #ffffff;
border-left: 1px solid #e5e7eb;
}
.sample-options {
z-index: 1000;
}
.panel-header {
padding-bottom: 14px;
border-bottom: 1px solid #eef0f3;
}
.panel-header h1 {
margin: 0;
font-size: 18px;
font-weight: 650;
line-height: 1.25;
}
.panel-description {
margin: 8px 0 0;
color: #6b7280;
font-size: 13px;
line-height: 1.6;
}
.option-row {
display: grid;
}
.inputContainer {
box-sizing: border-box;
}
.control-section {
padding: 14px 0;
border-bottom: 1px solid #eef0f3;
}
.control-section:last-child {
border-bottom: 0;
}
.control-section h2 {
margin: 0 0 10px;
color: #374151;
font-size: 13px;
font-weight: 700;
line-height: 1.3;
}
.options-container label {
color: #374151;
font-size: 13px;
font-weight: 600;
line-height: 1.35;
}
.options-container select,
.options-container input[type="text"],
.options-container input[type="number"] {
width: 100%;
height: 30px;
padding: 0 8px;
box-sizing: border-box;
color: #111827;
font: inherit;
background: #ffffff;
border: 1px solid #d8dde5;
border-radius: 6px;
outline: none;
transition: border-color .15s ease, box-shadow .15s ease;
}
.options-container select:focus,
.options-container input[type="text"]:focus,
.options-container input[type="number"]:focus,
.options-container input[type="file"]:focus,
.options-container button:focus {
border-color: #2563eb;
box-shadow: 0 0 0 3px rgba(37, 99, 235, .12);
}
.options-container input[type="file"] {
display: block;
min-width: 0;
color: #374151;
font-size: 12px;
}
.options-container input[type="file"]::file-selector-button {
height: 28px;
margin-right: 8px;
padding: 0 10px;
color: #1f4f82;
font: inherit;
font-weight: 600;
cursor: pointer;
background: #ffffff;
border: 1px solid #9bb2cf;
border-radius: 4px;
}
.options-container button,
.options-container input[type="button"] {
min-height: 30px;
padding: 0 12px;
box-sizing: border-box;
color: #1f4f82;
font: inherit;
font-weight: 600;
cursor: pointer;
background: #ffffff;
border: 1px solid #9bb2cf;
border-radius: 4px;
transition: background-color .15s ease, border-color .15s ease;
}
.options-container button:hover,
.options-container input[type="button"]:hover {
background: #edf5ff;
border-color: #6f98c8;
}
.settingButton {
flex: 0 0 auto;
margin: 0;
}
.file-action-row,
.save-action-row {
display: grid;
grid-template-columns: auto minmax(0, 1fr) auto;
gap: 8px;
align-items: center;
min-width: 0;
}
.file-action-row {
margin-bottom: 8px;
}
.file-action-row label,
.save-action-row label {
white-space: nowrap;
}
.file-action-row input[type="file"] {
width: 100%;
max-width: 100%;
min-width: 0;
overflow: hidden;
text-overflow: clip;
}
.save-action-row {
margin-bottom: 10px;
}
.save-action-row select {
width: 100%;
min-width: 0;
}
#open,
#save {
min-width: 56px;
}
.open-options .item,
.save-options .item {
display: flex;
gap: 8px;
align-items: center;
min-height: 24px;
margin: 4px 0;
}
.open-options .item label,
.save-options .item label {
flex: 1 1 auto;
min-width: 0;
font-weight: 500;
overflow-wrap: anywhere;
}
.open-options .item select,
.save-options .item select,
.open-options .item input[type="text"],
.save-options .item input[type="text"],
.open-options .item input[type="number"],
.save-options .item input[type="number"] {
flex: 0 0 128px;
width: 128px;
height: 28px;
}
.open-options .item input[type="checkbox"],
.save-options .item input[type="checkbox"] {
width: 16px;
height: 16px;
margin: 0;
accent-color: #2563eb;
flex: 0 0 auto;
}
.excelFileTypeContainer {
margin-bottom: 10px;
}
#saveExcelFileType {
margin: 8px 0 0;
}
@media (max-width: 760px) {
.sample-tutorial {
flex-direction: column;
}
.sample-container {
flex: 1 1 55%;
min-height: 55%;
}
.options-container {
flex: 0 0 45%;
width: 100%;
height: 45%;
border-top: 1px solid #e5e7eb;
border-left: 0;
}
}
(function (global) {
System.config({
transpiler: 'plugin-babel',
babelOptions: {
es2015: true,
react: true
},
meta: {
'*.css': { loader: 'css' }
},
paths: {
// paths serve as alias
'npm:': 'node_modules/',
'cdn:': 'node_modules/'
},
// map tells the System loader where to look for things
map: {
'@mescius/spread-sheets': 'cdn:@mescius/spread-sheets/index.js',
'@mescius/spread-sheets-resources-ko': 'cdn:@mescius/spread-sheets-resources-ko/index.js',
'@mescius/spread-sheets-print': 'cdn:@mescius/spread-sheets-print/index.js',
'@mescius/spread-sheets-react': 'cdn:@mescius/spread-sheets-react/index.js',
'@mescius/spread-sheets-io': 'cdn:@mescius/spread-sheets-io/index.js',
'@mescius/spread-sheets-charts': 'cdn:@mescius/spread-sheets-charts/index.js',
'@mescius/spread-sheets-shapes': 'cdn:@mescius/spread-sheets-shapes/index.js',
'@mescius/spread-sheets-slicers': 'cdn:@mescius/spread-sheets-slicers/index.js',
'@mescius/spread-sheets-pivot-addon': 'cdn:@mescius/spread-sheets-pivot-addon/index.js',
'@mescius/spread-sheets-reportsheet-addon': 'cdn:@mescius/spread-sheets-reportsheet-addon/index.js',
'@mescius/spread-sheets-tablesheet': 'cdn:@mescius/spread-sheets-tablesheet/index.js',
'@mescius/spread-sheets-ganttsheet': 'cdn:@mescius/spread-sheets-ganttsheet/index.js',
'@grapecity/jsob-test-dependency-package/react-components': 'npm:@grapecity/jsob-test-dependency-package/react-components/index.js',
'react': 'npm:react/cjs/react.production.js',
'react-dom': 'npm:react-dom/cjs/react-dom.production.js',
'react-dom/client': 'npm:react-dom/cjs/react-dom-client.production.js',
'scheduler': 'npm:scheduler/cjs/scheduler.production.js',
'css': 'npm:systemjs-plugin-css/css.js',
'plugin-babel': 'npm:systemjs-plugin-babel/plugin-babel.js',
'systemjs-babel-build':'npm:systemjs-plugin-babel/systemjs-babel-browser.js'
},
// packages tells the System loader how to load when no filename and/or no extension
packages: {
src: {
defaultExtension: 'jsx'
},
"node_modules": {
defaultExtension: 'js'
},
}
});
})(this);