IO

GanttSheet supports importing and exporting different kinds of file types, and it also supports printing and exporting to pdf.

Required Dependency If you want to support the IO feature (except json serialization/deserialization) you need to import the modules: TableSheet: spread-sheets-tablesheet GanttSheet: spread-sheets-ganttsheet SJS IO: spread-sheets-io Print: spread-sheets-print PDF: spread-sheets-pdf Export to Excel If you want to export the gantt data to Excel, you need to make sure the serialization option is includeBindingSource: true. Note: The gantt chart column will be exported as a picture in the Excel file.
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 />);
/*REPLACE_MARKER*/ /*DO NOT DELETE THESE COMMENTS*/ import * as React from 'react'; import GC from '@mescius/spread-sheets'; import '@mescius/spread-sheets-print'; import '@mescius/spread-sheets-pdf'; import '@mescius/spread-sheets-io'; import "@mescius/spread-sheets-tablesheet"; import "@mescius/spread-sheets-ganttsheet"; import { SpreadSheets } from '@mescius/spread-sheets-react'; import './styles.css'; const FileType = { SJS: 'sjs', Excel: 'xlsx', SSJson: 'ssjson' }; const openOptions = { openMode: GC.Spread.Sheets.OpenMode.normal, fullRecalc: true }; let spread = null; let myTable = null; export function AppFunc() { const initSpread=(workbook)=> { spread = workbook; spread.suspendPaint(); spread.clearSheets(); initDataSource(spread); initGanttSheet(spread); spread.resumePaint(); initSplitView(spread); } const initDataSource=(spread)=> { var tableName = "Gantt_Id"; var baseApiUrl = getBaseApiUrl(); var apiUrl = baseApiUrl + "/" + tableName; var dataManager = spread.dataManager(); myTable = dataManager.addTable("myTable", { batch: true, remote: { read: { url: apiUrl } }, schema: { hierarchy: { type: "Parent", column: "parentId" }, columns: { id: { isPrimaryKey: true }, taskNumber: { dataType: "rowOrder" } } } }); } const initGanttSheet=(spread)=> { var ganttSheet = spread.addSheetTab(0, "GanttSheet", GC.Spread.Sheets.SheetType.ganttSheet); var view = myTable.addView("ganttView", [ { value: "taskNumber", caption: "NO.", width: 60 }, { value: "name", caption: "Task Name", width: 200 }, { value: "duration", caption: "Duration", width: 90 }, { value: "predecessors", caption: "Predecessors", width: 120, visible: false } ]); view.fetch().then(function () { ganttSheet.bindGanttView(view); }); } const uploadFile=() =>{ var fileInput = document.getElementById("file-input"); fileInput.click(); } const openFile=(e) =>{ var fileNameItem = document.getElementById("file-name"); var fileInput = document.getElementById("file-input"); fileNameItem.value = 'Loading file...'; var file = fileInput.files[0]; if (!file) { alert("Upload a file first."); return; } var fileType = getFileType(file); var fileName = file.name; if (fileType === FileType.SJS) { spread.open(file, function () { fileNameItem.value = fileName; fileInput.value = ''; }, function () { }, openOptions); } else { spread.import(file, function () { fileNameItem.value = fileName; fileInput.value = ''; }, function () { }, openOptions); } } const exportFile=(fileType)=> { var fileName = 'export.' + fileType; var options = getExportOptions(fileType); if (fileType === FileType.SJS) { spread.save(function (blob) { saveAs(blob, fileName); }, function () { }, options); } else { spread.export(function (blob) { saveAs(blob, fileName); }, function () { }, options); } } const printSpread=() =>{ spread.print(); } const savePDF=()=> { spread.savePDF( function (blob) { saveAs(blob, 'download.pdf'); }, function () { } ); } return ( <div id="split-view" class="sample-tutorial"> <div class="sample-spreadsheets split-content"> <SpreadSheets workbookInitialized={spread => initSpread(spread)}></SpreadSheets> </div> <div class="options-container split-panel"> <div class="option-block"> <input id="file-input" type="file" name="files[]" accept=".xlsx, .ssjson, .json, .sjs, .zip, .xlsm" class="hide" onChange={() => { openFile() }} /> <div class="option-row input-box"> <label for="file-name">File Name</label> <input type="text" id="file-name" value="" disabled /> </div> <div class="option-row"> <input type="button" id="open-file" class="option-button" value="Open File" onClick={() => { uploadFile() }} /> <div class="option-info">File Type: *.ssjson, *.sjs</div> </div> </div> <div class="option-block"> <div class="option-row"> <input type="button" id="export-to-json" class="option-button" value="Export to JSON" onClick={() => { exportFile('ssjson') }} /> </div> <div class="option-row"> <input type="button" id="export-to-sjs" class="option-button" value="Export to SJS" onClick={() => { exportFile('sjs') }} /> </div> <div class="option-row"> <input type="button" id="export-to-excel" class="option-button" value="Export to Excel" onClick={() => { exportFile('xlsx') }} /> </div> </div> <div class="option-block"> <div class="option-row"> <input type="button" id="print" class="option-button" value="Print" onClick={() => { printSpread() }} /> </div> <div class="option-row"> <input type="button" id="pdf" class="option-button" value="PDF" onClick={() => { savePDF() }} /> </div> </div> </div> </div> ); } 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') { return FileType.Excel; } else if (extensionName === 'ssjson' || extensionName === 'json') { return FileType.SSJson; } } function getExportOptions(fileType) { return { fileType: GC.Spread.Sheets.FileType[fileType], includeBindingSource: true, saveAsView: true }; } function initSplitView(spread) { var host = document.getElementById("split-view"); var content = host.getElementsByClassName("split-content")[0]; var panel = host.getElementsByClassName("split-panel")[0]; new SplitView({ host: host, content: content, panel: panel, refreshContent: function () { spread.refresh(); } }); } function getBaseApiUrl() { return window.location.href.match(/http.+spreadjs\/demos\//)[0] + 'server/api'; }
/*REPLACE_MARKER*/ /*DO NOT DELETE THESE COMMENTS*/ import * as React from 'react'; import GC from '@mescius/spread-sheets'; import '@mescius/spread-sheets-print'; import '@mescius/spread-sheets-pdf'; import '@mescius/spread-sheets-io'; import "@mescius/spread-sheets-tablesheet"; import "@mescius/spread-sheets-ganttsheet"; import { SpreadSheets } from '@mescius/spread-sheets-react'; import './styles.css'; const FileType = { SJS: 'sjs', Excel: 'xlsx', SSJson: 'ssjson' }; const openOptions = { openMode: GC.Spread.Sheets.OpenMode.normal, fullRecalc: true }; const Component = React.Component; export class App extends Component { constructor(props) { super(props); this.spread = null; } render() { return ( <div id="split-view" class="sample-tutorial"> <div class="sample-spreadsheets split-content"> <SpreadSheets workbookInitialized={spread => this.initSpread(spread)}></SpreadSheets> </div> {/* <input type="button" id="add-task" class="option-button" value="Add Task" onClick={ () => { this.addTask() } } /> */} <div class="options-container split-panel"> <div class="option-block"> <input id="file-input" type="file" name="files[]" accept=".xlsx, .ssjson, .json, .sjs, .zip, .xlsm" class="hide" onChange={() => { this.openFile() }} /> <div class="option-row input-box"> <label for="file-name">File Name</label> <input type="text" id="file-name" value="" disabled /> </div> <div class="option-row"> <input type="button" id="open-file" class="option-button" value="Open File" onClick={() => { this.uploadFile() }} /> <div class="option-info">File Type: *.ssjson, *.sjs</div> </div> </div> <div class="option-block"> <div class="option-row"> <input type="button" id="export-to-json" class="option-button" value="Export to JSON" onClick={() => { this.exportFile('ssjson') }} /> </div> <div class="option-row"> <input type="button" id="export-to-sjs" class="option-button" value="Export to SJS" onClick={() => { this.exportFile('sjs') }} /> </div> <div class="option-row"> <input type="button" id="export-to-excel" class="option-button" value="Export to Excel" onClick={() => { this.exportFile('xlsx') }} /> </div> </div> <div class="option-block"> <div class="option-row"> <input type="button" id="print" class="option-button" value="Print" onClick={() => { this.printSpread() }} /> </div> <div class="option-row"> <input type="button" id="pdf" class="option-button" value="PDF" onClick={() => { this.savePDF() }} /> </div> </div> </div> </div> ); } initSpread(spread) { this.spread = spread; spread.suspendPaint(); spread.clearSheets(); this.initDataSource(spread); this.initGanttSheet(spread); spread.resumePaint(); initSplitView(spread); } initDataSource(spread) { var tableName = "Gantt_Id"; var baseApiUrl = getBaseApiUrl(); var apiUrl = baseApiUrl + "/" + tableName; var dataManager = spread.dataManager(); var myTable = dataManager.addTable("myTable", { batch: true, remote: { read: { url: apiUrl } }, schema: { hierarchy: { type: "Parent", column: "parentId" }, columns: { id: { isPrimaryKey: true }, taskNumber: { dataType: "rowOrder" } } } }); this.myTable = myTable; } initGanttSheet(spread) { var ganttSheet = spread.addSheetTab(0, "GanttSheet", GC.Spread.Sheets.SheetType.ganttSheet); var view = this.myTable.addView("ganttView", [ { value: "taskNumber", caption: "NO.", width: 60 }, { value: "name", caption: "Task Name", width: 200 }, { value: "duration", caption: "Duration", width: 90 }, { value: "predecessors", caption: "Predecessors", width: 120, visible: false } ]); view.fetch().then(function () { ganttSheet.bindGanttView(view); }); } uploadFile() { var fileInput = document.getElementById("file-input"); fileInput.click(); } openFile(e) { var spread = this.spread; var fileNameItem = document.getElementById("file-name"); var fileInput = document.getElementById("file-input"); fileNameItem.value = 'Loading file...'; var file = fileInput.files[0]; if (!file) { alert("Upload a file first."); return; } var fileType = getFileType(file); var fileName = file.name; if (fileType === FileType.SJS) { spread.open(file, function () { fileNameItem.value = fileName; fileInput.value = ''; }, function () { }, openOptions); } else { spread.import(file, function () { fileNameItem.value = fileName; fileInput.value = ''; }, function () { }, openOptions); } } exportFile(fileType) { var spread = this.spread; var fileName = 'export.' + fileType; var options = getExportOptions(fileType); if (fileType === FileType.SJS) { spread.save(function (blob) { saveAs(blob, fileName); }, function () { }, options); } else { spread.export(function (blob) { saveAs(blob, fileName); }, function () { }, options); } } printSpread() { this.spread.print(); } savePDF() { this.spread.savePDF( function (blob) { saveAs(blob, 'download.pdf'); }, function () { } ); } } 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') { return FileType.Excel; } else if (extensionName === 'ssjson' || extensionName === 'json') { return FileType.SSJson; } } function getExportOptions(fileType) { return { fileType: GC.Spread.Sheets.FileType[fileType], includeBindingSource: true, saveAsView: true }; } function initSplitView(spread) { var host = document.getElementById("split-view"); var content = host.getElementsByClassName("split-content")[0]; var panel = host.getElementsByClassName("split-panel")[0]; new SplitView({ host: host, content: content, panel: panel, refreshContent: function () { spread.refresh(); } }); } function getBaseApiUrl() { return window.location.href.match(/http.+spreadjs\/demos\//)[0] + 'server/api'; }
<!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$/en/react/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/spread/source/splitView/splitView.css"> <!-- SystemJS --> <script src="$DEMOROOT$/en/react/node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <!-- plugins --> <script src="$DEMOROOT$/spread/source/splitView/SplitView.js"></script> <script src="$DEMOROOT$/spread/source/js/FileSaver.js" type="text/javascript"></script> <script> System.import('$DEMOROOT$/en/lib/react/license.js').then(function () { System.import('./src/app'); }); </script> </head> <body> <div id="app" style="height: 100%;"></div> </body> </html>
.options-container { float: right; width: 280px; padding: 12px; height: 100%; box-sizing: border-box; background: #fbfbfb; overflow: auto; box-shadow: inset 0px 0 4px 0 rgba(0,0,0,0.4); } .option-block { background: #fff; padding: 8px; margin: 12px 0; border-radius: 4px; border: 1px dashed #82bc00; box-shadow: 0px 0 6px 0 rgba(0,0,0,0.1); } .option-block.toggle { border: 1px dotted #f7a711; } .option-row { font-size: 14px; box-sizing: border-box; padding: 4px 0; } .option-title { font-weight: bold; color: #656565; } .option-info { font-size: 12px; color: #919191; margin-top: 6px; font-weight: normal; } .option-info.valid { color: #82bc00; } .option-info.toggle { color: #f7a711; } .option-button { width: 100%; padding: 0; line-height: 20px; background: #82bc00; color: #fff; transition: 0.3s; cursor: pointer; outline: none; border-radius: 4px; box-sizing: border-box; box-shadow: 0 1px 4px 0 rgba(0,0,0,0.3); border: none; } .option-button:hover { background: #82bc00; color: #fff; box-shadow: 0 3px 8px 0 rgba(0,0,0,0.4); } .option-checkbox { background: #fff; border: 1px dashed #f7a711; color: #f7a711; padding: 2px 4px; transition: 0.3s; box-sizing: border-box; cursor: pointer; } .option-checkbox.active { color: #fff; background: #f7a711; box-shadow: 0 1px 4px 0 rgba(0,0,0,0.3); border-radius: 4px; } .selection-box { position: relative; } .selection-box > select { text-align: left; width: 100%; height: 20px; padding: 0; line-height: 20px; background: transparent; border: none; border-bottom: 2px solid #656565; color: #656565; transition: 0.3s; cursor: pointer; outline: none; box-sizing: border-box; } .selection-box > select > option { background: white; } .selection-box > select:focus { border-bottom: 2px solid #82bc00; color: #82bc00; box-shadow: 0 2px 6px 0 rgba(0,0,0,0.3); } .selection-box > label { position: absolute; cursor: pointer; font-size: 12px; color: #fff; background: #656565; padding: 0 4px; right: 0; top: 6px; box-shadow: 0 1px 4px 0 rgba(0,0,0,0.3); } .input-box { position: relative; } .input-box > input[type=text] { width: 100%; background: transparent; border: none; color: #656565; border-bottom: 2px solid #656565; outline: none; box-sizing: border-box; transition: 0.3s; } .input-box > input[type=text]:focus { color: #82bc00; border-bottom: 2px solid #82bc00; } .input-box > label { cursor: pointer; position: absolute; right: 0; top: 5px; font-size: 12px; color: #fff; background: #656565; padding: 0 4px; box-shadow: 0 1px 4px 0 rgba(0,0,0,0.3); }
(function (global) { System.config({ transpiler: 'plugin-babel', babelOptions: { es2015: true, react: true }, meta: { '*.css': { loader: 'css' } }, paths: { // paths serve as alias 'npm:': 'node_modules/' }, // map tells the System loader where to look for things map: { '@mescius/spread-sheets': 'npm:@mescius/spread-sheets/index.js', '@mescius/spread-sheets-print': 'npm:@mescius/spread-sheets-print/index.js', '@mescius/spread-sheets-pdf': 'npm:@mescius/spread-sheets-pdf/index.js', '@mescius/spread-sheets-io': 'npm:@mescius/spread-sheets-io/index.js', '@mescius/spread-sheets-tablesheet': 'npm:@mescius/spread-sheets-tablesheet/index.js', '@mescius/spread-sheets-ganttsheet': 'npm:@mescius/spread-sheets-ganttsheet/index.js', '@mescius/spread-sheets-react': 'npm:@mescius/spread-sheets-react/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);