", 2, null);
- /* set up function arguments */
- Object args[] = {d, q};
+ /* set up function arguments */
+ Object args[] = {d, q};
- /* call read -> wb workbook */
- Function readfunc = (Function)JSHelper.get_object("XLSX.read",this.scope);
- NativeObject wb = (NativeObject)readfunc.call(this.cx, this.scope, this.nXLSX, args);
+ /* call read -> wb workbook */
+ Function readfunc = (Function)JSHelper.get_object("XLSX.read",this.scope);
+ NativeObject wb = (NativeObject)readfunc.call(this.cx, this.scope, this.nXLSX, args);
- return new SheetJSFile(wb, this);
- }
+ return new SheetJSFile(wb, this);
+ }
- public static void close() { JSHelper.close(); }
+ public static void close() { JSHelper.close(); }
}
diff --git a/demos/altjs/com/sheetjs/SheetJSFile.java b/demos/altjs/com/sheetjs/SheetJSFile.java
index ee8f4dc..dcc0e08 100644
--- a/demos/altjs/com/sheetjs/SheetJSFile.java
+++ b/demos/altjs/com/sheetjs/SheetJSFile.java
@@ -6,19 +6,19 @@ import org.mozilla.javascript.NativeObject;
import org.mozilla.javascript.Function;
public class SheetJSFile {
- public NativeObject wb;
- public SheetJS sheetjs;
- public SheetJSFile() {}
- public SheetJSFile(NativeObject wb, SheetJS sheetjs) { this.wb = wb; this.sheetjs = sheetjs; }
- public String[] get_sheet_names() {
- try {
- return JSHelper.get_string_array("SheetNames", this.wb);
- } catch(ObjectNotFoundException e) {
- return null;
- }
- }
- public SheetJSSheet get_sheet(int idx) throws ObjectNotFoundException {
- return new SheetJSSheet(this, idx);
- }
+ public NativeObject wb;
+ public SheetJS sheetjs;
+ public SheetJSFile() {}
+ public SheetJSFile(NativeObject wb, SheetJS sheetjs) { this.wb = wb; this.sheetjs = sheetjs; }
+ public String[] get_sheet_names() {
+ try {
+ return JSHelper.get_string_array("SheetNames", this.wb);
+ } catch(ObjectNotFoundException e) {
+ return null;
+ }
+ }
+ public SheetJSSheet get_sheet(int idx) throws ObjectNotFoundException {
+ return new SheetJSSheet(this, idx);
+ }
}
diff --git a/demos/altjs/com/sheetjs/SheetJSSheet.java b/demos/altjs/com/sheetjs/SheetJSSheet.java
index 88a1cac..a99ab03 100644
--- a/demos/altjs/com/sheetjs/SheetJSSheet.java
+++ b/demos/altjs/com/sheetjs/SheetJSSheet.java
@@ -6,24 +6,24 @@ import org.mozilla.javascript.Function;
import org.mozilla.javascript.NativeObject;
public class SheetJSSheet {
- public NativeObject ws;
- public SheetJSFile wb;
- public SheetJSSheet(SheetJSFile wb, int idx) throws ObjectNotFoundException {
- this.wb = wb;
- this.ws = (NativeObject)JSHelper.get_object("Sheets." + wb.get_sheet_names()[idx],wb.wb);
- }
- public String get_range() throws ObjectNotFoundException {
- return JSHelper.get_object("!ref",this.ws).toString();
- }
- public String get_string_value(String address) throws ObjectNotFoundException {
- return JSHelper.get_object(address + ".v",this.ws).toString();
- }
+ public NativeObject ws;
+ public SheetJSFile wb;
+ public SheetJSSheet(SheetJSFile wb, int idx) throws ObjectNotFoundException {
+ this.wb = wb;
+ this.ws = (NativeObject)JSHelper.get_object("Sheets." + wb.get_sheet_names()[idx],wb.wb);
+ }
+ public String get_range() throws ObjectNotFoundException {
+ return JSHelper.get_object("!ref",this.ws).toString();
+ }
+ public String get_string_value(String address) throws ObjectNotFoundException {
+ return JSHelper.get_object(address + ".v",this.ws).toString();
+ }
- public String get_csv() throws ObjectNotFoundException {
- Function csvify = (Function)JSHelper.get_object("XLSX.utils.sheet_to_csv",this.wb.sheetjs.scope);
- Object csvArgs[] = {this.ws};
- Object csv = csvify.call(this.wb.sheetjs.cx, this.wb.sheetjs.scope, this.wb.sheetjs.scope, csvArgs);
- return csv.toString();
- }
+ public String get_csv() throws ObjectNotFoundException {
+ Function csvify = (Function)JSHelper.get_object("XLSX.utils.sheet_to_csv",this.wb.sheetjs.scope);
+ Object csvArgs[] = {this.ws};
+ Object csv = csvify.call(this.wb.sheetjs.cx, this.wb.sheetjs.scope, this.wb.sheetjs.scope, csvArgs);
+ return csv.toString();
+ }
}
diff --git a/demos/altjs/main.swift b/demos/altjs/main.swift
index 42462ec..24b278a 100755
--- a/demos/altjs/main.swift
+++ b/demos/altjs/main.swift
@@ -5,17 +5,17 @@ let sheetjs = try SheetJSCore();
try print(sheetjs.version());
let filenames: [[String]] = [
- ["xlsx", "xlsx"],
- ["xlsb", "xlsb"],
- ["biff8.xls", "xls"],
- ["xml.xls", "xlml"]
+ ["xlsx", "xlsx"],
+ ["xlsb", "xlsb"],
+ ["biff8.xls", "xls"],
+ ["xml.xls", "xlml"]
];
for fn in filenames {
- let wb: SJSWorkbook = try sheetjs.readFile(file: "sheetjs." + fn[0]);
- let ws: SJSWorksheet = try wb.getSheetAtIndex(idx: 0);
- let csv: String = try ws.toCSV();
- print(csv);
- let wbout: String = try wb.writeBStr(bookType: fn[1]);
- try wbout.write(toFile: "sheetjsswift." + fn[0], atomically: false, encoding: String.Encoding.isoLatin1);
+ let wb: SJSWorkbook = try sheetjs.readFile(file: "sheetjs." + fn[0]);
+ let ws: SJSWorksheet = try wb.getSheetAtIndex(idx: 0);
+ let csv: String = try ws.toCSV();
+ print(csv);
+ let wbout: String = try wb.writeBStr(bookType: fn[1]);
+ try wbout.write(toFile: "sheetjsswift." + fn[0], atomically: false, encoding: String.Encoding.isoLatin1);
}
diff --git a/demos/altjs/sheetjs.duk.c b/demos/altjs/sheetjs.duk.c
index 490f358..23f6c5d 100644
--- a/demos/altjs/sheetjs.duk.c
+++ b/demos/altjs/sheetjs.duk.c
@@ -66,6 +66,8 @@ int main(int argc, char *argv[]) {
DOIT("var global = (function(){ return this; }).call(null);");
/* load library */
+ res = eval_file(ctx, "shim.min.js");
+ if(res != 0) FAIL("shim load")
res = eval_file(ctx, "xlsx.full.min.js");
if(res != 0) FAIL("library load")
@@ -75,9 +77,9 @@ int main(int argc, char *argv[]) {
duk_pop(ctx);
/* read file */
-#define INFILE "sheetjs.xlsx"
- res = load_file(ctx, INFILE, "buf");
- if(res != 0) FAIL("load " INFILE)
+ res = load_file(ctx, argv[1], "buf");
+ if(res != 0) FAIL("file load")
+ printf("Loaded file %s\n", argv[1]);
/* parse workbook */
DOIT("wb = XLSX.read(buf, {type:'buffer', cellNF:true});");
diff --git a/demos/database/.eslintrc b/demos/database/.eslintrc
index d059de3..dbf6551 100644
--- a/demos/database/.eslintrc
+++ b/demos/database/.eslintrc
@@ -1,7 +1,7 @@
{
"env": { "shared-node-browser":true },
"parserOptions": {
- "ecmaVersion": 2017
+ "ecmaVersion": 8
},
"plugins": [ "html", "json" ]
}
diff --git a/demos/database/KnexTest.js b/demos/database/KnexTest.js
new file mode 100644
index 0000000..9675da2
--- /dev/null
+++ b/demos/database/KnexTest.js
@@ -0,0 +1,73 @@
+/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
+/* eslint-env node */
+/* global Promise */
+const XLSX = require('xlsx');
+const assert = require('assert');
+const SheetJSKnex = require("./SheetJSKnex");
+const Knex = require('knex');
+
+/* Connection to both databases are passed around */
+let P = Promise.resolve([
+ Knex({ client: 'sqlite3', connection: { filename: './knex1.db' } }),
+ Knex({ client: 'sqlite3', connection: { filename: './knex2.db' } })
+]);
+
+/* Sample data table */
+P = P.then(async (_) => {
+ const [knex] = _;
+ await knex.schema.dropTableIfExists('pres');
+ await knex.schema.createTable('pres', (table) => {
+ table.string('name');
+ table.integer('idx');
+ });
+ await knex.insert([
+ { name: "Barack Obama", idx: 44 },
+ { name: "Donald Trump", idx: 45 }
+ ]).into('pres');
+
+ await knex.schema.dropTableIfExists('fmts');
+ await knex.schema.createTable('fmts', (table) => {
+ table.string('ext');
+ table.string('ctr');
+ table.integer('multi');
+ });
+ await knex.insert([
+ { ext: 'XLSB', ctr: 'ZIP', multi: 1 },
+ { ext: 'XLS', ctr: 'CFB', multi: 1 },
+ { ext: 'XLML', ctr: '', multi: 1 },
+ { ext: 'CSV', ctr: 'ZIP', multi: 0 },
+ ]).into('fmts');
+
+ return _;
+});
+
+/* Export database to XLSX */
+P = P.then(async (_) => {
+ const [knex] = _;
+ const wb = XLSX.utils.book_new();
+ await SheetJSKnex.book_append_knex(wb, knex, "pres");
+ await SheetJSKnex.book_append_knex(wb, knex, "fmts");
+ XLSX.writeFile(wb, "knex.xlsx");
+ return _;
+});
+
+/* Import XLSX to database */
+P = P.then(async (_) => {
+ const [, knex] = _;
+ const wb = XLSX.readFile("knex.xlsx");
+ await SheetJSKnex.wb_to_knex(wb, knex);
+ return _;
+});
+
+/* Compare databases */
+P = P.then(async (_) => {
+ const [k1, k2] = _;
+ const P1 = await k1.select("*").from('pres');
+ const P2 = await k2.select("*").from('pres');
+ const F1 = await k1.select("*").from('fmts');
+ const F2 = await k2.select("*").from('fmts');
+ assert.deepEqual(P1, P2);
+ assert.deepEqual(F1, F2);
+});
+
+P.then(async () => { process.exit(); });
diff --git a/demos/database/MySQLTest.js b/demos/database/MySQLTest.js
index 40d1bb0..43ea452 100644
--- a/demos/database/MySQLTest.js
+++ b/demos/database/MySQLTest.js
@@ -27,7 +27,7 @@ var init = [
];
(async () => {
- const conn1 = await mysql.createConnection({...opts, database: "sheetjs"});
+ const conn1 = await mysql.createConnection(Object.assign({}, opts, {database: "sheetjs"}));
for(var i = 0; i < init.length; ++i) await conn1.query(init[i]);
/* Export table to XLSX */
@@ -50,7 +50,7 @@ var init = [
await conn1.close();
/* Import XLSX to table */
- const conn2 = await mysql.createConnection({...opts, database: "sheetj5"});
+ const conn2 = await mysql.createConnection(Object.assign({}, opts, {database: "sheetj5"}));
var wb2 = XLSX.readFile("mysql.xlsx");
var queries = SheetJSSQL.book_to_sql(wb2, "MYSQL");
for(i = 0; i < queries.length; ++i) await conn2.query(queries[i]);
diff --git a/demos/database/PgSQLTest.js b/demos/database/PgSQLTest.js
index a021ff5..b1d6651 100644
--- a/demos/database/PgSQLTest.js
+++ b/demos/database/PgSQLTest.js
@@ -26,8 +26,8 @@ var init = [
"INSERT INTO fmts VALUES ('CSV', '', 0)",
];
-var conn1 = new Client({...opts, database: "sheetjs"});
-var conn2 = new Client({...opts, database: "sheetj5"});
+var conn1 = new Client(Object.assign({}, opts, {database: "sheetjs"}));
+var conn2 = new Client(Object.assign({}, opts, {database: "sheetj5"}));
(async () => {
await conn1.connect();
for(var i = 0; i < init.length; ++i) await conn1.query(init[i]);
diff --git a/demos/database/README.md b/demos/database/README.md
index 4010ee9..dc6e071 100644
--- a/demos/database/README.md
+++ b/demos/database/README.md
@@ -49,8 +49,12 @@ scanned to determine the column "types", and there are third-party connectors
that can push arrays of JS objects to database tables.
The [`sexql`](http://sheetjs.com/sexql) browser demo uses WebSQL, which is
-limited to the SQLite fundamental types. Its schema builder scans the first row
-to find headers:
+limited to the SQLite fundamental types.
+
+
+ Implementation details (click to show)
+
+The `sexql` schema builder scans the first row to find headers:
```js
if(!ws || !ws['!ref']) return;
@@ -99,8 +103,11 @@ value of a column, the column is marked as `TEXT`:
}
```
+
+
The included `SheetJSSQL.js` script demonstrates SQL statement generation.
+
## Objects, K/V and "Schema-less" Databases
So-called "Schema-less" databases allow for arbitrary keys and values within the
@@ -137,6 +144,9 @@ XXX| A | B |
The included `ObjUtils.js` script demonstrates object-workbook conversion:
+
+ Implementation details (click to show)
+
```js
function deepset(obj, path, value) {
if(path.indexOf(".") == -1) return obj[path] = value;
@@ -185,6 +195,8 @@ function object_to_workbook(obj) {
}
```
+
+
## Browser APIs
@@ -229,7 +241,7 @@ differences surround API shape and supported data types.
[The `better-sqlite3` module](https://www.npmjs.com/package/better-sqlite3)
provides a very simple API for working with SQLite databases. `Statement#all`
-runs a prepared statement and returns an array of JS objects
+runs a prepared statement and returns an array of JS objects.
`SQLiteTest.js` generates a simple two-table SQLite database (`SheetJS1.db`),
exports to XLSX (`sqlite.xlsx`), imports the new XLSX file to a new database
@@ -255,6 +267,15 @@ The `rows` key of the object is an array of JS objects.
tables in the `sheetjs` database, exports to XLSX, imports the new XLSX file to
the `sheetj5` database and verifies the tables are preserved.
+#### Knex Query Builder
+
+[The `knex` module](https://www.npmjs.com/package/knex) builds SQL queries. The
+same exact code can be used against Oracle Database, MSSQL, and other engines.
+
+`KnexTest.js` uses the `sqlite3` connector and follows the same procedure as the
+SQLite test. The included `SheetJSKnex.js` script converts between the query
+builder and the common spreadsheet format.
+
### Key/Value Stores
#### Redis
@@ -267,7 +288,7 @@ strings in a special worksheet (`_strs`), the manifest in another worksheet
`RedisTest.js` connects to a local Redis server, populates data based on the
official Redis tutorial, exports to XLSX, flushes the server, imports the new
XLSX file and verifies the data round-tripped correctly. `SheetJSRedis.js`
-includes the implementation details
+includes the implementation details.
#### LowDB
diff --git a/demos/database/SQLiteTest.js b/demos/database/SQLiteTest.js
index 5b2500a..fb21812 100644
--- a/demos/database/SQLiteTest.js
+++ b/demos/database/SQLiteTest.js
@@ -21,7 +21,7 @@ var init = [
];
db1.exec(init.join(";"));
-/* Export table to XLSX */
+/* Export database to XLSX */
var wb = XLSX.utils.book_new();
function book_append_table(wb, db, name) {
var r = db.prepare('SELECT * FROM ' + name).all();
@@ -32,7 +32,7 @@ book_append_table(wb, db1, "pres");
book_append_table(wb, db1, "fmts");
XLSX.writeFile(wb, "sqlite.xlsx");
-/* Import XLSX to table */
+/* Import XLSX to database */
var db2 = new Database('SheetJS2.db');
var wb2 = XLSX.readFile("sqlite.xlsx");
var queries = SheetJSSQL.book_to_sql(wb2, "SQLITE");
@@ -46,7 +46,6 @@ var F2 = db2.prepare("SELECT * FROM fmts").all();
assert.deepEqual(P1, P2);
assert.deepEqual(F1, F2);
-/* Display results */
console.log(P2);
console.log(F2);
diff --git a/demos/database/SheetJSKnex.js b/demos/database/SheetJSKnex.js
new file mode 100644
index 0000000..d9b1758
--- /dev/null
+++ b/demos/database/SheetJSKnex.js
@@ -0,0 +1,78 @@
+/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
+/* eslint-env node */
+var XLSX = require("xlsx");
+
+async function book_append_knex(wb, knex, tbl) {
+ const aoo = await knex.select("*").from(tbl);
+ XLSX.utils.book_append_sheet(wb, XLSX.utils.json_to_sheet(aoo), tbl);
+}
+
+const TYPES = {
+ b: "boolean",
+ n: "float",
+ t: "string",
+ d: "dateTime"
+};
+async function ws_to_knex(ws, knex, n) {
+ if(!ws || !ws['!ref']) return;
+ var range = XLSX.utils.decode_range(ws['!ref']);
+ if(!range || !range.s || !range.e || range.s > range.e) return;
+ var R = range.s.r, C = range.s.c;
+
+ var names = new Array(range.e.c-range.s.c+1);
+ for(C = range.s.c; C<= range.e.c; ++C){
+ var addr = XLSX.utils.encode_cell({c:C,r:R});
+ names[C-range.s.c] = ws[addr] ? ws[addr].v : XLSX.utils.encode_col(C);
+ }
+
+ for(var i = 0; i < names.length; ++i) if(names.indexOf(names[i]) < i)
+ for(var j = 0; j < names.length; ++j) {
+ var _name = names[i] + "_" + (j+1);
+ if(names.indexOf(_name) > -1) continue;
+ names[i] = _name;
+ }
+
+ var types = new Array(range.e.c-range.s.c+1);
+ for(C = range.s.c; C<= range.e.c; ++C) {
+ var seen = {}, _type = "";
+ for(R = range.s.r+1; R<= range.e.r; ++R)
+ seen[(ws[XLSX.utils.encode_cell({c:C,r:R})]||{t:"z"}).t] = true;
+ if(seen.s || seen.str) _type = TYPES.t;
+ else if(seen.n + seen.b + seen.d + seen.e > 1) _type = TYPES.t;
+ else switch(true) {
+ case seen.b: _type = TYPES.b; break;
+ case seen.n: _type = TYPES.n; break;
+ case seen.e: _type = TYPES.t; break;
+ case seen.d: _type = TYPES.d; break;
+ }
+ types[C-range.s.c] = _type || TYPES.t;
+ }
+
+ await knex.schema.dropTableIfExists(n);
+ await knex.schema.createTable(n, (table) => { names.forEach((n, i) => { table[types[i] || "text"](n); }); });
+
+ for(R = range.s.r+1; R<= range.e.r; ++R) {
+ var row = {};
+ for(C = range.s.c; C<= range.e.c; ++C) {
+ var cell = ws[XLSX.utils.encode_cell({c:C,r:R})];
+ if(!cell) continue;
+ var key = names[C-range.s.c], val = cell.v;
+ if(types[C-range.s.c] == TYPES.n) if(cell.t == 'b' || typeof val == 'boolean' ) val = +val;
+ row[key] = val;
+ }
+ await knex.insert(row).into(n);;
+ }
+}
+
+async function wb_to_knex(wb, knex) {
+ for(var i = 0; i < wb.SheetNames.length; ++i) {
+ var n = wb.SheetNames[i];
+ var ws = wb.Sheets[n];
+ await ws_to_knex(ws, knex, n);
+ }
+}
+
+module.exports = {
+ book_append_knex,
+ wb_to_knex
+};
diff --git a/demos/database/SheetJSRedis.js b/demos/database/SheetJSRedis.js
index e3f4b64..1231ebf 100644
--- a/demos/database/SheetJSRedis.js
+++ b/demos/database/SheetJSRedis.js
@@ -67,6 +67,7 @@ async function wb_to_redis(wb, R) {
await aoa_to_redis[M[i].type](aoa, R, M[i].key);
}
}
+
module.exports = {
redis_to_wb,
wb_to_redis
diff --git a/demos/database/SheetJSSQL.js b/demos/database/SheetJSSQL.js
index a5bab14..731d3b1 100644
--- a/demos/database/SheetJSSQL.js
+++ b/demos/database/SheetJSSQL.js
@@ -1,4 +1,5 @@
/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */
+/* global XLSX, require, module */
var SheetJSSQL = (function() {
var X;
@@ -51,7 +52,7 @@ function sheet_to_sql(ws, sname, mode) {
var BT = mode == "PGSQL" ? "" : "`";
var Q = mode == "PGSQL" ? "'" : '"';
- var R = mode == "PGSQL" ? /'/g : /"/g;
+ var J = mode == "PGSQL" ? /'/g : /"/g;
out.push("DROP TABLE IF EXISTS " + BT + sname + BT );
out.push("CREATE TABLE " + BT + sname + BT + " (" + names.map(function(n, i) { return BT + n + BT + " " + (types[i]||"TEXT"); }).join(", ") + ");" );
@@ -64,7 +65,7 @@ function sheet_to_sql(ws, sname, mode) {
var val = cell.v;
switch(types[C-range.s.c]) {
case TYPES.n: if(cell.t == 'b' || typeof val == 'boolean' ) val = +val; break;
- default: val = Q + val.toString().replace(R, Q + Q) + Q;
+ default: val = Q + val.toString().replace(J, Q + Q) + Q;
}
values.push(val);
}
diff --git a/demos/fusebox/index.html b/demos/fusebox/index.html
index d657400..90dcdb8 100644
--- a/demos/fusebox/index.html
+++ b/demos/fusebox/index.html
@@ -1,14 +1,36 @@
+
+
-
-
-
-
-
-
+
+SheetJS FuseBox Test
+
-
+
+SheetJS FuseBox Demo
+
+Source Code Repo
+Issues? Something look weird? Click here and report an issue
+
+Original script: sheetjs.ts
+
+Console Output:
+
+
+
+
+
-
\ No newline at end of file
+