angularjs
This commit is contained in:
parent
b71c65775b
commit
95f65248a0
@ -563,6 +563,176 @@ for(var i = 0; i < localForage.length; ++i) aoo.push(JSON.parse(await localForag
|
||||
const wb = XLSX.utils.json_to_sheet(aoo);
|
||||
```
|
||||
|
||||
### Other SQL Databases
|
||||
|
||||
The `generate_sql` function from ["Building Schemas from Worksheets"](#building-schemas-from-worksheets)
|
||||
can be adapted to generate SQL statements for a variety of databases, including:
|
||||
|
||||
**PostgreSQL**
|
||||
|
||||
The `pg` connector library was tested against the `generate_sql` output as-is.
|
||||
|
||||
The `rows` property of a query result is an array of objects that plays nice
|
||||
with `json_to_sheet`:
|
||||
|
||||
```js
|
||||
const aoa = await connection.query(`SELECT * FROM DataTable`).rows;
|
||||
const worksheet = XLSX.utils.json_to_sheet(aoa);
|
||||
```
|
||||
|
||||
**MySQL / MariaDB**
|
||||
|
||||
The `mysql2` connector library was tested. The differences are shown below,
|
||||
primarily stemming from the different quoting requirements and field types.
|
||||
|
||||
<details><summary><b>Differences</b> (click to show)</summary>
|
||||
|
||||
```js
|
||||
// highlight-start
|
||||
// define mapping between determined types and MySQL types
|
||||
const PG = { "n": "REAL", "s": "TEXT", "b": "TINYINT" };
|
||||
// highlight-end
|
||||
|
||||
function generate_sql(ws, wsname) {
|
||||
|
||||
// generate an array of objects from the data
|
||||
const aoo = XLSX.utils.sheet_to_json(ws);
|
||||
|
||||
// types will map column headers to types, while hdr holds headers in order
|
||||
const types = {}, hdr = [];
|
||||
|
||||
// loop across each row object
|
||||
aoo.forEach(row =>
|
||||
// Object.entries returns a row of [key, value] pairs. Loop across those
|
||||
Object.entries(row).forEach(([k,v]) => {
|
||||
|
||||
// If this is first time seeing key, mark unknown and append header array
|
||||
if(!types[k]) { types[k] = "?"; hdr.push(k); }
|
||||
|
||||
// skip null and undefined
|
||||
if(v == null) return;
|
||||
|
||||
// check and resolve type
|
||||
switch(typeof v) {
|
||||
case "string": // strings are the broadest type
|
||||
types[k] = "s"; break;
|
||||
case "number": // if column is not string, number is the broadest type
|
||||
if(types[k] != "s") types[k] = "n"; break;
|
||||
case "boolean": // only mark boolean if column is unknown or boolean
|
||||
if("?b".includes(types[k])) types[k] = "b"; break;
|
||||
default: types[k] = "s"; break; // default to string type
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
// The final array consists of the CREATE TABLE query and a series of INSERTs
|
||||
return [
|
||||
// generate CREATE TABLE query and return batch
|
||||
// highlight-next-line
|
||||
`CREATE TABLE ${wsname} (${hdr.map(h =>
|
||||
// highlight-next-line
|
||||
`${h} ${PG[types[h]]}`
|
||||
).join(", ")});`
|
||||
].concat(aoo.map(row => { // generate INSERT query for each row
|
||||
// entries will be an array of [key, value] pairs for the data in the row
|
||||
const entries = Object.entries(row);
|
||||
// fields will hold the column names and values will hold the values
|
||||
const fields = [], values = [];
|
||||
// check each key/value pair in the row
|
||||
entries.forEach(([k,v]) => {
|
||||
// skip null / undefined
|
||||
if(v == null) return;
|
||||
// highlight-next-line
|
||||
fields.push(`${k}`);
|
||||
// when the field type is numeric, `true` -> 1 and `false` -> 0
|
||||
if(types[k] == "n") values.push(typeof v == "boolean" ? (v ? 1 : 0) : v);
|
||||
// otherwise,
|
||||
// highlight-next-line
|
||||
else values.push(`"${v.toString().replaceAll('"', '""')}"`);
|
||||
})
|
||||
if(fields.length) return `INSERT INTO \`${wsname}\` (${fields.join(", ")}) VALUES (${values.join(", ")})`;
|
||||
})).filter(x => x); // filter out skipped rows
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
The first property of a query result is an array of objects that plays nice
|
||||
with `json_to_sheet`:
|
||||
|
||||
```js
|
||||
const aoa = await connection.query(`SELECT * FROM DataTable`)[0];
|
||||
const worksheet = XLSX.utils.json_to_sheet(aoa);
|
||||
```
|
||||
|
||||
|
||||
### Query Builders
|
||||
|
||||
Query builders are designed to simplify query generation and normalize field
|
||||
types and other database minutiae.
|
||||
|
||||
**Knex**
|
||||
|
||||
The result of a `SELECT` statement is an array of objects:
|
||||
|
||||
```js
|
||||
const aoo = await connection.select("*").from("DataTable");
|
||||
const worksheet = XLSX.utils.json_to_sheet(aoa);
|
||||
```
|
||||
|
||||
Knex wraps primitive types when creating a table. `generate_sql` takes a `knex`
|
||||
connection object and uses the API:
|
||||
|
||||
<details><summary><b>Generating a Table</b> (click to show)</summary>
|
||||
|
||||
```js
|
||||
// define mapping between determined types and Knex types
|
||||
const PG = { "n": "float", "s": "text", "b": "boolean" };
|
||||
|
||||
async function generate_sql(knex, ws, wsname) {
|
||||
|
||||
// generate an array of objects from the data
|
||||
const aoo = XLSX.utils.sheet_to_json(ws);
|
||||
|
||||
// types will map column headers to types, while hdr holds headers in order
|
||||
const types = {}, hdr = [];
|
||||
|
||||
// loop across each row object
|
||||
aoo.forEach(row =>
|
||||
// Object.entries returns a row of [key, value] pairs. Loop across those
|
||||
Object.entries(row).forEach(([k,v]) => {
|
||||
|
||||
// If this is first time seeing key, mark unknown and append header array
|
||||
if(!types[k]) { types[k] = "?"; hdr.push(k); }
|
||||
|
||||
// skip null and undefined
|
||||
if(v == null) return;
|
||||
|
||||
// check and resolve type
|
||||
switch(typeof v) {
|
||||
case "string": // strings are the broadest type
|
||||
types[k] = "s"; break;
|
||||
case "number": // if column is not string, number is the broadest type
|
||||
if(types[k] != "s") types[k] = "n"; break;
|
||||
case "boolean": // only mark boolean if column is unknown or boolean
|
||||
if("?b".includes(types[k])) types[k] = "b"; break;
|
||||
default: types[k] = "s"; break; // default to string type
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
await knex.schema.dropTableIfExists(wsname);
|
||||
await knex.schema.createTable(wsname, (table) => { hdr.forEach(h => { table[PG[types[h]] || "text"](h); }); });
|
||||
for(let i = 0; i < aoo.length; ++i) {
|
||||
if(!aoo[i] || !Object.keys(aoo[i]).length) continue;
|
||||
try { await knex.insert(aoo[i]).into(wsname); } catch(e) {}
|
||||
}
|
||||
return knex;
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
### MongoDB Structured Collections
|
||||
|
||||
|
@ -20,6 +20,135 @@ designed to be referenced with `<script>` tags.
|
||||
|
||||
## Frameworks
|
||||
|
||||
### AngularJS
|
||||
|
||||
[AngularJS](https://en.wikipedia.org/wiki/AngularJS) was a front-end MVC
|
||||
framework that was abandoned by Google in 2022. It should not be confused with
|
||||
"Angular" the modern framework.
|
||||
|
||||
The [Live demo](pathname:///angularjs/index.html) shows a simple table that is
|
||||
updated with file data and exported to spreadsheets.
|
||||
|
||||
This demo uses AngularJS 1.5.0.
|
||||
|
||||
<details><summary><b>Full Exposition</b> (click to show)</summary>
|
||||
|
||||
**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");
|
||||
```
|
||||
|
||||
|
||||
**Import Directive**
|
||||
|
||||
A general import directive is fairly straightforward:
|
||||
|
||||
- Define the `importSheetJs` directive in the app:
|
||||
|
||||
```js
|
||||
app.directive("importSheetJs", [SheetJSImportDirective]);
|
||||
```
|
||||
|
||||
- Add the attribute `import-sheet-js=""` to the file input element:
|
||||
|
||||
```html
|
||||
<input type="file" import-sheet-js="" multiple="false" />
|
||||
```
|
||||
|
||||
- Define the directive:
|
||||
|
||||
```js
|
||||
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 ab = e.target.result;
|
||||
var workbook = XLSX.read(ab);
|
||||
|
||||
/* DO SOMETHING WITH workbook HERE */
|
||||
};
|
||||
|
||||
reader.readAsArrayBuffer(changeEvent.target.files[0]);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
**Export Service**
|
||||
|
||||
An export can be triggered at any point! Depending on how data is represented,
|
||||
a workbook object can be built using the utility functions. For example, using
|
||||
an array of objects:
|
||||
|
||||
```js
|
||||
/* starting from this data */
|
||||
var data = [
|
||||
{ name: "Barack Obama", pres: 44 },
|
||||
{ name: "Donald Trump", pres: 45 }
|
||||
];
|
||||
|
||||
/* generate a worksheet */
|
||||
var ws = XLSX.utils.json_to_sheet(data);
|
||||
|
||||
/* add to workbook */
|
||||
var wb = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(wb, ws, "Presidents");
|
||||
|
||||
/* write workbook and force a download */
|
||||
XLSX.writeFile(wb, "sheetjs.xlsx");
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
### KnockoutJS
|
||||
|
||||
[KnockoutJS](https://en.wikipedia.org/wiki/Knockout_(web_framework)) was a
|
||||
@ -28,8 +157,9 @@ popular MVVM framework.
|
||||
The [Live demo](pathname:///knockout/knockout.html) shows a view model that is
|
||||
updated with file data and exported to spreadsheets.
|
||||
|
||||
<details><summary><b>Full Exposition</b> (click to show)</summary>
|
||||
|
||||
#### State
|
||||
**State**
|
||||
|
||||
Arrays of arrays are the simplest data structure for representing worksheets.
|
||||
|
||||
@ -70,7 +200,7 @@ var aoa = model.aoa();
|
||||
var ws = XLSX.utils.aoa_to_sheet(aoa);
|
||||
```
|
||||
|
||||
#### Data Binding
|
||||
**Data Binding**
|
||||
|
||||
`data-bind="foreach: ..."` provides a simple approach for binding to `TABLE`:
|
||||
|
||||
@ -92,3 +222,5 @@ binding is possible using the `$parent` and `$index` binding context properties:
|
||||
</tr>
|
||||
</table>
|
||||
```
|
||||
|
||||
</details>
|
153
docz/docs/04-getting-started/03-demos/14-grid.md
Normal file
153
docz/docs/04-getting-started/03-demos/14-grid.md
Normal file
@ -0,0 +1,153 @@
|
||||
---
|
||||
sidebar_position: 14
|
||||
title: Data Grids and UI
|
||||
---
|
||||
|
||||
Various JavaScript UI components provide a more interactive editing experience.
|
||||
Most are able to interchange with arrays of arrays or arrays of data objects.
|
||||
This demo focuses on a few open source data grids.
|
||||
|
||||
:::note
|
||||
|
||||
[SheetJS Pro](https://sheetjs.com/pro) offers additional features like styling
|
||||
and images. The UI tools typically support many of these advanced features.
|
||||
|
||||
To eliminate any confusion, the live examples linked from this page demonstrate
|
||||
SheetJS Community Edition data interchange.
|
||||
|
||||
:::
|
||||
|
||||
## Managed Lifecycle
|
||||
|
||||
Many UI components tend to manage the entire lifecycle, providing methods to
|
||||
import and export data.
|
||||
|
||||
The `sheet_to_json` utility function generates arrays of objects, which is
|
||||
suitable for a number of libraries. When more advanced shapes are needed,
|
||||
it is easier to munge the output of an array of arrays.
|
||||
|
||||
|
||||
### Canvas DataGrid
|
||||
|
||||
After extensive testing, [`canvas-datagrid`](https://canvas-datagrid.js.org/demo.html)
|
||||
stood out as a very high-performance grid with an incredibly simple API.
|
||||
|
||||
[Click here for a live integration demo.](pathname:///cdg/index.html)
|
||||
|
||||
<details><summary><b>Full Exposition</b> (click to show)</summary>
|
||||
|
||||
**Obtaining the Library**
|
||||
|
||||
The `canvas-datagrid` NodeJS packages include a minified script that can be
|
||||
directly inserted as a script tag. The unpkg CDN also serves this script:
|
||||
|
||||
```html
|
||||
<script src="https://unpkg.com/canvas-datagrid/dist/canvas-datagrid.js"></script>
|
||||
```
|
||||
|
||||
**Previewing Data**
|
||||
|
||||
The HTML document needs a container element:
|
||||
|
||||
```html
|
||||
<div id="gridctr"></div>
|
||||
```
|
||||
|
||||
Grid initialization is a one-liner:
|
||||
|
||||
```js
|
||||
var grid = canvasDatagrid({
|
||||
parentNode: document.getElementById('gridctr'),
|
||||
data: []
|
||||
});
|
||||
```
|
||||
|
||||
For large data sets, it's necessary to constrain the size of the grid.
|
||||
|
||||
```js
|
||||
grid.style.height = '100%';
|
||||
grid.style.width = '100%';
|
||||
```
|
||||
|
||||
Once the workbook is read and the worksheet is selected, assigning the data
|
||||
variable automatically updates the view:
|
||||
|
||||
```js
|
||||
grid.data = XLSX.utils.sheet_to_json(ws, {header:1});
|
||||
```
|
||||
|
||||
This demo previews the first worksheet.
|
||||
|
||||
**Editing**
|
||||
|
||||
`canvas-datagrid` handles the entire edit cycle. No intervention is necessary.
|
||||
|
||||
**Saving Data**
|
||||
|
||||
`grid.data` is immediately readable and can be converted back to a worksheet.
|
||||
Some versions return an array-like object without the length, so a little bit of
|
||||
preparation may be needed:
|
||||
|
||||
```js
|
||||
/* converts an array of array-like objects into an array of arrays */
|
||||
function prep(arr) {
|
||||
var out = [];
|
||||
for(var i = 0; i < arr.length; ++i) {
|
||||
if(!arr[i]) continue;
|
||||
if(Array.isArray(arr[i])) { out[i] = arr[i]; continue };
|
||||
var o = new Array();
|
||||
Object.keys(arr[i]).forEach(function(k) { o[+k] = arr[i][k] });
|
||||
out[i] = o;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/* build worksheet from the grid data */
|
||||
var ws = XLSX.utils.aoa_to_sheet(prep(grid.data));
|
||||
|
||||
/* build up workbook */
|
||||
var wb = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(wb, ws, 'SheetJS');
|
||||
|
||||
/* generate download */
|
||||
XLSX.writeFile(wb, "SheetJS.xlsx");
|
||||
```
|
||||
|
||||
**Additional Features**
|
||||
|
||||
This demo barely scratches the surface. The underlying grid component includes
|
||||
many additional features including massive data streaming, sorting and styling.
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
### Angular UI Grid
|
||||
|
||||
:::warning
|
||||
|
||||
This UI Grid is for AngularJS, not the modern Angular. New projects should not
|
||||
use AngularJS. This demo is included for legacy applications.
|
||||
|
||||
The [AngularJS demo](./legacy#angularjs) covers more general strategies.
|
||||
|
||||
:::
|
||||
|
||||
[Click here for a live integration demo.](pathname:///angularjs/ui-grid.html)
|
||||
|
||||
<details><summary><b>Notes</b> (click to show)</summary>
|
||||
|
||||
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 `readAsArrayBuffer`, converting to a suitable
|
||||
representation and updating the scope.
|
||||
|
||||
`SheetJSExportService` exposes export functions for `XLSB` and `XLSX`. Other
|
||||
file formats can be exported 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`
|
||||
options, the output can be controlled.
|
||||
|
||||
</details>
|
@ -18,7 +18,7 @@ The demo projects include small runnable examples and short explainers.
|
||||
|
||||
### Frameworks
|
||||
|
||||
- [`Angular.JS`](https://github.com/SheetJS/SheetJS/tree/master/demos/angular/)
|
||||
- [`Angular.JS`](./legacy#angularjs)
|
||||
- [`Angular 2+ and Ionic`](https://github.com/SheetJS/SheetJS/tree/master/demos/angular2/)
|
||||
- [`Knockout`](./legacy#knockout)
|
||||
- [`Meteor`](https://github.com/SheetJS/SheetJS/tree/master/demos/meteor/)
|
||||
@ -27,10 +27,11 @@ The demo projects include small runnable examples and short explainers.
|
||||
|
||||
### Front-End UI Components
|
||||
|
||||
- [`canvas-datagrid`](https://github.com/SheetJS/SheetJS/tree/master/demos/datagrid/)
|
||||
- [`canvas-datagrid`](./grid#canvas-datagrid)
|
||||
- [`x-spreadsheet`](https://github.com/SheetJS/SheetJS/tree/master/demos/xspreadsheet/)
|
||||
- [`react-data-grid`](https://github.com/SheetJS/SheetJS/tree/master/demos/react/modify/)
|
||||
- [`vue3-table-light`](https://github.com/SheetJS/SheetJS/tree/master/demos/vue/modify/)
|
||||
- [`angular-ui-grid`](./grid#angular-ui-grid)
|
||||
|
||||
### Platforms and Integrations
|
||||
|
||||
|
78
docz/static/angularjs/index.html
Normal file
78
docz/static/angularjs/index.html
Normal file
@ -0,0 +1,78 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- sheetjs (C) 2013-present SheetJS http://sheetjs.com -->
|
||||
<!-- vim: set ts=2: -->
|
||||
<html ng-app="s5s">
|
||||
<head>
|
||||
<title>SheetJS + AngularJS</title>
|
||||
<!-- Angular -->
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.min.js"></script>
|
||||
|
||||
<!-- SheetJS library -->
|
||||
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js"></script>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
|
||||
</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://docs.sheetjs.com">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:
|
||||
- $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://sheetjs.com/pres.xlsx">Sample Spreadsheet</a>
|
||||
|
||||
The table has hardcoded fields `Name` and `Index`.
|
||||
|
||||
</pre>
|
||||
|
||||
<div ng-controller="sheetjs">
|
||||
|
||||
<table id="s5s-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>
|
||||
var app = angular.module('s5s', []);
|
||||
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('s5s-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>
|
201
docz/static/angularjs/ui-grid.html
Normal file
201
docz/static/angularjs/ui-grid.html
Normal file
@ -0,0 +1,201 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- SheetJS (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>
|
||||
|
||||
<!-- SheetJS library -->
|
||||
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js"></script>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
|
||||
|
||||
<!-- ui-grid -->
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/4.11.0/ui-grid.js"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/4.11.0/ui-grid.css"/>
|
||||
<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://docs.sheetjs.com">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>
|
||||
|
||||
<!-- SheetJS Service -->
|
||||
<script>
|
||||
function SheetJSExportService(uiGridExporterService) {
|
||||
|
||||
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 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 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;
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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 SheetJSImportDirective() {
|
||||
return {
|
||||
scope: { opts: '=' },
|
||||
link: function($scope, $elm) {
|
||||
$elm.on('change', function(changeEvent) {
|
||||
var reader = new FileReader();
|
||||
|
||||
reader.onload = function(e) {
|
||||
/* read workbook */
|
||||
var ab = e.target.result;
|
||||
var wb = XLSX.read(ab);
|
||||
|
||||
/* 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] };
|
||||
|
||||
/* 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;
|
||||
});
|
||||
};
|
||||
|
||||
reader.readAsArrayBuffer(changeEvent.target.files[0]);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- App -->
|
||||
<script>
|
||||
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() { 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; });
|
||||
|
||||
}]);
|
||||
app.directive("importSheetJs", [SheetJSImportDirective]);
|
||||
|
||||
</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>
|
167
docz/static/cdg/index.html
Normal file
167
docz/static/cdg/index.html
Normal file
@ -0,0 +1,167 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- xlsx.js (C) 2013-present SheetJS http://sheetjs.com -->
|
||||
<!-- vim: set ts=2: -->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>SheetJS + canvas-datagrid Live Demo</title>
|
||||
<style>
|
||||
#drop{
|
||||
border:2px dashed #bbb;
|
||||
-moz-border-radius:5px;
|
||||
-webkit-border-radius:5px;
|
||||
border-radius:5px;
|
||||
padding:25px;
|
||||
text-align:center;
|
||||
font:20pt bold,"Vollkorn";color:#bbb
|
||||
}
|
||||
#b64data{
|
||||
width:100%;
|
||||
}
|
||||
a { text-decoration: none }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<pre>
|
||||
<b><a href="http://sheetjs.com">SheetJS Data Preview Live Demo</a></b>
|
||||
|
||||
<a href="https://canvas-datagrid.js.org/">canvas-datagrid component library</a>
|
||||
|
||||
<a href="https://github.com/SheetJS/sheetjs">Source Code Repo</a>
|
||||
<a href="https://github.com/SheetJS/sheetjs/issues">Issues? Something look weird? Click here and report an issue</a>
|
||||
|
||||
<div id="drop">Drop a spreadsheet file here to see sheet data</div>
|
||||
<input type="file" name="xlfile" id="xlf" /> ... or click here to select a file
|
||||
<textarea id="b64data">... or paste a base64-encoding here</textarea>
|
||||
<b>Advanced Demo Options:</b>
|
||||
</pre>
|
||||
<p><input type="submit" value="Export to XLSX!" id="xport" onclick="export_xlsx();" disabled="true"></p>
|
||||
<div id="htmlout"></div>
|
||||
<br />
|
||||
<script src="https://unpkg.com/canvas-datagrid/dist/canvas-datagrid.js"></script>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js"></script>
|
||||
<script src="https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js"></script>
|
||||
<script>
|
||||
/*jshint browser:true */
|
||||
/* eslint-env browser */
|
||||
/* eslint no-use-before-define:0 */
|
||||
/*global Uint8Array, Uint16Array, ArrayBuffer */
|
||||
/*global XLSX */
|
||||
|
||||
var cDg;
|
||||
|
||||
var process_wb = (function() {
|
||||
var XPORT = document.getElementById('xport');
|
||||
var HTMLOUT = document.getElementById('htmlout');
|
||||
|
||||
return function process_wb(wb) {
|
||||
/* get data */
|
||||
var ws = wb.Sheets[wb.SheetNames[0]];
|
||||
var data = XLSX.utils.sheet_to_json(ws, {header:1});
|
||||
|
||||
/* update canvas-datagrid */
|
||||
if(!cDg) cDg = canvasDatagrid({ parentNode:HTMLOUT, data:data });
|
||||
cDg.style.height = '100%';
|
||||
cDg.style.width = '100%';
|
||||
cDg.data = data;
|
||||
XPORT.disabled = false;
|
||||
|
||||
/* create schema (for A,B,C column headings) */
|
||||
var range = XLSX.utils.decode_range(ws['!ref']);
|
||||
for(var i = range.s.c; i <= range.e.c; ++i) cDg.schema[i - range.s.c].title = XLSX.utils.encode_col(i);
|
||||
|
||||
HTMLOUT.style.height = (window.innerHeight - 400) + "px";
|
||||
HTMLOUT.style.width = (window.innerWidth - 50) + "px";
|
||||
|
||||
if(typeof console !== 'undefined') console.log("output", new Date());
|
||||
};
|
||||
})();
|
||||
|
||||
var do_file = (function() {
|
||||
return function do_file(files) {
|
||||
var f = files[0];
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
if(typeof console !== 'undefined') console.log("onload", new Date());
|
||||
var data = e.target.result;
|
||||
data = new Uint8Array(data);
|
||||
process_wb(XLSX.read(data, {type: 'array'}));
|
||||
};
|
||||
reader.readAsArrayBuffer(f);
|
||||
};
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var drop = document.getElementById('drop');
|
||||
if(!drop.addEventListener) return;
|
||||
|
||||
function handleDrop(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
do_file(e.dataTransfer.files);
|
||||
}
|
||||
|
||||
function handleDragover(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
e.dataTransfer.dropEffect = 'copy';
|
||||
}
|
||||
|
||||
drop.addEventListener('dragenter', handleDragover, false);
|
||||
drop.addEventListener('dragover', handleDragover, false);
|
||||
drop.addEventListener('drop', handleDrop, false);
|
||||
})();
|
||||
|
||||
(function() {
|
||||
var xlf = document.getElementById('xlf');
|
||||
if(!xlf.addEventListener) return;
|
||||
function handleFile(e) { do_file(e.target.files); }
|
||||
xlf.addEventListener('change', handleFile, false);
|
||||
})();
|
||||
|
||||
var export_xlsx = (function() {
|
||||
function prep(arr) {
|
||||
var out = [];
|
||||
for(var i = 0; i < arr.length; ++i) {
|
||||
if(!arr[i]) continue;
|
||||
if(Array.isArray(arr[i])) { out[i] = arr[i]; continue };
|
||||
var o = new Array();
|
||||
Object.keys(arr[i]).forEach(function(k) { o[+k] = arr[i][k] });
|
||||
out[i] = o;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
return function export_xlsx() {
|
||||
if(!cDg) return;
|
||||
/* convert canvas-datagrid data to worksheet */
|
||||
var new_ws = XLSX.utils.aoa_to_sheet(prep(cDg.data));
|
||||
|
||||
/* build workbook */
|
||||
var new_wb = XLSX.utils.book_new();
|
||||
XLSX.utils.book_append_sheet(new_wb, new_ws, 'SheetJS');
|
||||
|
||||
/* write file and trigger a download */
|
||||
XLSX.writeFile(new_wb, 'SheetJSCanvasDataGridExport.xlsx', {bookSST:true});
|
||||
};
|
||||
})();
|
||||
|
||||
(async() => {
|
||||
const ab = await(await fetch("https://sheetjs.com/pres.numbers")).arrayBuffer();
|
||||
process_wb(XLSX.read(ab));
|
||||
})();
|
||||
</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>
|
Loading…
Reference in New Issue
Block a user