From 5de62a947ff8ac94089133859bc8384313f07fed Mon Sep 17 00:00:00 2001 From: SheetJS Date: Mon, 12 Mar 2018 22:51:54 -0400 Subject: [PATCH] version bump 0.12.5: ancillary utility update - add BOM to `stream.to_csv` (fixes #1024 h/t @hr5959) - `utils.format_cell` type (h/t @victorj2307) - duktape niggles - demo cleanup --- .spelling | 1 + README.md | 1 + bits/01_version.js | 2 +- bits/55_vml.js | 3 +- bits/57_cmntxml.js | 12 +- bits/75_xlml.js | 2 + bits/97_node.js | 2 + demos/altjs/.gitignore | 1 + demos/altjs/Makefile | 10 +- demos/altjs/SheetJSCore.swift | 144 +++++++++--------- demos/altjs/SheetJSRhino.java | 36 ++--- demos/altjs/com/sheetjs/JSHelper.java | 62 ++++---- .../com/sheetjs/ObjectNotFoundException.java | 4 +- demos/altjs/com/sheetjs/SheetJS.java | 64 ++++---- demos/altjs/com/sheetjs/SheetJSFile.java | 28 ++-- demos/altjs/com/sheetjs/SheetJSSheet.java | 36 ++--- demos/altjs/main.swift | 20 +-- demos/altjs/sheetjs.duk.c | 8 +- demos/database/.eslintrc | 2 +- demos/database/KnexTest.js | 73 +++++++++ demos/database/MySQLTest.js | 4 +- demos/database/PgSQLTest.js | 4 +- demos/database/README.md | 29 +++- demos/database/SQLiteTest.js | 5 +- demos/database/SheetJSKnex.js | 78 ++++++++++ demos/database/SheetJSRedis.js | 1 + demos/database/SheetJSSQL.js | 5 +- demos/fusebox/index.html | 38 ++++- demos/oldie/README.md | 2 + demos/react/Makefile | 2 +- demos/react/README.md | 6 +- demos/react/native.sh | 2 +- demos/react/react-native.js | 32 ++-- demos/systemjs/Makefile | 5 +- demos/systemjs/README.md | 2 +- demos/systemjs/main.simple.js | 2 +- demos/systemjs/simple.html | 34 +++++ demos/typescript/Makefile | 6 +- demos/typescript/demo.js | 3 + demos/typescript/lib/index.ts | 10 +- demos/typescript/package.json | 4 +- demos/typescript/src/index.js | 4 + demos/typescript/tslint.json | 11 ++ demos/xhr/.gitignore | 1 + demos/xhr/README.md | 17 +-- demos/xhr/axios.html | 5 +- demos/xhr/fetch.html | 5 +- demos/xhr/server.js | 14 +- demos/xhr/superagent.html | 5 +- demos/xhr/xhr.html | 5 +- dist/xlsx.core.min.js | 28 ++-- dist/xlsx.core.min.map | 2 +- dist/xlsx.extendscript.js | 21 +-- dist/xlsx.full.min.js | 16 +- dist/xlsx.full.min.map | 2 +- dist/xlsx.js | 21 +-- dist/xlsx.min.js | 16 +- dist/xlsx.min.map | 2 +- docbits/10_install.md | 1 + misc/docs/README.md | 1 + package.json | 2 +- tests/write.js | 2 +- types/index.d.ts | 3 + types/xlsx-tests.ts | 25 ++- xlsx.flow.js | 21 +-- xlsx.js | 21 +-- 66 files changed, 681 insertions(+), 355 deletions(-) create mode 100644 demos/database/KnexTest.js create mode 100644 demos/database/SheetJSKnex.js create mode 100644 demos/typescript/tslint.json create mode 100644 demos/xhr/.gitignore diff --git a/.spelling b/.spelling index 2d15f0c..0f0de95 100644 --- a/.spelling +++ b/.spelling @@ -106,6 +106,7 @@ ui-grid angular-cli - demos/database/README.md +Knex LowDB MariaDB MySQL diff --git a/README.md b/README.md index d622287..14ba8a9 100644 --- a/README.md +++ b/README.md @@ -162,6 +162,7 @@ In the browser, just add a script tag: | `unpkg` | | | `jsDelivr` | | | `CDNjs` | | +| `packd` | | `unpkg` makes the latest version available at: diff --git a/bits/01_version.js b/bits/01_version.js index e287eea..c6a4dc6 100644 --- a/bits/01_version.js +++ b/bits/01_version.js @@ -1 +1 @@ -XLSX.version = '0.12.4'; +XLSX.version = '0.12.5'; diff --git a/bits/55_vml.js b/bits/55_vml.js index 2688d29..ff86aa5 100644 --- a/bits/55_vml.js +++ b/bits/55_vml.js @@ -14,7 +14,8 @@ function write_comments_vml(rId, comments) { ]; while(_shapeid < rId * 1000) _shapeid += 1000; - comments.map(function(x) { return decode_cell(x[0]); }).forEach(function(c) { o = o.concat([ + comments.forEach(function(x) { var c = decode_cell(x[0]); + o = o.concat([ '*/ = []; o.push(""); - data.map(function(x) { return x[1]; }).forEach(function(comment) { - comment.map(function(x) { return escapexml(x.a); }).forEach(function(a) { - if(iauthor.indexOf(a) > -1) return; - iauthor.push(a); - o.push("" + a + ""); - }); - }); + data.forEach(function(x) { x[1].forEach(function(w) { var a = escapexml(w.a); + if(iauthor.indexOf(a) > -1) return; + iauthor.push(a); + o.push("" + a + ""); + }); }); o.push(""); o.push(""); data.forEach(function(d) { diff --git a/bits/75_xlml.js b/bits/75_xlml.js index d1fef06..c05fef0 100644 --- a/bits/75_xlml.js +++ b/bits/75_xlml.js @@ -163,6 +163,8 @@ function xlml_clean_comment(comment/*:any*/) { function xlml_normalize(d)/*:string*/ { if(has_buf &&/*::typeof Buffer !== "undefined" && d != null && d instanceof Buffer &&*/ Buffer.isBuffer(d)) return d.toString('utf8'); if(typeof d === 'string') return d; + /* duktape */ + if(typeof Uint8Array !== 'undefined' && d instanceof Uint8Array) return utf8read(a2s(ab2a(d))); throw new Error("Bad input format: expected Buffer or string"); } diff --git a/bits/97_node.js b/bits/97_node.js index fdd1c4f..ed90247 100644 --- a/bits/97_node.js +++ b/bits/97_node.js @@ -15,7 +15,9 @@ if(has_buf && typeof require != 'undefined') (function() { var rowinfo/*:Array*/ = o.skipHidden && sheet["!rows"] || []; for(var C = r.s.c; C <= r.e.c; ++C) if (!((colinfo[C]||{}).hidden)) cols[C] = encode_col(C); var R = r.s.r; + var BOM = false; stream._read = function() { + if(!BOM) { BOM = true; return stream.push("\uFEFF"); } if(R > r.e.r) return stream.push(null); while(R <= r.e.r) { ++R; diff --git a/demos/altjs/.gitignore b/demos/altjs/.gitignore index cdf6d02..535d624 100644 --- a/demos/altjs/.gitignore +++ b/demos/altjs/.gitignore @@ -4,5 +4,6 @@ duk* *.class *.jar rhino +shim.min.js xlsx.*.js payload.js diff --git a/demos/altjs/Makefile b/demos/altjs/Makefile index 49047c4..60286cd 100644 --- a/demos/altjs/Makefile +++ b/demos/altjs/Makefile @@ -5,12 +5,16 @@ all: duktape nashorn rhinojs swift base: if [ ! -e sheetjs.xlsx ]; then node ../../tests/write.js; fi if [ ! -e xlsx.full.min.js ]; then cp ../../dist/xlsx.full.min.js .; fi + if [ ! -e shim.min.js ]; then cp ../../dist/shim.min.js .; fi -.PHONY: duktape -duktape: base ## duktape demo +.PHONY: duk +duk: base bash ./duktape.sh gcc -std=c99 -Wall -osheetjs.duk sheetjs.duk.c duktape.c -lm - ./sheetjs.duk + +.PHONY: duktape +duktape: duk ## duktape demo + for ext in xlsx xlsb biff8.xls xml.xls; do ./sheetjs.duk sheetjs.$$ext; done .PHONY: nashorn nashorn: base ## nashorn demo diff --git a/demos/altjs/SheetJSCore.swift b/demos/altjs/SheetJSCore.swift index 8e98d1c..1555278 100755 --- a/demos/altjs/SheetJSCore.swift +++ b/demos/altjs/SheetJSCore.swift @@ -2,95 +2,95 @@ import JavaScriptCore; enum SJSError: Error { - case badJSContext; - case badJSWorkbook; - case badJSWorksheet; + case badJSContext; + case badJSWorkbook; + case badJSWorksheet; }; class SJSWorksheet { - var context: JSContext!; - var wb: JSValue!; var ws: JSValue!; - var idx: Int32; + var context: JSContext!; + var wb: JSValue!; var ws: JSValue!; + var idx: Int32; - func toCSV() throws -> String { - let XLSX: JSValue! = context.objectForKeyedSubscript("XLSX"); - let utils: JSValue! = XLSX.objectForKeyedSubscript("utils"); - let sheet_to_csv: JSValue! = utils.objectForKeyedSubscript("sheet_to_csv"); - return sheet_to_csv.call(withArguments: [ws]).toString(); - } + func toCSV() throws -> String { + let XLSX: JSValue! = context.objectForKeyedSubscript("XLSX"); + let utils: JSValue! = XLSX.objectForKeyedSubscript("utils"); + let sheet_to_csv: JSValue! = utils.objectForKeyedSubscript("sheet_to_csv"); + return sheet_to_csv.call(withArguments: [ws]).toString(); + } - init(ctx: JSContext, workbook: JSValue, worksheet: JSValue, idx: Int32) throws { - self.context = ctx; self.wb = workbook; self.ws = worksheet; self.idx = idx; - } + init(ctx: JSContext, workbook: JSValue, worksheet: JSValue, idx: Int32) throws { + self.context = ctx; self.wb = workbook; self.ws = worksheet; self.idx = idx; + } } class SJSWorkbook { - var context: JSContext!; - var wb: JSValue!; var SheetNames: JSValue!; var Sheets: JSValue!; + var context: JSContext!; + var wb: JSValue!; var SheetNames: JSValue!; var Sheets: JSValue!; - func getSheetAtIndex(idx: Int32) throws -> SJSWorksheet { - let SheetName: String = SheetNames.atIndex(Int(idx)).toString(); - let ws: JSValue! = Sheets.objectForKeyedSubscript(SheetName); - return try SJSWorksheet(ctx: context, workbook: wb, worksheet: ws, idx: idx); - } + func getSheetAtIndex(idx: Int32) throws -> SJSWorksheet { + let SheetName: String = SheetNames.atIndex(Int(idx)).toString(); + let ws: JSValue! = Sheets.objectForKeyedSubscript(SheetName); + return try SJSWorksheet(ctx: context, workbook: wb, worksheet: ws, idx: idx); + } - func writeBStr(bookType: String = "xlsx") throws -> String { - let XLSX: JSValue! = context.objectForKeyedSubscript("XLSX"); - context.evaluateScript(String(format: "var writeopts = {type:'binary', bookType:'%@'}", bookType)); - let writeopts: JSValue! = context.objectForKeyedSubscript("writeopts"); - let writefunc: JSValue! = XLSX.objectForKeyedSubscript("write"); - return writefunc.call(withArguments: [wb, writeopts]).toString(); - } + func writeBStr(bookType: String = "xlsx") throws -> String { + let XLSX: JSValue! = context.objectForKeyedSubscript("XLSX"); + context.evaluateScript(String(format: "var writeopts = {type:'binary', bookType:'%@'}", bookType)); + let writeopts: JSValue! = context.objectForKeyedSubscript("writeopts"); + let writefunc: JSValue! = XLSX.objectForKeyedSubscript("write"); + return writefunc.call(withArguments: [wb, writeopts]).toString(); + } - init(ctx: JSContext, wb: JSValue) throws { - self.context = ctx; - self.wb = wb; - self.SheetNames = wb.objectForKeyedSubscript("SheetNames"); - self.Sheets = wb.objectForKeyedSubscript("Sheets"); - } + init(ctx: JSContext, wb: JSValue) throws { + self.context = ctx; + self.wb = wb; + self.SheetNames = wb.objectForKeyedSubscript("SheetNames"); + self.Sheets = wb.objectForKeyedSubscript("Sheets"); + } } class SheetJSCore { - var context: JSContext!; - var XLSX: JSValue!; + var context: JSContext!; + var XLSX: JSValue!; - func init_context() throws -> JSContext { - var context: JSContext! - do { - context = JSContext(); - context.exceptionHandler = { ctx, X in if let e = X { print(e.toString()); }; }; - context.evaluateScript("var global = (function(){ return this; }).call(null);"); - context.evaluateScript("if(typeof wbs == 'undefined') wbs = [];"); - let src = try String(contentsOfFile: "xlsx.full.min.js"); - context.evaluateScript(src); - if context != nil { return context!; } - } catch { print(error.localizedDescription); } - throw SJSError.badJSContext; - } + func init_context() throws -> JSContext { + var context: JSContext! + do { + context = JSContext(); + context.exceptionHandler = { ctx, X in if let e = X { print(e.toString()); }; }; + context.evaluateScript("var global = (function(){ return this; }).call(null);"); + context.evaluateScript("if(typeof wbs == 'undefined') wbs = [];"); + let src = try String(contentsOfFile: "xlsx.full.min.js"); + context.evaluateScript(src); + if context != nil { return context!; } + } catch { print(error.localizedDescription); } + throw SJSError.badJSContext; + } - func version() throws -> String { - if let version = XLSX.objectForKeyedSubscript("version") { return version.toString(); } - throw SJSError.badJSContext; - } + func version() throws -> String { + if let version = XLSX.objectForKeyedSubscript("version") { return version.toString(); } + throw SJSError.badJSContext; + } - func readFile(file: String) throws -> SJSWorkbook { - let data: String! = try String(contentsOfFile: file, encoding: String.Encoding.isoLatin1); - return try readBStr(data: data); - } + func readFile(file: String) throws -> SJSWorkbook { + let data: String! = try String(contentsOfFile: file, encoding: String.Encoding.isoLatin1); + return try readBStr(data: data); + } - func readBStr(data: String) throws -> SJSWorkbook { - context.setObject(data, forKeyedSubscript: "payload" as (NSCopying & NSObjectProtocol)!); - context.evaluateScript("var wb = XLSX.read(payload, {type:'binary'});"); - let wb: JSValue! = context.objectForKeyedSubscript("wb"); - if wb == nil { throw SJSError.badJSWorkbook; } - return try SJSWorkbook(ctx: context, wb: wb); - } + func readBStr(data: String) throws -> SJSWorkbook { + context.setObject(data, forKeyedSubscript: "payload" as (NSCopying & NSObjectProtocol)!); + context.evaluateScript("var wb = XLSX.read(payload, {type:'binary'});"); + let wb: JSValue! = context.objectForKeyedSubscript("wb"); + if wb == nil { throw SJSError.badJSWorkbook; } + return try SJSWorkbook(ctx: context, wb: wb); + } - init() throws { - do { - self.context = try init_context(); - self.XLSX = self.context.objectForKeyedSubscript("XLSX"); - if self.XLSX == nil { throw SJSError.badJSContext; } - } catch { print(error.localizedDescription); } - } + init() throws { + do { + self.context = try init_context(); + self.XLSX = self.context.objectForKeyedSubscript("XLSX"); + if self.XLSX == nil { throw SJSError.badJSContext; } + } catch { print(error.localizedDescription); } + } } diff --git a/demos/altjs/SheetJSRhino.java b/demos/altjs/SheetJSRhino.java index 0439054..75bf980 100644 --- a/demos/altjs/SheetJSRhino.java +++ b/demos/altjs/SheetJSRhino.java @@ -5,27 +5,27 @@ import com.sheetjs.SheetJSFile; import com.sheetjs.SheetJSSheet; public class SheetJSRhino { - public static void main(String args[]) throws Exception { - try { - SheetJS sjs = new SheetJS(); + public static void main(String args[]) throws Exception { + try { + SheetJS sjs = new SheetJS(); - /* open file */ - SheetJSFile xl = sjs.read_file(args[0]); + /* open file */ + SheetJSFile xl = sjs.read_file(args[0]); - /* get sheetnames */ - String[] sheetnames = xl.get_sheet_names(); - System.err.println(sheetnames[0]); + /* get sheetnames */ + String[] sheetnames = xl.get_sheet_names(); + System.err.println(sheetnames[0]); - /* convert to CSV */ - SheetJSSheet sheet = xl.get_sheet(0); - String csv = sheet.get_csv(); + /* convert to CSV */ + SheetJSSheet sheet = xl.get_sheet(0); + String csv = sheet.get_csv(); - System.out.println(csv); + System.out.println(csv); - } catch(Exception e) { - throw e; - } finally { - SheetJS.close(); - } - } + } catch(Exception e) { + throw e; + } finally { + SheetJS.close(); + } + } } diff --git a/demos/altjs/com/sheetjs/JSHelper.java b/demos/altjs/com/sheetjs/JSHelper.java index 4f27126..c8dcec0 100644 --- a/demos/altjs/com/sheetjs/JSHelper.java +++ b/demos/altjs/com/sheetjs/JSHelper.java @@ -13,39 +13,39 @@ import org.mozilla.javascript.NativeObject; import org.mozilla.javascript.Scriptable; public class JSHelper { - static String read_file(String file) throws IOException { - byte[] b = Files.readAllBytes(Paths.get(file)); - System.out.println(b.length); - StringBuilder sb = new StringBuilder(); - for(int i = 0; i < b.length; ++i) sb.append(Character.toString((char)(b[i] < 0 ? b[i] + 256 : b[i]))); - return sb.toString(); - } + static String read_file(String file) throws IOException { + byte[] b = Files.readAllBytes(Paths.get(file)); + System.out.println(b.length); + StringBuilder sb = new StringBuilder(); + for(int i = 0; i < b.length; ++i) sb.append(Character.toString((char)(b[i] < 0 ? b[i] + 256 : b[i]))); + return sb.toString(); + } - static Object get_object(String path, Object base) throws ObjectNotFoundException { - int idx = path.indexOf("."); - Scriptable b = (Scriptable)base; - if(idx == -1) return b.get(path, b); - Object o = b.get(path.substring(0,idx), b); - if(o == Scriptable.NOT_FOUND) throw new ObjectNotFoundException("not found: |" + path.substring(0,idx) + "|" + Integer.toString(idx)); - return get_object(path.substring(idx+1), (NativeObject)o); - } + static Object get_object(String path, Object base) throws ObjectNotFoundException { + int idx = path.indexOf("."); + Scriptable b = (Scriptable)base; + if(idx == -1) return b.get(path, b); + Object o = b.get(path.substring(0,idx), b); + if(o == Scriptable.NOT_FOUND) throw new ObjectNotFoundException("not found: |" + path.substring(0,idx) + "|" + Integer.toString(idx)); + return get_object(path.substring(idx+1), (NativeObject)o); + } - static Object[] get_array(String path, Object base) throws ObjectNotFoundException { - NativeArray arr = (NativeArray)get_object(path, base); - Object[] out = new Object[(int)arr.getLength()]; - int idx; - for(Object o : arr.getIds()) out[idx = (Integer)o] = arr.get(idx, arr); - return out; - } + static Object[] get_array(String path, Object base) throws ObjectNotFoundException { + NativeArray arr = (NativeArray)get_object(path, base); + Object[] out = new Object[(int)arr.getLength()]; + int idx; + for(Object o : arr.getIds()) out[idx = (Integer)o] = arr.get(idx, arr); + return out; + } - static String[] get_string_array(String path, Object base) throws ObjectNotFoundException { - NativeArray arr = (NativeArray)get_object(path, base); - String[] out = new String[(int)arr.getLength()]; - int idx; - for(Object o : arr.getIds()) out[idx = (Integer)o] = arr.get(idx, arr).toString(); - return out; - } - - public static void close() { Context.exit(); } + static String[] get_string_array(String path, Object base) throws ObjectNotFoundException { + NativeArray arr = (NativeArray)get_object(path, base); + String[] out = new String[(int)arr.getLength()]; + int idx; + for(Object o : arr.getIds()) out[idx = (Integer)o] = arr.get(idx, arr).toString(); + return out; + } + + public static void close() { Context.exit(); } } diff --git a/demos/altjs/com/sheetjs/ObjectNotFoundException.java b/demos/altjs/com/sheetjs/ObjectNotFoundException.java index 7fc15c7..1116922 100644 --- a/demos/altjs/com/sheetjs/ObjectNotFoundException.java +++ b/demos/altjs/com/sheetjs/ObjectNotFoundException.java @@ -5,6 +5,6 @@ package com.sheetjs; import java.lang.Exception; public class ObjectNotFoundException extends Exception { - public ObjectNotFoundException() {} - public ObjectNotFoundException(String message) { super(message); } + public ObjectNotFoundException() {} + public ObjectNotFoundException(String message) { super(message); } } diff --git a/demos/altjs/com/sheetjs/SheetJS.java b/demos/altjs/com/sheetjs/SheetJS.java index a87a929..01def4b 100644 --- a/demos/altjs/com/sheetjs/SheetJS.java +++ b/demos/altjs/com/sheetjs/SheetJS.java @@ -12,47 +12,47 @@ import org.mozilla.javascript.NativeObject; import org.mozilla.javascript.Scriptable; public class SheetJS { - public Scriptable scope; - public Context cx; - public NativeObject nXLSX; + public Scriptable scope; + public Context cx; + public NativeObject nXLSX; - public SheetJS() throws Exception { - this.cx = Context.enter(); - this.scope = this.cx.initStandardObjects(); + public SheetJS() throws Exception { + this.cx = Context.enter(); + this.scope = this.cx.initStandardObjects(); - /* boilerplate */ - cx.setOptimizationLevel(-1); - String s = "var global = (function(){ return this; }).call(null);"; - cx.evaluateString(scope, s, "", 1, null); + /* boilerplate */ + cx.setOptimizationLevel(-1); + String s = "var global = (function(){ return this; }).call(null);"; + cx.evaluateString(scope, s, "", 1, null); - /* eval library */ - s = new Scanner(SheetJS.class.getResourceAsStream("/xlsx.full.min.js")).useDelimiter("\\Z").next(); - //s = new Scanner(new File("xlsx.full.min.js")).useDelimiter("\\Z").next(); - cx.evaluateString(scope, s, "", 1, null); + /* eval library */ + s = new Scanner(SheetJS.class.getResourceAsStream("/xlsx.full.min.js")).useDelimiter("\\Z").next(); + //s = new Scanner(new File("xlsx.full.min.js")).useDelimiter("\\Z").next(); + cx.evaluateString(scope, s, "", 1, null); - /* grab XLSX variable */ - Object XLSX = scope.get("XLSX", scope); - if(XLSX == Scriptable.NOT_FOUND) throw new Exception("XLSX not found"); - this.nXLSX = (NativeObject)XLSX; - } + /* grab XLSX variable */ + Object XLSX = scope.get("XLSX", scope); + if(XLSX == Scriptable.NOT_FOUND) throw new Exception("XLSX not found"); + this.nXLSX = (NativeObject)XLSX; + } - public SheetJSFile read_file(String filename) throws IOException, ObjectNotFoundException { - /* open file */ - String d = JSHelper.read_file(filename); + public SheetJSFile read_file(String filename) throws IOException, ObjectNotFoundException { + /* open file */ + String d = JSHelper.read_file(filename); - /* options argument */ - NativeObject q = (NativeObject)this.cx.evaluateString(this.scope, "q = {'type':'binary', 'WTF':1};", "", 2, null); + /* options argument */ + NativeObject q = (NativeObject)this.cx.evaluateString(this.scope, "q = {'type':'binary', 'WTF':1};", "", 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
+
diff --git a/demos/oldie/README.md b/demos/oldie/README.md
index 6d7d802..205517e 100644
--- a/demos/oldie/README.md
+++ b/demos/oldie/README.md
@@ -114,6 +114,8 @@ Downloadify.create(element_id, {
 });
 ```
 
+#### Upload
+
 The demo also includes an HTML file input element for updating the data table:
 
 ```js
diff --git a/demos/react/Makefile b/demos/react/Makefile
index a63d201..1cd4b95 100644
--- a/demos/react/Makefile
+++ b/demos/react/Makefile
@@ -15,7 +15,7 @@ native: ## Build react-native project
 
 .PHONY: ios
 ios: native ## react-native ios sim
-	cd SheetJS; react-native run-ios; cd -
+	cd SheetJS; react-native run-ios --simulator="iPhone X"; cd -
 
 .PHONY: android
 android: native ## react-native android sim
diff --git a/demos/react/README.md b/demos/react/README.md
index b44b12f..0246682 100644
--- a/demos/react/README.md
+++ b/demos/react/README.md
@@ -77,8 +77,7 @@ Reproducing the full project is straightforward:
 react-native init SheetJS
 cd SheetJS
 npm i -S xlsx react react-native react-native-table-component react-native-fs
-cp ../react-native.js index.ios.js
-cp ../react-native.js index.android.js
+cp ../react-native.js index.js
 react-native link
 ```
 
@@ -107,6 +106,9 @@ const wbout = XLSX.write(wb, {type:'binary', bookType:"xlsx"});
 writeFile(file, wbout, 'ascii').then((r)=>{/* :) */}).catch((e)=>{/* :( */});
 ```
 
+Note: for real app deployments, the `UIFileSharingEnabled` flag must be manually
+set in the iOS project `Info.plist` file.
+
 ## Other Demos
 
 #### Preact
diff --git a/demos/react/native.sh b/demos/react/native.sh
index b4f642a..cfa94cb 100755
--- a/demos/react/native.sh
+++ b/demos/react/native.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 # xlsx.js (C) 2013-present  SheetJS -- http://sheetjs.com */
 if [ ! -e SheetJS ]; then
-	react-native init SheetJS
+	react-native init --version="0.53.3" SheetJS
 	cd SheetJS
 	npm i -S xlsx react-native-table-component react-native-fs
 	cd -
diff --git a/demos/react/react-native.js b/demos/react/react-native.js
index dd9ec93..4d48eb6 100644
--- a/demos/react/react-native.js
+++ b/demos/react/react-native.js
@@ -2,8 +2,8 @@
 import XLSX from 'xlsx';
 
 import React, { Component } from 'react';
-import { AppRegistry, StyleSheet, Text, View, Button, Alert, Image } from 'react-native';
-import { Table, Row, Rows } from 'react-native-table-component';
+import { AppRegistry, StyleSheet, Text, View, Button, Alert, Image, ScrollView, TouchableWithoutFeedback } from 'react-native';
+import { Table, Row, Rows, TableWrapper } from 'react-native-table-component';
 
 // react-native-fs
 import { writeFile, readFile, DocumentDirectoryPath } from 'react-native-fs';
@@ -21,12 +21,14 @@ const output = str => str.split("").map(x => x.charCodeAt(0));
 */
 
 const make_cols = refstr => Array.from({length: XLSX.utils.decode_range(refstr).e.c + 1}, (x,i) => XLSX.utils.encode_col(i));
+const make_width = refstr => Array.from({length: XLSX.utils.decode_range(refstr).e.c + 1}, () => 60);
 
 export default class SheetJS extends Component {
 	constructor(props) {
 		super(props);
 		this.state = {
 			data: [[1,2,3],[4,5,6]],
+			widthArr: [60, 60, 60],
 			cols: make_cols("A1:C2")
 		};
 		this.importFile = this.importFile.bind(this);
@@ -46,7 +48,7 @@ export default class SheetJS extends Component {
 					const data = XLSX.utils.sheet_to_json(ws, {header:1});
 
 					/* update state */
-					this.setState({ data: data, cols: make_cols(ws['!ref']) });
+					this.setState({ data: data, cols: make_cols(ws['!ref']), widthArr: make_width(ws['!ref']) });
 				}).catch((err) => { Alert.alert("importFile Error", "Error " + err.message); });
 			}}
 		]);
@@ -67,7 +69,8 @@ export default class SheetJS extends Component {
 		}).catch((err) => { Alert.alert("exportFile Error", "Error " + err.message); });
 	};
 	render() { return (
-
+
+	 
 	
 	SheetJS React Native Demo
 	Import Data
@@ -76,11 +79,22 @@ export default class SheetJS extends Component {