Workbook Viewer

This sample implements a simple Excel workbook viewer that loads xlsx file content and displays it on the page.

The sample creates a Workbook instance, then loads an xlsx file content to the workbook instance using the Workbook.load method. After that, it walks through the content of the current workbook sheet provided by WorkSheet class, and creates an HTML table that visualizes the content.

The sample also creates tabs that allow switching between workbook sheets. It is implemented using the BootstrapJS tab-like styling of the <li> elements with the applied ng-repeat directive that iterates through the Workbook.sheets collection.

import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import * as wjcCore from '@grapecity/wijmo'; import * as wjcXlsx from '@grapecity/wijmo.xlsx'; // document.readyState === 'complete' ? init() : window.onload = init; // function init() { let workbook; // document.querySelector('#importFile').addEventListener('change', () => { loadWorkbook(); }); // document.querySelector('#sheetNav').addEventListener('click', (e) => { e.preventDefault(); // let navEle = e.target.parentElement; let activeIndex = toggleNavActiveStatus(navEle); if (activeIndex !== -1) { drawSheet(activeIndex); } }); // function loadWorkbook() { let reader = new FileReader(); // reader.onload = (e) => { let tmp = new wjcXlsx.Workbook(); tmp.loadAsync(reader.result, (result) => { workbook = result; drawSheetNav(workbook.activeWorksheet || 0); drawSheet(workbook.activeWorksheet || 0); }); }; // let file = document.getElementById('importFile').files[0]; if (file) { reader.readAsDataURL(file); } } // function drawSheet(sheetIndex) { let drawRoot = document.getElementById('tableHost'); drawRoot.textContent = ''; drawWorksheet(workbook, sheetIndex, drawRoot, 200, 100); } // function drawSheetNav(activeIndex) { let contianer = document.querySelector('#sheetNav'); contianer.innerHTML = ''; let navItem = ''; for (let i = 0; i < workbook.sheets.length; i++) { let sheet = workbook.sheets[i]; navItem += `<li role="presentation" class="${i === activeIndex ? 'active' : ''}"><a href="#">${sheet.name}</a></li>`; } contianer.innerHTML = navItem; } // function drawWorksheet(workbook, sheetIndex, rootElement, maxRows, maxColumns) { //NOTES: //Empty cells' values are numeric NaN, format is "General" // //Excessive empty properties: //fill.color = undefined // // netFormat should return '' for ''. What is 'General'? // font.color should start with '#'? // Column/row styles are applied to each cell style, this is convenient, but Column/row style info should be kept, // for column/row level styling // formats conversion is incorrect - dates and virtually everything; netFormat - return array of formats? // ?row heights - see hello.xlsx if (!workbook || !workbook.sheets || sheetIndex < 0 || workbook.sheets.length == 0) { return; } // sheetIndex = Math.min(sheetIndex, workbook.sheets.length - 1); // if (maxRows == null) { maxRows = 200; } // if (maxColumns == null) { maxColumns = 100; } // // Namespace and XlsxConverter shortcuts. let sheet = workbook.sheets[sheetIndex], defaultRowHeight = 20, defaultColumnWidth = 60, tableEl = document.createElement('table'); // tableEl.border = '1'; tableEl.style.borderCollapse = 'collapse'; // let maxRowCells = 0; for (let r = 0; sheet.rows && r < sheet.rows.length; r++) { if (sheet.rows[r] && sheet.rows[r].cells) { maxRowCells = Math.max(maxRowCells, sheet.rows[r].cells.length); } } // // add columns let columnCount = 0; if (sheet.columns) { columnCount = sheet.columns.length; maxRowCells = Math.min(Math.max(maxRowCells, columnCount), maxColumns); for (let c = 0; c < maxRowCells; c++) { let col = c < columnCount ? sheet.columns[c] : null, colEl = document.createElement('col'); tableEl.appendChild(colEl); let colWidth = defaultColumnWidth + 'px'; if (col) { importStyle(colEl.style, col.style); if (col.autoWidth) { colWidth = ''; } else if (col.width != null) { colWidth = col.width + 'px'; } } colEl.style.width = colWidth; } } // // generate rows let rowCount = Math.min(maxRows, sheet.rows.length); for (let r = 0; sheet.rows && r < rowCount; r++) { let row = sheet.rows[r], rowEl = document.createElement('tr'); tableEl.appendChild(rowEl); if (row) { importStyle(rowEl.style, row.style); if (row.height != null) { rowEl.style.height = row.height + 'px'; } for (let c = 0; row.cells && c < row.cells.length; c++) { let cell = row.cells[c], cellEl = document.createElement('td'); rowEl.appendChild(cellEl); if (cell) { importStyle(cellEl.style, cell.style); let value = cell.value; if (!(value == null || value !== value)) { // TBD: check for NaN should be eliminated let netFormat = ''; if (cell.style && cell.style.format) { netFormat = wjcXlsx.Workbook.fromXlsxFormat(cell.style.format)[0]; } let fmtValue = netFormat ? wjcCore.Globalize.format(value, netFormat) : value; cellEl.innerHTML = wjcCore.escapeHtml(fmtValue); } if (cell.colSpan && cell.colSpan > 1) { cellEl.colSpan = cell.colSpan; c += cellEl.colSpan - 1; } } } } // // pad with empty cells let padCellsCount = maxRowCells - (row && row.cells ? row.cells.length : 0); for (let i = 0; i < padCellsCount; i++) { rowEl.appendChild(document.createElement('td')); } // if (!rowEl.style.height) { rowEl.style.height = defaultRowHeight + 'px'; } } // // do it at the end for performance rootElement.appendChild(tableEl); } // function importStyle(cssStyle, xlsxStyle) { if (!xlsxStyle) { return; } // if (xlsxStyle.fill) { if (xlsxStyle.fill.color) { cssStyle.backgroundColor = xlsxStyle.fill.color; } } // if (xlsxStyle.hAlign && xlsxStyle.hAlign != wjcXlsx.HAlign.Fill) { cssStyle.textAlign = wjcXlsx.HAlign[xlsxStyle.hAlign].toLowerCase(); } // let font = xlsxStyle.font; if (font) { if (font.family) { cssStyle.fontFamily = font.family; } if (font.bold) { cssStyle.fontWeight = 'bold'; } if (font.italic) { cssStyle.fontStyle = 'italic'; } if (font.size != null) { cssStyle.fontSize = font.size + 'px'; } if (font.underline) { cssStyle.textDecoration = 'underline'; } if (font.color) { cssStyle.color = font.color; } } } // function toggleNavActiveStatus(navEle) { let activeIndex = -1; let navEles = document.querySelectorAll('#sheetNav li'); for (let i = 0; i < navEles.length; i++) { let currentItem = navEles[i]; wjcCore.removeClass(currentItem, 'active'); if (currentItem === navEle) { wjcCore.addClass(currentItem, 'active'); activeIndex = i; } } return activeIndex; } } <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>GrapeCity Wijmo Workbook Viewer</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app'); </script> </head> <body> <div class="container-fluid"> <div class="row"> <input type="file" class="form-control" id="importFile" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel.sheet.macroEnabled.12" style="width:300px" /> </div> <!-- Sheet tabs --> <ul id="sheetNav" class="nav nav-tabs" style="margin-top:40px"> </ul> <!-- Current sheet view --> <div id="tableHost"></div> </div> </body> </html> import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; // import { Component, enableProdMode, NgModule } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; // import * as wjcCore from '@grapecity/wijmo'; import * as wjcXlsx from '@grapecity/wijmo.xlsx'; // @Component({ selector: 'app-component', templateUrl: 'src/app.component.html' }) export class AppComponent { workbook: wjcXlsx.Workbook; sheetIndex: number; // ngAfterViewInit() { document.getElementById('importFile').addEventListener('change', () => { this._loadWorkbook(); }); } // tabClicked(e: MouseEvent, index: number) { e.preventDefault(); this._drawSheet(index); } // private _loadWorkbook() { let reader = new FileReader(); // reader.onload = (e) => { let workbook = new wjcXlsx.Workbook(); workbook.loadAsync(<string>reader.result, (result: wjcXlsx.Workbook) => { this.workbook = result; this._drawSheet(this.workbook.activeWorksheet || 0); }); }; // let file = (<HTMLInputElement>document.getElementById('importFile')).files[0]; if (file) { reader.readAsDataURL(file); } } // private _drawSheet(sheetIndex: number) { let drawRoot = document.getElementById('tableHost'); drawRoot.textContent = ''; this.sheetIndex = sheetIndex; this._drawWorksheet(this.workbook, sheetIndex, drawRoot, 200, 100); } // private _drawWorksheet(workbook: wjcXlsx.IWorkbook, sheetIndex: number, rootElement: HTMLElement, maxRows: number, maxColumns: number) { //NOTES: //Empty cells' values are numeric NaN, format is "General" // //Excessive empty properties: //fill.color = undefined // // netFormat should return '' for ''. What is 'General'? // font.color should start with '#'? // Column/row styles are applied to each cell style, this is convenient, but Column/row style info should be kept, // for column/row level styling // formats conversion is incorrect - dates and virtually everything; netFormat - return array of formats? // ?row heights - see hello.xlsx if (!workbook || !workbook.sheets || sheetIndex < 0 || workbook.sheets.length == 0) { return; } // sheetIndex = Math.min(sheetIndex, workbook.sheets.length - 1); // if (maxRows == null) { maxRows = 200; } // if (maxColumns == null) { maxColumns = 100; } // // Namespace and XlsxConverter shortcuts. let sheet = workbook.sheets[sheetIndex], defaultRowHeight = 20, defaultColumnWidth = 60, tableEl = document.createElement('table'); // tableEl.border = '1'; tableEl.style.borderCollapse = 'collapse'; // let maxRowCells = 0; for (let r = 0; sheet.rows && r < sheet.rows.length; r++) { if (sheet.rows[r] && sheet.rows[r].cells) { maxRowCells = Math.max(maxRowCells, sheet.rows[r].cells.length); } } // // add columns let columnCount = 0; if (sheet.columns) { columnCount = sheet.columns.length; maxRowCells = Math.min(Math.max(maxRowCells, columnCount), maxColumns); for (let c = 0; c < maxRowCells; c++) { let col = c < columnCount ? sheet.columns[c] : null, colEl = document.createElement('col'); tableEl.appendChild(colEl); let colWidth = defaultColumnWidth + 'px'; if (col) { this._importStyle(colEl.style, col.style); if (col.autoWidth) { colWidth = ''; } else if (col.width != null) { colWidth = col.width + 'px'; } } colEl.style.width = colWidth; } } // // generate rows let rowCount = Math.min(maxRows, sheet.rows.length); for (let r = 0; sheet.rows && r < rowCount; r++) { let row = sheet.rows[r], rowEl = document.createElement('tr'); tableEl.appendChild(rowEl); if (row) { this._importStyle(rowEl.style, row.style); if (row.height != null) { rowEl.style.height = row.height + 'px'; } for (let c = 0; row.cells && c < row.cells.length; c++) { let cell = row.cells[c], cellEl = document.createElement('td'); rowEl.appendChild(cellEl); if (cell) { this._importStyle(cellEl.style, cell.style); let value = cell.value; if (!(value == null || value !== value)) { // TBD: check for NaN should be eliminated let netFormat = ''; if (cell.style && cell.style.format) { netFormat = wjcXlsx.Workbook.fromXlsxFormat(cell.style.format)[0]; } let fmtValue = netFormat ? wjcCore.Globalize.format(value, netFormat) : value; cellEl.innerHTML = wjcCore.escapeHtml(fmtValue); } if (cell.colSpan && cell.colSpan > 1) { cellEl.colSpan = cell.colSpan; c += cellEl.colSpan - 1; } } } } // pad with empty cells let padCellsCount = maxRowCells - (row && row.cells ? row.cells.length : 0); for (let i = 0; i < padCellsCount; i++) { rowEl.appendChild(document.createElement('td')); } // if (!rowEl.style.height) { rowEl.style.height = defaultRowHeight + 'px'; } } // // do it at the end for performance rootElement.appendChild(tableEl); } // private _importStyle(cssStyle: CSSStyleDeclaration, xlsxStyle: wjcXlsx.IWorkbookStyle) { if (!xlsxStyle) { return; } // if (xlsxStyle.fill) { if (xlsxStyle.fill.color) { cssStyle.backgroundColor = xlsxStyle.fill.color; } } // if (xlsxStyle.hAlign && xlsxStyle.hAlign != wjcXlsx.HAlign.Fill) { cssStyle.textAlign = wjcXlsx.HAlign[xlsxStyle.hAlign].toLowerCase(); } // let font = xlsxStyle.font; if (font) { if (font.family) { cssStyle.fontFamily = font.family; } if (font.bold) { cssStyle.fontWeight = 'bold'; } if (font.italic) { cssStyle.fontStyle = 'italic'; } if (font.size != null) { cssStyle.fontSize = font.size + 'px'; } if (font.underline) { cssStyle.textDecoration = 'underline'; } if (font.color) { cssStyle.color = font.color; } } } } // @NgModule({ imports: [BrowserModule, FormsModule], declarations: [AppComponent], bootstrap: [AppComponent] }) export class AppModule { } // enableProdMode(); // Bootstrap application with hash style navigation and global services. platformBrowserDynamic().bootstrapModule(AppModule); <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>GrapeCity Wijmo Workbook Viewer</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- Polyfills --> <script src="node_modules/core-js/client/shim.min.js"></script> <script src="node_modules/zone.js/dist/zone.min.js"></script> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.js"></script> <script src="systemjs.config.js"></script> <script> // workaround to load 'rxjs/operators' from the rxjs bundle System.import('rxjs').then(function (m) { System.set(SystemJS.resolveSync('rxjs/operators'), System.newModule(m.operators)); System.import('./src/app.component'); }); </script> </head> <body> <app-component></app-component> </body> </html> <div class="container-fluid"> <div class="row"> <input type="file" class="form-control" id="importFile" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel.sheet.macroEnabled.12" style="width:300px" /> </div> <!-- Sheet tabs --> <ul *ngIf="workbook" class="nav nav-tabs" style="margin-top:40px"> <li role="presentation" *ngFor="let sheet of workbook.sheets; let i = index" [ngClass]="{ active: i == sheetIndex }"> <a href="#" (click)="tabClicked($event, i)">{{sheet.name}}</a> </li> </ul> <!-- Current sheet view --> <div id="tableHost"></div> </div> <template> <div class="container-fluid"> <div class="row"> <input type="file" class="form-control" id="importFile" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel.sheet.macroEnabled.12" style="width:300px" /> </div> <!-- Sheet tabs --> <ul v-if="workbook != null" class="nav nav-tabs" style="margin-top:40px"> <li role="presentation" v-for="(sheet, index) in workbook.sheets" :key="index" v-bind:class="{active: index == sheetIndex}"> <a href="#" @click="tabClicked($event, index)">{{sheet.name}}</a> </li> </ul> <!-- Current sheet view --> <div id="tableHost"></div> </div> </template> <script> import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; import Vue from 'vue'; import * as wjcCore from '@grapecity/wijmo'; import * as wjcXlsx from '@grapecity/wijmo.xlsx'; let App = Vue.extend({ name: 'app', data: function() { return { workbook: null, sheetIndex: -1 }; }, mounted: function () { document.getElementById('importFile').addEventListener('change', () => { this._loadWorkbook(); }); }, methods: { tabClicked(e, index) { e.preventDefault(); this._drawSheet(index); }, _drawSheet(sheetIndex) { let drawRoot = document.getElementById('tableHost'); drawRoot.textContent = ''; this.sheetIndex = sheetIndex; this._drawWorksheet(this.workbook, sheetIndex, drawRoot, 200, 100); }, _loadWorkbook() { let reader = new FileReader(); reader.onload = (e) => { let workbook = new wjcXlsx.Workbook(); workbook.loadAsync(reader.result, (result) => { this.workbook = result; this._drawSheet(this.workbook.activeWorksheet || 0); }); }; let file = document.getElementById('importFile').files[0]; if (file) { reader.readAsDataURL(file); } }, _drawWorksheet(workbook, sheetIndex, rootElement, maxRows, maxColumns) { //NOTES: //Empty cells' values are numeric NaN, format is "General" // //Excessive empty properties: //fill.color = undefined // // netFormat should return '' for ''. What is 'General'? // font.color should start with '#'? // Column/row styles are applied to each cell style, this is convenient, but Column/row style info should be kept, // for column/row level styling // formats conversion is incorrect - dates and virtually everything; netFormat - return array of formats? // ?row heights - see hello.xlsx if (!workbook || !workbook.sheets || sheetIndex < 0 || workbook.sheets.length == 0) { return; } sheetIndex = Math.min(sheetIndex, workbook.sheets.length - 1); if (maxRows == null) { maxRows = 200; } if (maxColumns == null) { maxColumns = 100; } // Namespace and XlsxConverter shortcuts. let sheet = workbook.sheets[sheetIndex], defaultRowHeight = 20, defaultColumnWidth = 60, tableEl = document.createElement('table'); tableEl.border = '1'; tableEl.style.borderCollapse = 'collapse'; let maxRowCells = 0; for (let r = 0; sheet.rows && r < sheet.rows.length; r++) { if (sheet.rows[r] && sheet.rows[r].cells) { maxRowCells = Math.max(maxRowCells, sheet.rows[r].cells.length); } } // add columns let columnCount = 0; if (sheet.columns) { columnCount = sheet.columns.length; maxRowCells = Math.min(Math.max(maxRowCells, columnCount), maxColumns); for (let c = 0; c < maxRowCells; c++) { let col = c < columnCount ? sheet.columns[c] : null, colEl = document.createElement('col'); tableEl.appendChild(colEl); let colWidth = defaultColumnWidth + 'px'; if (col) { this._importStyle(colEl.style, col.style); if (col.autoWidth) { colWidth = ''; } else if (col.width != null) { colWidth = col.width + 'px'; } } colEl.style.width = colWidth; } } // generate rows let rowCount = Math.min(maxRows, sheet.rows.length); for (let r = 0; sheet.rows && r < rowCount; r++) { let row = sheet.rows[r], rowEl = document.createElement('tr'); tableEl.appendChild(rowEl); if (row) { this._importStyle(rowEl.style, row.style); if (row.height != null) { rowEl.style.height = row.height + 'px'; } for (let c = 0; row.cells && c < row.cells.length; c++) { let cell = row.cells[c], cellEl = document.createElement('td'); rowEl.appendChild(cellEl); if (cell) { this._importStyle(cellEl.style, cell.style); let value = cell.value; if (!(value == null || value !== value)) { // TBD: check for NaN should be eliminated let netFormat = ''; if (cell.style && cell.style.format) { netFormat = wjcXlsx.Workbook.fromXlsxFormat(cell.style.format)[0]; } let fmtValue = netFormat ? wjcCore.Globalize.format(value, netFormat) : value; cellEl.innerHTML = wjcCore.escapeHtml(fmtValue); } if (cell.colSpan && cell.colSpan > 1) { cellEl.colSpan = cell.colSpan; c += cellEl.colSpan - 1; } } } } // pad with empty cells let padCellsCount = maxRowCells - (row && row.cells ? row.cells.length : 0); for (let i = 0; i < padCellsCount; i++) { rowEl.appendChild(document.createElement('td')); } if (!rowEl.style.height) { rowEl.style.height = defaultRowHeight + 'px'; } } // do it at the end for performance rootElement.appendChild(tableEl); }, _importStyle(cssStyle, xlsxStyle) { if (!xlsxStyle) { return; } if (xlsxStyle.fill) { if (xlsxStyle.fill.color) { cssStyle.backgroundColor = xlsxStyle.fill.color; } } if (xlsxStyle.hAlign && xlsxStyle.hAlign != wjcXlsx.HAlign.Fill) { cssStyle.textAlign = wjcXlsx.HAlign[xlsxStyle.hAlign].toLowerCase(); } let font = xlsxStyle.font; if (font) { if (font.family) { cssStyle.fontFamily = font.family; } if (font.bold) { cssStyle.fontWeight = 'bold'; } if (font.italic) { cssStyle.fontStyle = 'italic'; } if (font.size != null) { cssStyle.fontSize = font.size + 'px'; } if (font.underline) { cssStyle.textDecoration = 'underline'; } if (font.color) { cssStyle.color = font.color; } } } } }); new Vue({ render: h => h(App) }).$mount('#app'); </script> <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>GrapeCity Wijmo Workbook Viewer</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app.vue'); </script> </head> <body> <div id="app"> </div> </body> </html> import 'bootstrap.css'; import '@grapecity/wijmo.styles/wijmo.css'; // import * as React from 'react'; import * as ReactDOM from 'react-dom'; import * as wjcCore from '@grapecity/wijmo'; import * as wjcXlsx from '@grapecity/wijmo.xlsx'; // class App extends React.Component { // constructor(props) { super(props); this._inputStyle = { width: '300px' }; this._navContainerStyle = { marginTop: '40px' }; // this.state = { workbook: null, sheetIndex: -1 }; } // render() { let lists = []; // if (this.state.workbook != null) { lists = this.state.workbook.sheets.map((sheet, index) => { return <li role="presentation" className={index === this.state.sheetIndex ? 'active' : ''}> <a href="#" onClick={e => { e.preventDefault(); this._drawSheet(index); }}>{sheet.name}</a> </li>; }); } // return <div className="container-fluid"> <div className="row"> <input type="file" className="form-control" id="importFile" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel.sheet.macroEnabled.12" style={this._inputStyle}/> </div> <ul className="nav nav-tabs" style={this._navContainerStyle}> {lists} </ul> <div id="tableHost"></div> </div>; } // componentDidMount() { document.getElementById('importFile').addEventListener('change', () => { this._loadWorkbook(); }); } // _drawSheet(sheetIndex) { let drawRoot = document.getElementById('tableHost'); drawRoot.textContent = ''; this.setState({ sheetIndex: sheetIndex }); this._drawWorksheet(this.state.workbook, sheetIndex, drawRoot, 200, 100); } // _loadWorkbook() { let reader = new FileReader(); // reader.onload = (e) => { let workbook = new wjcXlsx.Workbook(); workbook.loadAsync(reader.result, (result) => { this.setState({ workbook: result }); this._drawSheet(this.state.workbook.activeWorksheet || 0); }); }; // let file = document.getElementById('importFile').files[0]; if (file) { reader.readAsDataURL(file); } } // _drawWorksheet(workbook, sheetIndex, rootElement, maxRows, maxColumns) { //NOTES: //Empty cells' values are numeric NaN, format is "General" // //Excessive empty properties: //fill.color = undefined // // netFormat should return '' for ''. What is 'General'? // font.color should start with '#'? // Column/row styles are applied to each cell style, this is convenient, but Column/row style info should be kept, // for column/row level styling // formats conversion is incorrect - dates and virtually everything; netFormat - return array of formats? // ?row heights - see hello.xlsx if (!workbook || !workbook.sheets || sheetIndex < 0 || workbook.sheets.length == 0) { return; } // sheetIndex = Math.min(sheetIndex, workbook.sheets.length - 1); // if (maxRows == null) { maxRows = 200; } // if (maxColumns == null) { maxColumns = 100; } // // Namespace and XlsxConverter shortcuts. let sheet = workbook.sheets[sheetIndex], defaultRowHeight = 20, defaultColumnWidth = 60, tableEl = document.createElement('table'); // tableEl.border = '1'; tableEl.style.borderCollapse = 'collapse'; // let maxRowCells = 0; for (let r = 0; sheet.rows && r < sheet.rows.length; r++) { if (sheet.rows[r] && sheet.rows[r].cells) { maxRowCells = Math.max(maxRowCells, sheet.rows[r].cells.length); } } // // add columns let columnCount = 0; if (sheet.columns) { columnCount = sheet.columns.length; maxRowCells = Math.min(Math.max(maxRowCells, columnCount), maxColumns); for (let c = 0; c < maxRowCells; c++) { let col = c < columnCount ? sheet.columns[c] : null, colEl = document.createElement('col'); tableEl.appendChild(colEl); let colWidth = defaultColumnWidth + 'px'; if (col) { this._importStyle(colEl.style, col.style); if (col.autoWidth) { colWidth = ''; } else if (col.width != null) { colWidth = col.width + 'px'; } } colEl.style.width = colWidth; } } // // generate rows let rowCount = Math.min(maxRows, sheet.rows.length); for (let r = 0; sheet.rows && r < rowCount; r++) { let row = sheet.rows[r], rowEl = document.createElement('tr'); tableEl.appendChild(rowEl); if (row) { this._importStyle(rowEl.style, row.style); if (row.height != null) { rowEl.style.height = row.height + 'px'; } for (let c = 0; row.cells && c < row.cells.length; c++) { let cell = row.cells[c], cellEl = document.createElement('td'); rowEl.appendChild(cellEl); if (cell) { this._importStyle(cellEl.style, cell.style); let value = cell.value; if (!(value == null || value !== value)) { // TBD: check for NaN should be eliminated let netFormat = ''; if (cell.style && cell.style.format) { netFormat = wjcXlsx.Workbook.fromXlsxFormat(cell.style.format)[0]; } let fmtValue = netFormat ? wjcCore.Globalize.format(value, netFormat) : value; cellEl.innerHTML = wjcCore.escapeHtml(fmtValue); } if (cell.colSpan && cell.colSpan > 1) { cellEl.colSpan = cell.colSpan; c += cellEl.colSpan - 1; } } } } // // pad with empty cells let padCellsCount = maxRowCells - (row && row.cells ? row.cells.length : 0); for (let i = 0; i < padCellsCount; i++) { rowEl.appendChild(document.createElement('td')); } // if (!rowEl.style.height) { rowEl.style.height = defaultRowHeight + 'px'; } } // // do it at the end for performance rootElement.appendChild(tableEl); } // _importStyle(cssStyle, xlsxStyle) { if (!xlsxStyle) { return; } // if (xlsxStyle.fill) { if (xlsxStyle.fill.color) { cssStyle.backgroundColor = xlsxStyle.fill.color; } } // if (xlsxStyle.hAlign && xlsxStyle.hAlign != wjcXlsx.HAlign.Fill) { cssStyle.textAlign = wjcXlsx.HAlign[xlsxStyle.hAlign].toLowerCase(); } // let font = xlsxStyle.font; if (font) { if (font.family) { cssStyle.fontFamily = font.family; } if (font.bold) { cssStyle.fontWeight = 'bold'; } if (font.italic) { cssStyle.fontStyle = 'italic'; } if (font.size != null) { cssStyle.fontSize = font.size + 'px'; } if (font.underline) { cssStyle.textDecoration = 'underline'; } if (font.color) { cssStyle.color = font.color; } } } } // ReactDOM.render(<App />, document.getElementById('app')); <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>GrapeCity Wijmo Workbook Viewer</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- SystemJS --> <script src="node_modules/systemjs/dist/system.src.js"></script> <script src="systemjs.config.js"></script> <script> System.import('./src/app'); </script> </head> <body> <div id="app"></div> </body> </html>