version bump 0.12.6: BrtUid

- `BrtUid` record (fixes #1044 h/t @gustavosimil)
- `sheet_to_json` allow default for errors (fixes #1035 h/t @arijitkanrar)
- docs and demos update
This commit is contained in:
SheetJS 2018-03-19 17:42:55 -04:00
parent 975c7fb57f
commit dc2128caca
35 changed files with 567 additions and 284 deletions

@ -99,8 +99,7 @@ Duktape
Nashorn
- demos/angular/README.md
angular-ui-grid
ui-grid
AngularJS
- demos/angular2/README.md
angular-cli

@ -157,12 +157,12 @@ In the browser, just add a script tag:
<details>
<summary><b>CDN Availability</b> (click to show)</summary>
| CDN | URL |
|-----------:|:-----------------------------------------|
| `unpkg` | <https://unpkg.com/xlsx/> |
| `jsDelivr` | <https://jsdelivr.com/package/npm/xlsx> |
| `CDNjs` | <http://cdnjs.com/libraries/xlsx> |
| `packd` | <https://bundle.run/xlsx?name=XLSX> |
| CDN | URL |
|-----------:|:-------------------------------------------|
| `unpkg` | <https://unpkg.com/xlsx/> |
| `jsDelivr` | <https://jsdelivr.com/package/npm/xlsx> |
| `CDNjs` | <http://cdnjs.com/libraries/xlsx> |
| `packd` | <https://bundle.run/xlsx@latest?name=XLSX> |
`unpkg` makes the latest version available at:
@ -190,7 +190,7 @@ $ bower install js-xlsx
The [`demos` directory](demos/) includes sample projects for:
**Frameworks and APIs**
- [`angular 1.x`](demos/angular/)
- [`angularjs`](demos/angular/)
- [`angular 2 / 4 / 5 and ionic`](demos/angular2/)
- [`meteor`](demos/meteor/)
- [`react and react-native`](demos/react/)
@ -345,15 +345,32 @@ The `table_to_book` and `table_to_sheet` utility functions take a DOM TABLE
element and iterate through the child nodes.
```js
var worksheet = XLSX.utils.table_to_book(document.getElementById('tableau'));
var workbook = XLSX.utils.table_to_book(document.getElementById('tableau'));
/* DO SOMETHING WITH workbook HERE */
```
Multiple tables on a web page can be converted to individual worksheets:
```js
/* create new workbook */
var workbook = XLSX.utils.book_new();
/* convert table 'table1' to worksheet named "Sheet1" */
var ws1 = XLSX.utils.table_to_book(document.getElementById('table1'));
XLSX.utils.book_append_sheet(workbook, ws1, "Sheet1");
/* convert table 'table2' to worksheet named "Sheet2" */
var ws2 = XLSX.utils.table_to_book(document.getElementById('table2'));
XLSX.utils.book_append_sheet(workbook, ws2, "Sheet2");
/* workbook now has 2 worksheets */
```
Alternatively, the HTML code can be extracted and parsed:
```js
var htmlstr = document.getElementById('tableau').outerHTML;
var worksheet = XLSX.read(htmlstr, {type:'string'});
var workbook = XLSX.read(htmlstr, {type:'string'});
```
</details>
@ -362,7 +379,7 @@ var worksheet = XLSX.read(htmlstr, {type:'string'});
<summary><b>Browser download file (ajax)</b> (click to show)</summary>
Note: for a more complete example that works in older browsers, check the demo
at <http://oss.sheetjs.com/js-xlsx/ajax.html>). The [`xhr` demo](demos/xhr/)
at <http://oss.sheetjs.com/js-xlsx/ajax.html>. The [`xhr` demo](demos/xhr/)
includes more examples with `XMLHttpRequest` and `fetch`.
```js
@ -566,7 +583,7 @@ var desired_value = (desired_cell ? desired_cell.v : undefined);
<summary><b>Adding a new worksheet to a workbook</b> (click to show)</summary>
This example uses [`XLSX.utils.aoa_to_sheet`](#array-of-arrays-input) to make a
worksheet and appends the new worksheet to the workbook:
sheet and `XLSX.utils.book_append_sheet` to append the sheet to the workbook:
```js
var new_ws_name = "SheetJS";
@ -578,16 +595,29 @@ var ws_data = [
];
var ws = XLSX.utils.aoa_to_sheet(ws_data);
/* Add the sheet name to the list */
wb.SheetNames.push(ws_name);
/* Load the worksheet object */
wb.Sheets[ws_name] = ws;
/* Add the worksheet to the workbook */
XLSX.utils.book_append_sheet(wb, ws, ws_name);
```
</details>
<details>
<summary><b>Creating a new workbook from scratch</b> (click to show)</summary>
The workbook object contains a `SheetNames` array of names and a `Sheets` object
mapping sheet names to sheet objects. The `XLSX.utils.book_new` utility function
creates a new workbook object:
```js
/* create a new blank workbook */
var wb = XLSX.utils.book_new();
```
The new workbook is blank and contains no worksheets. The write functions will
error if the workbook is empty.
</details>
### Parsing and Writing Examples

@ -42,6 +42,7 @@ program
.option('-E, --eth', 'emit ETH to <sheetname> or <file>.eth (Ethercalc)')
.option('-t, --txt', 'emit TXT to <sheetname> or <file>.txt (UTF-8 TSV)')
.option('-r, --rtf', 'emit RTF to <sheetname> or <file>.txt (Table RTF)')
.option('-z, --dump', 'dump internal representation as JSON')
.option('-F, --field-sep <sep>', 'CSV field separator', ",")
.option('-R, --row-sep <sep>', 'CSV row separator', "\n")
@ -158,6 +159,10 @@ if(program.listSheets) {
console.log((wb.SheetNames||[]).join("\n"));
process.exit(0);
}
if(program.dump) {
console.log(JSON.stringify(wb));
process.exit(0);
}
/* full workbook formats */
workbook_formats.forEach(function(m) { if(program[m[0]] || isfmt(m[0])) {

@ -1 +1 @@
XLSX.version = '0.12.5';
XLSX.version = '0.12.6';

@ -240,7 +240,7 @@ function parse_sty_bin(data, themes, opts) {
case 0x046A: /* 'BrtSlicerStyleElement' */
case 0x0200: /* 'BrtTableStyleElement' */
case 0x082F: /* 'BrtTimelineStyleElement' */
/* case 'BrtUid' */
case 0x0C00: /* 'BrtUid' */
break;
case 0x0023: /* 'BrtFRTBegin' */

@ -44,7 +44,8 @@ function parse_comments_bin(data, opts)/*:Array<RawComment>*/ {
if(!c.t) c.t = "";
delete c.rfx; out.push(c); break;
/* case 'BrtUid': */
case 0x0C00: /* 'BrtUid' */
break;
case 0x0023: /* 'BrtFRTBegin' */
pass = true; break;

@ -570,7 +570,6 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 0x01E5: /* 'BrtWsFmtInfo' */
break;
/* case 'BrtUid' */
case 0x00AF: /* 'BrtAFilterDateGroupItem' */
case 0x0284: /* 'BrtActiveX' */
case 0x0271: /* 'BrtBigName' */
@ -620,6 +619,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb/*:WBWBProps*/, themes, styles)/
case 0x0413: /* 'BrtSparkline' */
case 0x01AC: /* 'BrtTable' */
case 0x00AA: /* 'BrtTop10Filter' */
case 0x0C00: /* 'BrtUid' */
case 0x0032: /* 'BrtValueMeta' */
case 0x0816: /* 'BrtWebExtension' */
case 0x0415: /* 'BrtWsFmtInfoEx14' */

@ -56,7 +56,6 @@ function parse_cs_bin(data, opts, idx/*:number*/, rels, wb/*::, themes, styles*/
if(val.name) wb.Sheets[idx].CodeName = val.name;
break;
/* case 'BrtUid': */
case 0x0232: /* 'BrtBkHim' */
case 0x028C: /* 'BrtCsPageSetup' */
case 0x029D: /* 'BrtCsProtection' */
@ -64,6 +63,7 @@ function parse_cs_bin(data, opts, idx/*:number*/, rels, wb/*::, themes, styles*/
case 0x0227: /* 'BrtLegacyDrawing' */
case 0x0228: /* 'BrtLegacyDrawingHF' */
case 0x01DC: /* 'BrtMargins' */
case 0x0C00: /* 'BrtUid' */
break;
case 0x0023: /* 'BrtFRTBegin' */

@ -130,8 +130,8 @@ function parse_wb_bin(data, opts)/*:WorkbookFile*/ {
case 0x0169: /* 'BrtPlaceholderName' */
break;
/* case 'BrtModelTimeGroupingCalcCol' */
/* case 'BrtUid' */
/* case 'BrtModelTimeGroupingCalcCol' */
case 0x0C00: /* 'BrtUid' */
case 0x0C01: /* 'BrtRevisionPtr' */
case 0x0817: /* 'BrtAbsPath15' */
case 0x0216: /* 'BrtBookProtection' */

@ -826,6 +826,7 @@ var XLSBRecordEnum = {
/*::[*/0x085B/*::]*/: { n:"BrtBeginModelTimeGrouping" },
/*::[*/0x085C/*::]*/: { n:"BrtEndModelTimeGrouping" },
/*::[*/0x085D/*::]*/: { n:"BrtModelTimeGroupingCalcCol" },
/*::[*/0x0C00/*::]*/: { n:"BrtUid" },
/*::[*/0x0C01/*::]*/: { n:"BrtRevisionPtr" },
/*::[*/0xFFFF/*::]*/: { n:"" }
};

@ -57,7 +57,7 @@ function sheet_to_json(sheet/*:Worksheet*/, opts/*:?Sheet2JSONOpts*/) {
v = val.v;
switch(val.t){
case 'z': if(v == null) break; continue;
case 'e': continue;
case 'e': v = void 0; break;
case 's': case 'd': case 'b': case 'n': break;
default: throw new Error('unrecognized type ' + val.t);
}

@ -18,7 +18,7 @@ can be installed with Bash on Windows or with `cygwin`.
### Included Demos
**Frameworks and APIs**
- [`angular 1.x`](angular/)
- [`angularjs`](angular/)
- [`angular 2 / 4 / 5 and ionic`](angular2/)
- [`meteor`](meteor/)
- [`react and react-native`](react/)

@ -1,4 +1,4 @@
# Angular 1
# AngularJS
The `xlsx.core.min.js` and `xlsx.full.min.js` scripts are designed to be dropped
into web pages with script tags:
@ -7,14 +7,57 @@ into web pages with script tags:
<script src="xlsx.full.min.js"></script>
```
Strictly speaking, there should be no need for an angular demo! You can proceed
as you would with any other browser-friendly library. To make this meaningful,
we chose to show an integration with a common angular table component.
Strictly speaking, there should be no need for an Angular demo! You can proceed
as you would with any other browser-friendly library.
## Array of Objects
A common data table is often stored as an array of objects:
```js
$scope.data = [
{ Name: "Bill Clinton", Index: 42 },
{ Name: "GeorgeW Bush", Index: 43 },
{ Name: "Barack Obama", Index: 44 },
{ Name: "Donald Trump", Index: 45 }
];
```
This neatly maps to a table with `ng-repeat`:
```html
<table id="sjs-table">
<tr><th>Name</th><th>Index</th></tr>
<tr ng-repeat="row in data">
<td>{{row.Name}}</td>
<td>{{row.Index}}</td>
</tr>
</table>
```
The `$http` service can request binary data using the `"arraybuffer"` response
type coupled with `XLSX.read` with type `"array"`:
```js
$http({
method:'GET',
url:'https://sheetjs.com/pres.xlsx',
responseType:'arraybuffer'
}).then(function(data) {
var wb = XLSX.read(data.data, {type:"array"});
var d = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
$scope.data = d;
}, function(err) { console.log(err); });
```
The HTML table can be directly exported with `XLSX.utils.table_to_book`:
```js
var wb = XLSX.utils.table_to_book(document.getElementById('sjs-table'));
XLSX.writeFile(wb, "export.xlsx");
```
This demo uses angular-ui-grid to display a data table. The ui-grid does not
provide any way to modify the import button, so the demo includes a simple
directive for a HTML File Input control. It also includes a sample service for
export which adds an item to the export menu.
## Import Directive
@ -35,10 +78,10 @@ app.directive("importSheetJs", [SheetJSImportDirective]);
- Define the directive:
```js
var SheetJSImportDirective = function() {
function SheetJSImportDirective() {
return {
scope: { },
link: function ($scope, $elm, $attrs) {
scope: { opts: '=' },
link: function ($scope, $elm) {
$elm.on('change', function (changeEvent) {
var reader = new FileReader();
@ -54,12 +97,9 @@ var SheetJSImportDirective = function() {
});
}
};
};
}
```
The demo `SheetJSImportDirective` follows the prescription from the README for
File input controls using `readAsBinaryString`, converting to a suitable
representation and updating the scope.
## Export Service
@ -85,11 +125,22 @@ XLSX.utils.book_append_sheet(wb, ws, "Presidents");
XLSX.writeFile(wb, "sheetjs.xlsx");
```
## Demo
`grid.html` uses `angular-ui-grid` to display a table. The library does not
provide any way to modify the import button, so the demo includes a simple
directive for a HTML File Input control. It also includes a sample service for
export which adds an item to the export menu.
The demo `SheetJSImportDirective` follows the prescription from the README for
File input controls using `readAsBinaryString`, converting to a suitable
representation and updating the scope.
`SheetJSExportService` exposes export functions for `XLSB` and `XLSX`. Other
formats are easily supported by changing the `bookType` variable. It grabs
values from the grid, builds an array of arrays, generates a workbook and forces
a download. By setting the `filename` and `sheetname` options in the ui-grid
a download. By setting the `filename` and `sheetname` options in the `ui-grid`
options, the output can be controlled.
[![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx)

@ -1,93 +1,96 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* eslint-env browser */
/* global XLSX */
/* exported SheetJSExportService, SheetJSImportDirective */
function SheetJSExportService(uiGridExporterService) {
function exportSheetJS(gridApi, wopts) {
var columns = uiGridExporterService.getColumnHeaders(gridApi.grid, 'all');
var data = uiGridExporterService.getData(gridApi.grid, 'all', 'all');
function exportSheetJS(gridApi, wopts) {
var columns = uiGridExporterService.getColumnHeaders(gridApi.grid, 'all');
var data = uiGridExporterService.getData(gridApi.grid, 'all', 'all');
var fileName = gridApi.grid.options.filename || 'SheetJS';
fileName += wopts.bookType ? "." + wopts.bookType : '.xlsx';
var fileName = gridApi.grid.options.filename || 'SheetJS';
fileName += wopts.bookType ? "." + wopts.bookType : '.xlsx';
var sheetName = gridApi.grid.options.sheetname || 'Sheet1';
var sheetName = gridApi.grid.options.sheetname || 'Sheet1';
var wb = XLSX.utils.book_new(), ws = uigrid_to_sheet(data, columns);
XLSX.utils.book_append_sheet(wb, ws, sheetName);
XLSX.writeFile(wb, fileName);
}
var wb = XLSX.utils.book_new(), ws = uigrid_to_sheet(data, columns);
XLSX.utils.book_append_sheet(wb, ws, sheetName);
XLSX.writeFile(wb, fileName);
}
var service = {};
service.exportXLSB = function exportXLSB(gridApi) { return exportSheetJS(gridApi, { bookType: 'xlsb', bookSST: true, type: 'array' }); };
service.exportXLSX = function exportXLSX(gridApi) { return exportSheetJS(gridApi, { bookType: 'xlsx', bookSST: true, type: 'array' }); }
var service = {};
service.exportXLSB = function exportXLSB(gridApi) { return exportSheetJS(gridApi, { bookType: 'xlsb', bookSST: true, type: 'array' }); };
service.exportXLSX = function exportXLSX(gridApi) { return exportSheetJS(gridApi, { bookType: 'xlsx', bookSST: true, type: 'array' }); }
return service;
return service;
/* utilities */
function uigrid_to_sheet(data, columns) {
var o = [], oo = [], i = 0, j = 0;
/* utilities */
function uigrid_to_sheet(data, columns) {
var o = [], oo = [], i = 0, j = 0;
/* column headers */
for(j = 0; j < columns.length; ++j) oo.push(get_value(columns[j]));
o.push(oo);
/* column headers */
for(j = 0; j < columns.length; ++j) oo.push(get_value(columns[j]));
o.push(oo);
/* table data */
for(i = 0; i < data.length; ++i) {
oo = [];
for(j = 0; j < data[i].length; ++j) oo.push(get_value(data[i][j]));
o.push(oo);
}
/* aoa_to_sheet converts an array of arrays into a worksheet object */
return XLSX.utils.aoa_to_sheet(o);
}
/* table data */
for(i = 0; i < data.length; ++i) {
oo = [];
for(j = 0; j < data[i].length; ++j) oo.push(get_value(data[i][j]));
o.push(oo);
}
/* aoa_to_sheet converts an array of arrays into a worksheet object */
return XLSX.utils.aoa_to_sheet(o);
}
function get_value(col) {
if(!col) return col;
if(col.value) return col.value;
if(col.displayName) return col.displayName;
if(col.name) return col.name;
return null;
}
function get_value(col) {
if(!col) return col;
if(col.value) return col.value;
if(col.displayName) return col.displayName;
if(col.name) return col.name;
return null;
}
}
var SheetJSImportDirective = function() {
return {
scope: { opts: '=' },
link: function ($scope, $elm, $attrs) {
$elm.on('change', function (changeEvent) {
var reader = new FileReader();
function SheetJSImportDirective() {
return {
scope: { opts: '=' },
link: function($scope, $elm) {
$elm.on('change', function(changeEvent) {
var reader = new FileReader();
reader.onload = function (e) {
/* read workbook */
var bstr = e.target.result;
var wb = XLSX.read(bstr, {type:'binary'});
reader.onload = function(e) {
/* read workbook */
var bstr = e.target.result;
var wb = XLSX.read(bstr, {type:'binary'});
/* grab first sheet */
var wsname = wb.SheetNames[0];
var ws = wb.Sheets[wsname];
/* grab first sheet */
var wsname = wb.SheetNames[0];
var ws = wb.Sheets[wsname];
/* grab first row and generate column headers */
var aoa = XLSX.utils.sheet_to_json(ws, {header:1, raw:false});
var cols = [];
for(var i = 0; i < aoa[0].length; ++i) cols[i] = { field: aoa[0][i] };
/* grab first row and generate column headers */
var aoa = XLSX.utils.sheet_to_json(ws, {header:1, raw:false});
var cols = [];
for(var i = 0; i < aoa[0].length; ++i) cols[i] = { field: aoa[0][i] };
/* generate rest of the data */
var data = [];
for(var r = 1; r < aoa.length; ++r) {
data[r-1] = {};
for(i = 0; i < aoa[r].length; ++i) {
if(aoa[r][i] == null) continue;
data[r-1][aoa[0][i]] = aoa[r][i]
}
}
/* generate rest of the data */
var data = [];
for(var r = 1; r < aoa.length; ++r) {
data[r-1] = {};
for(i = 0; i < aoa[r].length; ++i) {
if(aoa[r][i] == null) continue;
data[r-1][aoa[0][i]] = aoa[r][i]
}
}
/* update scope */
$scope.$apply(function() {
$scope.opts.columnDefs = cols;
$scope.opts.data = data;
});
};
/* update scope */
$scope.$apply(function() {
$scope.opts.columnDefs = cols;
$scope.opts.data = data;
});
};
reader.readAsBinaryString(changeEvent.target.files[0]);
});
}
};
};
reader.readAsBinaryString(changeEvent.target.files[0]);
});
}
};
}

66
demos/angular/app.js vendored

@ -1,43 +1,45 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
/* eslint-env browser */
/* global angular, SheetJSExportService, SheetJSImportDirective */
var app = angular.module('app', ['ngAnimate', 'ngTouch', 'ui.grid', 'ui.grid.selection', 'ui.grid.exporter']);
/* Inject SheetJSExportService */
app.factory('SheetJSExportService', SheetJSExportService);
SheetJSExportService.inject = ['uiGridExporterService'];
app.controller('MainCtrl', ['$scope', '$http','SheetJSExportService', function ($scope, $http, SheetJSExportService) {
$scope.gridOptions = {
columnDefs: [
{ field: 'name' },
{ field: 'gender', visible: false},
{ field: 'company' }
],
enableGridMenu: true,
enableSelectAll: true,
exporterMenuPdf: false,
exporterMenuCsv: false,
showHeader: true,
onRegisterApi: function(gridApi){
$scope.gridApi = gridApi;
},
/* SheetJS Service setup */
filename: "SheetJSAngular",
sheetname: "ng-SheetJS",
gridMenuCustomItems: [
{
title: 'Export all data as XLSX',
action: function ($event) { SheetJSExportService.exportXLSX($scope.gridApi); },
order: 200
},
{
title: 'Export all data as XLSB',
action: function ($event) { SheetJSExportService.exportXLSB($scope.gridApi); },
order: 201
}
]
};
app.controller('MainCtrl', ['$scope', '$http','SheetJSExportService', function($scope, $http, SheetJSExportService) {
$scope.gridOptions = {
columnDefs: [
{ field: 'name' },
{ field: 'gender', visible: false},
{ field: 'company' }
],
enableGridMenu: true,
enableSelectAll: true,
exporterMenuPdf: false,
exporterMenuCsv: false,
showHeader: true,
onRegisterApi: function(gridApi){
$scope.gridApi = gridApi;
},
/* SheetJS Service setup */
filename: "SheetJSAngular",
sheetname: "ng-SheetJS",
gridMenuCustomItems: [
{
title: 'Export all data as XLSX',
action: function() { SheetJSExportService.exportXLSX($scope.gridApi); },
order: 200
},
{
title: 'Export all data as XLSB',
action: function() { SheetJSExportService.exportXLSB($scope.gridApi); },
order: 201
}
]
};
$http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/100.json').success(function(data) { $scope.gridOptions.data = data; });
$http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/100.json').success(function(data) { $scope.gridOptions.data = data; });
}]);
app.directive("importSheetJs", [SheetJSImportDirective]);

64
demos/angular/grid.html Normal file

@ -0,0 +1,64 @@
<!DOCTYPE html>
<!-- xlsx.js (C) 2013-present SheetJS http://sheetjs.com -->
<!-- vim: set ts=2: -->
<html ng-app="app">
<head>
<title>SheetJS + AngularJS + ui-grid</title>
<!-- Angular -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-touch.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-animate.js"></script>
<!-- ui-grid -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/4.0.0/ui-grid.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/4.0.0/ui-grid.css"/>
<!-- SheetJS js-xlsx library -->
<script src="shim.js"></script>
<script src="xlsx.full.min.js"></script>
<!-- SheetJS Service -->
<script src="SheetJS-angular.js"></script>
<style>
.grid1 {
width: 500px;
height: 400px;
};
</style>
</head>
<body>
<pre>
<b><a href="http://sheetjs.com">SheetJS + AngularJS demo</a></b>
The core library can be used as-is in AngularJS applications.
The <a href="https://github.com/sheetjs/js-xlsx">Community Edition README</a> details some common use cases.
We also have some <a href="http://sheetjs.com/demos/">more public demos</a>
This demo shows:
- SheetJSExportService: a service for exporting data from a ui-grid
- SheetJSImportDirective: a directive providing a file input button for import
<a href="https://obamawhitehouse.archives.gov/sites/default/files/omb/budget/fy2014/assets/receipts.xls">Sample Spreadsheet</a>
</pre>
<div ng-controller="MainCtrl">
<input type="file" import-sheet-js="" opts="gridOptions" multiple="false" />
<div id="grid1" ui-grid="gridOptions" ui-grid-selection ui-grid-exporter class="grid"></div>
</div>
<script src="app.js"></script>
<script type="text/javascript">
/* eslint no-use-before-define:0 */
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-36810333-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</body>
</html>

@ -1,53 +1,75 @@
<!DOCTYPE html>
<!-- xlsx.js (C) 2013-present SheetJS http://sheetjs.com -->
<!-- vim: set ts=2: -->
<html ng-app="app">
<html ng-app="sjs">
<head>
<title>SheetJS + Angular 1 + ui-grid</title>
<!-- Angular -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-touch.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-animate.js"></script>
<title>SheetJS + AngularJS</title>
<!-- Angular -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<!-- ui-grid -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/4.0.0/ui-grid.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/4.0.0/ui-grid.css"/>
<!-- SheetJS js-xlsx library -->
<script src="shim.js"></script>
<script src="xlsx.full.min.js"></script>
<!-- SheetJS Service -->
<script src="SheetJS-angular.js"></script>
<style>
.grid1 {
width: 500px;
height: 400px;
};
</style>
<!-- SheetJS js-xlsx library -->
<script src="shim.js"></script>
<script src="xlsx.full.min.js"></script>
</head>
<body>
<pre>
<b><a href="http://sheetjs.com">SheetJS + angular 1 + ui-grid demo</a></b>
<b><a href="http://sheetjs.com">SheetJS + AngularJS demo</a></b>
The core library can be used as-is in angular applications.
The core library can be used as-is in AngularJS applications.
The <a href="https://github.com/sheetjs/js-xlsx">Community Edition README</a> details some common use cases.
We also have some <a href="http://sheetjs.com/demos/">more public demos</a>
This demo shows:
- SheetJSExportService: a service for exporting data from a ui-grid
- SheetJSImportDirective: a directive providing a file input button for import
- $http request for XLSX file and scope update with data
- HTML table using ng-repeat
- XLSX table export using `XLSX.utils.table_to_book`
<a href="https://obamawhitehouse.archives.gov/sites/default/files/omb/budget/fy2014/assets/receipts.xls">Sample Spreadsheet</a>
<a href="https://sheetjs.com/pres.xlsx">Sample Spreadsheet</a>
</pre>
<div ng-controller="MainCtrl">
<input type="file" import-sheet-js="" opts="gridOptions" multiple="false" />
<div id="grid1" ui-grid="gridOptions" ui-grid-selection ui-grid-exporter class="grid"></div>
<div ng-controller="sheetjs">
<table id="sjs-table">
<tr><th>Name</th><th>Index</th></tr>
<tr ng-repeat="row in data">
<td>{{row.Name}}</td>
<td>{{row.Index}}</td>
</tr>
</table>
<button id="exportbtn">Export Table</button>
</div>
<script src="app.js"></script>
<script>
var app = angular.module('sjs', []);
app.controller('sheetjs', function($scope, $http) {
$http({
method:'GET',
url:'https://sheetjs.com/pres.xlsx',
responseType:'arraybuffer'
}).then(function(data) {
var wb = XLSX.read(data.data, {type:"array"});
var d = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
$scope.data = d;
}, function(err) { console.log(err); });
});
exportbtn.addEventListener('click', function() {
var wb = XLSX.utils.table_to_book(document.getElementById('sjs-table'));
XLSX.writeFile(wb, "export.xlsx");
});
</script>
<script type="text/javascript">
/* eslint no-use-before-define:0 */
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-36810333-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</body>
</html>

18
dist/xlsx.core.min.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.core.min.map generated vendored

File diff suppressed because one or more lines are too long

18
dist/xlsx.extendscript.js generated vendored

@ -9141,7 +9141,7 @@ module.exports = ZStream;
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
var XLSX = {};
(function make_xlsx(XLSX){
XLSX.version = '0.12.5';
XLSX.version = '0.12.6';
var current_codepage = 1200, current_ansi = 1252;
/*global cptable:true */
if(typeof module !== "undefined" && typeof require !== 'undefined') {
@ -17460,7 +17460,7 @@ function parse_sty_bin(data, themes, opts) {
case 0x046A: /* 'BrtSlicerStyleElement' */
case 0x0200: /* 'BrtTableStyleElement' */
case 0x082F: /* 'BrtTimelineStyleElement' */
/* case 'BrtUid' */
case 0x0C00: /* 'BrtUid' */
break;
case 0x0023: /* 'BrtFRTBegin' */
@ -18291,7 +18291,8 @@ function parse_comments_bin(data, opts) {
if(!c.t) c.t = "";
delete c.rfx; out.push(c); break;
/* case 'BrtUid': */
case 0x0C00: /* 'BrtUid' */
break;
case 0x0023: /* 'BrtFRTBegin' */
pass = true; break;
@ -22101,7 +22102,6 @@ function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles) {
case 0x01E5: /* 'BrtWsFmtInfo' */
break;
/* case 'BrtUid' */
case 0x00AF: /* 'BrtAFilterDateGroupItem' */
case 0x0284: /* 'BrtActiveX' */
case 0x0271: /* 'BrtBigName' */
@ -22151,6 +22151,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles) {
case 0x0413: /* 'BrtSparkline' */
case 0x01AC: /* 'BrtTable' */
case 0x00AA: /* 'BrtTop10Filter' */
case 0x0C00: /* 'BrtUid' */
case 0x0032: /* 'BrtValueMeta' */
case 0x0816: /* 'BrtWebExtension' */
case 0x0415: /* 'BrtWsFmtInfoEx14' */
@ -22484,7 +22485,6 @@ function parse_cs_bin(data, opts, idx, rels, wb) {
if(val.name) wb.Sheets[idx].CodeName = val.name;
break;
/* case 'BrtUid': */
case 0x0232: /* 'BrtBkHim' */
case 0x028C: /* 'BrtCsPageSetup' */
case 0x029D: /* 'BrtCsProtection' */
@ -22492,6 +22492,7 @@ function parse_cs_bin(data, opts, idx, rels, wb) {
case 0x0227: /* 'BrtLegacyDrawing' */
case 0x0228: /* 'BrtLegacyDrawingHF' */
case 0x01DC: /* 'BrtMargins' */
case 0x0C00: /* 'BrtUid' */
break;
case 0x0023: /* 'BrtFRTBegin' */
@ -23037,8 +23038,8 @@ function parse_wb_bin(data, opts) {
break;
/* case 'BrtModelTimeGroupingCalcCol' */
/* case 'BrtRevisionPtr' */
/* case 'BrtUid' */
case 0x0C00: /* 'BrtUid' */
case 0x0C01: /* 'BrtRevisionPtr' */
case 0x0817: /* 'BrtAbsPath15' */
case 0x0216: /* 'BrtBookProtection' */
case 0x02A5: /* 'BrtBookProtectionIso' */
@ -26163,6 +26164,7 @@ var XLSBRecordEnum = {
0x085B: { n:"BrtBeginModelTimeGrouping" },
0x085C: { n:"BrtEndModelTimeGrouping" },
0x085D: { n:"BrtModelTimeGroupingCalcCol" },
0x0C00: { n:"BrtUid" },
0x0C01: { n:"BrtRevisionPtr" },
0xFFFF: { n:"" }
};
@ -28569,7 +28571,7 @@ function sheet_to_json(sheet, opts) {
v = val.v;
switch(val.t){
case 'z': if(v == null) break; continue;
case 'e': continue;
case 'e': v = void 0; break;
case 's': case 'd': case 'b': case 'n': break;
default: throw new Error('unrecognized type ' + val.t);
}

32
dist/xlsx.full.min.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.full.min.map generated vendored

File diff suppressed because one or more lines are too long

18
dist/xlsx.js generated vendored

@ -4,7 +4,7 @@
/*global global, exports, module, require:false, process:false, Buffer:false, ArrayBuffer:false */
var XLSX = {};
(function make_xlsx(XLSX){
XLSX.version = '0.12.5';
XLSX.version = '0.12.6';
var current_codepage = 1200, current_ansi = 1252;
/*global cptable:true */
if(typeof module !== "undefined" && typeof require !== 'undefined') {
@ -8323,7 +8323,7 @@ function parse_sty_bin(data, themes, opts) {
case 0x046A: /* 'BrtSlicerStyleElement' */
case 0x0200: /* 'BrtTableStyleElement' */
case 0x082F: /* 'BrtTimelineStyleElement' */
/* case 'BrtUid' */
case 0x0C00: /* 'BrtUid' */
break;
case 0x0023: /* 'BrtFRTBegin' */
@ -9154,7 +9154,8 @@ function parse_comments_bin(data, opts) {
if(!c.t) c.t = "";
delete c.rfx; out.push(c); break;
/* case 'BrtUid': */
case 0x0C00: /* 'BrtUid' */
break;
case 0x0023: /* 'BrtFRTBegin' */
pass = true; break;
@ -12964,7 +12965,6 @@ function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles) {
case 0x01E5: /* 'BrtWsFmtInfo' */
break;
/* case 'BrtUid' */
case 0x00AF: /* 'BrtAFilterDateGroupItem' */
case 0x0284: /* 'BrtActiveX' */
case 0x0271: /* 'BrtBigName' */
@ -13014,6 +13014,7 @@ function parse_ws_bin(data, _opts, idx, rels, wb, themes, styles) {
case 0x0413: /* 'BrtSparkline' */
case 0x01AC: /* 'BrtTable' */
case 0x00AA: /* 'BrtTop10Filter' */
case 0x0C00: /* 'BrtUid' */
case 0x0032: /* 'BrtValueMeta' */
case 0x0816: /* 'BrtWebExtension' */
case 0x0415: /* 'BrtWsFmtInfoEx14' */
@ -13347,7 +13348,6 @@ function parse_cs_bin(data, opts, idx, rels, wb) {
if(val.name) wb.Sheets[idx].CodeName = val.name;
break;
/* case 'BrtUid': */
case 0x0232: /* 'BrtBkHim' */
case 0x028C: /* 'BrtCsPageSetup' */
case 0x029D: /* 'BrtCsProtection' */
@ -13355,6 +13355,7 @@ function parse_cs_bin(data, opts, idx, rels, wb) {
case 0x0227: /* 'BrtLegacyDrawing' */
case 0x0228: /* 'BrtLegacyDrawingHF' */
case 0x01DC: /* 'BrtMargins' */
case 0x0C00: /* 'BrtUid' */
break;
case 0x0023: /* 'BrtFRTBegin' */
@ -13900,8 +13901,8 @@ function parse_wb_bin(data, opts) {
break;
/* case 'BrtModelTimeGroupingCalcCol' */
/* case 'BrtRevisionPtr' */
/* case 'BrtUid' */
case 0x0C00: /* 'BrtUid' */
case 0x0C01: /* 'BrtRevisionPtr' */
case 0x0817: /* 'BrtAbsPath15' */
case 0x0216: /* 'BrtBookProtection' */
case 0x02A5: /* 'BrtBookProtectionIso' */
@ -17026,6 +17027,7 @@ var XLSBRecordEnum = {
0x085B: { n:"BrtBeginModelTimeGrouping" },
0x085C: { n:"BrtEndModelTimeGrouping" },
0x085D: { n:"BrtModelTimeGroupingCalcCol" },
0x0C00: { n:"BrtUid" },
0x0C01: { n:"BrtRevisionPtr" },
0xFFFF: { n:"" }
};
@ -19432,7 +19434,7 @@ function sheet_to_json(sheet, opts) {
v = val.v;
switch(val.t){
case 'z': if(v == null) break; continue;
case 'e': continue;
case 'e': v = void 0; break;
case 's': case 'd': case 'b': case 'n': break;
default: throw new Error('unrecognized type ' + val.t);
}

14
dist/xlsx.min.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/xlsx.min.map generated vendored

File diff suppressed because one or more lines are too long

@ -9,12 +9,12 @@ In the browser, just add a script tag:
<details>
<summary><b>CDN Availability</b> (click to show)</summary>
| CDN | URL |
|-----------:|:-----------------------------------------|
| `unpkg` | <https://unpkg.com/xlsx/> |
| `jsDelivr` | <https://jsdelivr.com/package/npm/xlsx> |
| `CDNjs` | <http://cdnjs.com/libraries/xlsx> |
| `packd` | <https://bundle.run/xlsx?name=XLSX> |
| CDN | URL |
|-----------:|:-------------------------------------------|
| `unpkg` | <https://unpkg.com/xlsx/> |
| `jsDelivr` | <https://jsdelivr.com/package/npm/xlsx> |
| `CDNjs` | <http://cdnjs.com/libraries/xlsx> |
| `packd` | <https://bundle.run/xlsx@latest?name=XLSX> |
`unpkg` makes the latest version available at:

@ -3,7 +3,7 @@
The [`demos` directory](demos/) includes sample projects for:
**Frameworks and APIs**
- [`angular 1.x`](demos/angular/)
- [`angularjs`](demos/angular/)
- [`angular 2 / 4 / 5 and ionic`](demos/angular2/)
- [`meteor`](demos/meteor/)
- [`react and react-native`](demos/react/)

@ -41,15 +41,32 @@ The `table_to_book` and `table_to_sheet` utility functions take a DOM TABLE
element and iterate through the child nodes.
```js
var worksheet = XLSX.utils.table_to_book(document.getElementById('tableau'));
var workbook = XLSX.utils.table_to_book(document.getElementById('tableau'));
/* DO SOMETHING WITH workbook HERE */
```
Multiple tables on a web page can be converted to individual worksheets:
```js
/* create new workbook */
var workbook = XLSX.utils.book_new();
/* convert table 'table1' to worksheet named "Sheet1" */
var ws1 = XLSX.utils.table_to_book(document.getElementById('table1'));
XLSX.utils.book_append_sheet(workbook, ws1, "Sheet1");
/* convert table 'table2' to worksheet named "Sheet2" */
var ws2 = XLSX.utils.table_to_book(document.getElementById('table2'));
XLSX.utils.book_append_sheet(workbook, ws2, "Sheet2");
/* workbook now has 2 worksheets */
```
Alternatively, the HTML code can be extracted and parsed:
```js
var htmlstr = document.getElementById('tableau').outerHTML;
var worksheet = XLSX.read(htmlstr, {type:'string'});
var workbook = XLSX.read(htmlstr, {type:'string'});
```
</details>
@ -58,7 +75,7 @@ var worksheet = XLSX.read(htmlstr, {type:'string'});
<summary><b>Browser download file (ajax)</b> (click to show)</summary>
Note: for a more complete example that works in older browsers, check the demo
at <http://oss.sheetjs.com/js-xlsx/ajax.html>). The [`xhr` demo](demos/xhr/)
at <http://oss.sheetjs.com/js-xlsx/ajax.html>. The [`xhr` demo](demos/xhr/)
includes more examples with `XMLHttpRequest` and `fetch`.
```js

@ -27,7 +27,7 @@ var desired_value = (desired_cell ? desired_cell.v : undefined);
<summary><b>Adding a new worksheet to a workbook</b> (click to show)</summary>
This example uses [`XLSX.utils.aoa_to_sheet`](#array-of-arrays-input) to make a
worksheet and appends the new worksheet to the workbook:
sheet and `XLSX.utils.book_append_sheet` to append the sheet to the workbook:
```js
var new_ws_name = "SheetJS";
@ -39,16 +39,29 @@ var ws_data = [
];
var ws = XLSX.utils.aoa_to_sheet(ws_data);
/* Add the sheet name to the list */
wb.SheetNames.push(ws_name);
/* Load the worksheet object */
wb.Sheets[ws_name] = ws;
/* Add the worksheet to the workbook */
XLSX.utils.book_append_sheet(wb, ws, ws_name);
```
</details>
<details>
<summary><b>Creating a new workbook from scratch</b> (click to show)</summary>
The workbook object contains a `SheetNames` array of names and a `Sheets` object
mapping sheet names to sheet objects. The `XLSX.utils.book_new` utility function
creates a new workbook object:
```js
/* create a new blank workbook */
var wb = XLSX.utils.book_new();
```
The new workbook is blank and contains no worksheets. The write functions will
error if the workbook is empty.
</details>
### Parsing and Writing Examples

@ -149,12 +149,12 @@ In the browser, just add a script tag:
```
| CDN | URL |
|-----------:|:-----------------------------------------|
| `unpkg` | <https://unpkg.com/xlsx/> |
| `jsDelivr` | <https://jsdelivr.com/package/npm/xlsx> |
| `CDNjs` | <http://cdnjs.com/libraries/xlsx> |
| `packd` | <https://bundle.run/xlsx?name=XLSX> |
| CDN | URL |
|-----------:|:-------------------------------------------|
| `unpkg` | <https://unpkg.com/xlsx/> |
| `jsDelivr` | <https://jsdelivr.com/package/npm/xlsx> |
| `CDNjs` | <http://cdnjs.com/libraries/xlsx> |
| `packd` | <https://bundle.run/xlsx@latest?name=XLSX> |
`unpkg` makes the latest version available at:
@ -181,7 +181,7 @@ $ bower install js-xlsx
The [`demos` directory](demos/) includes sample projects for:
**Frameworks and APIs**
- [`angular 1.x`](demos/angular/)
- [`angularjs`](demos/angular/)
- [`angular 2 / 4 / 5 and ionic`](demos/angular2/)
- [`meteor`](demos/meteor/)
- [`react and react-native`](demos/react/)
@ -322,21 +322,38 @@ The `table_to_book` and `table_to_sheet` utility functions take a DOM TABLE
element and iterate through the child nodes.
```js
var worksheet = XLSX.utils.table_to_book(document.getElementById('tableau'));
var workbook = XLSX.utils.table_to_book(document.getElementById('tableau'));
/* DO SOMETHING WITH workbook HERE */
```
Multiple tables on a web page can be converted to individual worksheets:
```js
/* create new workbook */
var workbook = XLSX.utils.book_new();
/* convert table 'table1' to worksheet named "Sheet1" */
var ws1 = XLSX.utils.table_to_book(document.getElementById('table1'));
XLSX.utils.book_append_sheet(workbook, ws1, "Sheet1");
/* convert table 'table2' to worksheet named "Sheet2" */
var ws2 = XLSX.utils.table_to_book(document.getElementById('table2'));
XLSX.utils.book_append_sheet(workbook, ws2, "Sheet2");
/* workbook now has 2 worksheets */
```
Alternatively, the HTML code can be extracted and parsed:
```js
var htmlstr = document.getElementById('tableau').outerHTML;
var worksheet = XLSX.read(htmlstr, {type:'string'});
var workbook = XLSX.read(htmlstr, {type:'string'});
```
Note: for a more complete example that works in older browsers, check the demo
at <http://oss.sheetjs.com/js-xlsx/ajax.html>). The [`xhr` demo](demos/xhr/)
at <http://oss.sheetjs.com/js-xlsx/ajax.html>. The [`xhr` demo](demos/xhr/)
includes more examples with `XMLHttpRequest` and `fetch`.
```js
@ -516,7 +533,7 @@ var desired_value = (desired_cell ? desired_cell.v : undefined);
This example uses [`XLSX.utils.aoa_to_sheet`](#array-of-arrays-input) to make a
worksheet and appends the new worksheet to the workbook:
sheet and `XLSX.utils.book_append_sheet` to append the sheet to the workbook:
```js
var new_ws_name = "SheetJS";
@ -528,16 +545,26 @@ var ws_data = [
];
var ws = XLSX.utils.aoa_to_sheet(ws_data);
/* Add the sheet name to the list */
wb.SheetNames.push(ws_name);
/* Load the worksheet object */
wb.Sheets[ws_name] = ws;
/* Add the worksheet to the workbook */
XLSX.utils.book_append_sheet(wb, ws, ws_name);
```
The workbook object contains a `SheetNames` array of names and a `Sheets` object
mapping sheet names to sheet objects. The `XLSX.utils.book_new` utility function
creates a new workbook object:
```js
/* create a new blank workbook */
var wb = XLSX.utils.book_new();
```
The new workbook is blank and contains no worksheets. The write functions will
error if the workbook is empty.
### Parsing and Writing Examples
- <http://sheetjs.com/demos/modify.html> read + modify + write files

@ -1,6 +1,6 @@
{
"name": "xlsx",
"version": "0.12.5",
"version": "0.12.6",
"author": "sheetjs",
"description": "SheetJS Spreadsheet data parser and writer",
"keywords": [

20
test.js

@ -1715,6 +1715,26 @@ describe('json output', function() {
assert.equal(json1[0].__EMPTY, 1);
assert.equal(json1[1].__EMPTY_1, 5);
});
it('should ignore errors and support default values', function() {
var ws = {
A1: {t:'s', v:"Field"}, B1: {t:'s', v:"Text"},
A2: {t:'e', v:0x2A, w:"#N/A" }, B2: {t:'s', v:"#N/A"},
A3: {t:'e', v:0x0F }, B3: {t:'s', v:"#VALUE!"},
A4: {t:'e', w:"#NAME?" }, B4: {t:'s', v:"#NAME?"},
"!ref": "A1:B4" };
seq(8).forEach(function(n) {
var opts = {};
if(n & 1) opts.header = 1;
if(n & 2) opts.raw = 1;
if(n & 4) opts.defval = null;
var J = X.utils.sheet_to_json(ws, opts);
// $FlowIgnore