diff --git a/bits/20_jsutils.js b/bits/20_jsutils.js index 8c58bc8..786e38b 100644 --- a/bits/20_jsutils.js +++ b/bits/20_jsutils.js @@ -159,22 +159,22 @@ function fuzzynum(s/*:string*/)/*:number*/ { } /* NOTE: Chrome rejects bare times like 1:23 PM */ -var FDRE1 = /^(0?\d|1[0-2])(?:|:([0-5]?\d)(?:|(\.\d+)(?:|:([0-5]?\d))|:([0-5]?\d)(|\.\d+)))([ap])m?/; +var FDRE1 = /^(0?\d|1[0-2])(?:|:([0-5]?\d)(?:|(\.\d+)(?:|:([0-5]?\d))|:([0-5]?\d)(|\.\d+)))\s+([ap])m?$/; function fuzzytime1(M) /*:Date*/ { - /* TODO: 1904 adjustment */ - if(!M[2]) return new Date(1900,0,0,(+M[1]%12) + (M[7] == "p" ? 12 : 0), 0, 0, 0); + /* TODO: 1904 adjustment, keep in sync with base date */ + if(!M[2]) return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), 0, 0, 0); if(M[3]) { - if(M[4]) return new Date(1900,0,0,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[4], parseFloat(M[3])*1000); - else return new Date(1900,0,0,(M[7] == "p" ? 12 : 0), +M[1], +M[2], parseFloat(M[3])*1000); + if(M[4]) return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[4], parseFloat(M[3])*1000); + else return new Date(1899,11,30,(M[7] == "p" ? 12 : 0), +M[1], +M[2], parseFloat(M[3])*1000); } - else if(M[5]) return new Date(1900, 0, 0, (+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0); - else return new Date(1900,0,0,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], 0, 0); + else if(M[5]) return new Date(1899,11,30, (+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0); + else return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], 0, 0); } var lower_months = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december']; function fuzzydate(s/*:string*/)/*:Date*/ { var lower = s.toLowerCase(); - var lnos = lower.replace(/\s+/g, ""); + var lnos = lower.replace(/\s+/g, " ").trim(); var M = lnos.match(FDRE1); if(M) return fuzzytime1(M); diff --git a/bits/40_harb.js b/bits/40_harb.js index 6b85b7e..4d12c5c 100644 --- a/bits/40_harb.js +++ b/bits/40_harb.js @@ -960,12 +960,12 @@ var PRN = /*#__PURE__*/(function() { else if(s == "TRUE") { cell.t = 'b'; cell.v = true; } else if(s == "FALSE") { cell.t = 'b'; cell.v = false; } else if(!isNaN(v = fuzzynum(s))) { cell.t = 'n'; if(o.cellText !== false) cell.w = s; cell.v = v; } - else if(!isNaN(fuzzydate(s).getDate()) || _re && s.match(_re)) { + else if(!isNaN((v = fuzzydate(s)).getDate()) || _re && s.match(_re)) { cell.z = o.dateNF || table_fmt[14]; var k = 0; - if(_re && s.match(_re)){ s=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); k=1; } - if(o.cellDates) { cell.t = 'd'; cell.v = parseDate(s, k); } - else { cell.t = 'n'; cell.v = datenum(parseDate(s, k)); } + if(_re && s.match(_re)){ s=dateNF_fix(s, o.dateNF, (s.match(_re)||[])); k=1; v = parseDate(s, k); } + if(o.cellDates) { cell.t = 'd'; cell.v = v; } + else { cell.t = 'n'; cell.v = datenum(v); } if(o.cellText !== false) cell.w = SSF_format(cell.z, cell.v instanceof Date ? datenum(cell.v):cell.v); if(!o.cellNF) delete cell.z; } else { diff --git a/demos/README.md b/demos/README.md index 7539740..c700643 100644 --- a/demos/README.md +++ b/demos/README.md @@ -18,7 +18,7 @@ can be installed with Bash on Windows or with `cygwin`. ### Included Demos **JavaScript APIs** -- [`XMLHttpRequest and fetch`](xhr/) +- [`XMLHttpRequest and fetch`](https://docs.sheetjs.com/docs/getting-started/demos/network) - [`Clipboard Data`](https://docs.sheetjs.com/docs/getting-started/demos/clipboard) - [`Typed Arrays for Machine Learning`](https://docs.sheetjs.com/docs/getting-started/demos/ml) - [`LocalStorage and SessionStorage`](https://docs.sheetjs.com/docs/getting-started/demos/database#localstorage-and-sessionstorage) @@ -29,7 +29,6 @@ can be installed with Bash on Windows or with `cygwin`. - [`Angular.JS`](https://docs.sheetjs.com/docs/getting-started/demos/legacy#angularjs) - [`Angular 2+ and Ionic`](angular2/) - [`Knockout`](https://docs.sheetjs.com/docs/getting-started/demos/legacy#knockoutjs) -- [`Meteor`](meteor/) - [`React, React Native and NextJS`](react/) - [`VueJS, WeeX and NuxtJS`](vue/) @@ -43,8 +42,7 @@ can be installed with Bash on Windows or with `cygwin`. **Platforms and Integrations** - [`Command-Line Tools`](https://docs.sheetjs.com/docs/getting-started/demos/cli) - [`NodeJS Server-Side Processing`](server/) -- [`Deno`](deno/) -- [`Electron`](electron/) +- [`Electron`](https://docs.sheetjs.com/docs/getting-started/demos/desktop#electron) - [`NW.js`](https://docs.sheetjs.com/docs/getting-started/demos/desktop#nwjs) - [`Chrome / Chromium Extension`](https://docs.sheetjs.com/docs/getting-started/demos/chromium) - [`Google Sheets API`](https://docs.sheetjs.com/docs/getting-started/demos/gsheet) @@ -68,7 +66,7 @@ can be installed with Bash on Windows or with `cygwin`. - [`rollup`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#rollup) - [`snowpack`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#snowpack) - [`swc`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#swc) -- [`systemjs`](systemjs/) +- [`systemjs`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#systemjs) - [`vite`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#vite) - [`webpack 2.x`](webpack/) - [`wmr`](https://docs.sheetjs.com/docs/getting-started/demos/bundler#wmr) diff --git a/demos/electron/Makefile b/demos/electron/Makefile deleted file mode 100644 index ea5d241..0000000 --- a/demos/electron/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -.PHONY: init -init: - mkdir -p node_modules - cd node_modules; if [ ! -e xlsx ]; then ln -s ../../../ xlsx ; fi; cd - - -.PHONY: lint -lint: - eslint *.js -.PHONY: run -run: - npm i - npx electron . -.PHONY: build -build: - npm run make diff --git a/demos/electron/README.md b/demos/electron/README.md index 0947ecd..95ad5dc 100644 --- a/demos/electron/README.md +++ b/demos/electron/README.md @@ -1,56 +1,6 @@ # Electron -This library is compatible with Electron and should just work out of the box. -The demonstration uses Electron 18.2.0. The library is added via `require` from -the renderer process. - -The library can also be required from the main process, as shown in this demo -to render a version string in the About dialog on OSX. - -The standard HTML5 `FileReader` techniques from the browser apply to Electron. -This demo includes a drag-and-drop box as well as a file input box, mirroring -the [SheetJS Data Preview Live Demo](http://oss.sheetjs.com/sheetjs/) - -The core data in this demo is an editable HTML table. The readers build up the -table using `sheet_to_html` (with `editable:true` option) and the writers scrape -the table using `table_to_book`. - -The demo project is structured for `electron-forge`: -- `npm start` will start the app. -- `npm run make` will build a standalone app. - -The standalone app was tested on an Intel Mac (`darwin-x64`). - -## Reading and Writing Files - -Since electron provides an `fs` implementation, `readFile` and `writeFile` can -be used in conjunction with the standard dialog windows. For example: - -```js -/* from app code, require('electron').remote calls back to main process */ -var dialog = require('electron').remote.dialog; - -/* show a file-open dialog and read the first selected file */ -var o = dialog.showOpenDialog({ properties: ['openFile'] }); -var workbook = XLSX.readFile(o[0]); - -/* show a file-save dialog and write the workbook */ -var o = dialog.showSaveDialog(); -XLSX.writeFile(workbook, o); -``` - -## Breaking Changes in Electron - -The first version of this demo used Electron 1.7.5. - -Electron 9.0.0 and later require the preference `nodeIntegration: true` in order -to `require('XLSX')` in the renderer process. - -Electron 12.0.0 and later also require `worldSafeExecuteJavascript: true` and -`contextIsolation: true`. - -Electron 14+ must use `@electron/remote` instead of `remote`. - - +[The new demo](https://docs.sheetjs.com/docs/getting-started/demos/desktop#electron) +includes an improved example and detailed explanations. [![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx) diff --git a/demos/electron/index.html b/demos/electron/index.html deleted file mode 100644 index c8ef088..0000000 --- a/demos/electron/index.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - -
- - --SheetJS Electron Demo - -Source Code Repo -Issues? Something look weird? Click here and report an issue -- - -
-
-Drop a spreadsheet file here to see sheet data- ... or click here to select a file - -
-SheetJS Meteor Demo - -{{> sheetjs}} - -- - - - - - - diff --git a/demos/meteor/client/main.js b/demos/meteor/client/main.js deleted file mode 100644 index ac5adfc..0000000 --- a/demos/meteor/client/main.js +++ /dev/null @@ -1,39 +0,0 @@ -/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */ -import XLSX from 'xlsx'; - -import { Meteor } from 'meteor/meteor'; -import { Template } from 'meteor/templating'; - -import './main.html'; - -Template.sheetjs.events({ - 'change input' (event) { - /* "Browser file upload form element" from SheetJS README */ - const file = event.currentTarget.files[0]; - const reader = new FileReader(); - reader.onload = function(e) { - const data = e.target.result; - const name = file.name; - /* Meteor magic */ - Meteor.call('uploadU', new Uint8Array(data), name, function(err, wb) { - if (err) throw err; - /* load the first worksheet */ - const ws = wb.Sheets[wb.SheetNames[0]]; - /* generate HTML table and enable export */ - const html = XLSX.utils.sheet_to_html(ws, { editable: true }); - document.getElementById('out').innerHTML = html; - document.getElementById('dnload').disabled = false; - }); - }; - reader.readAsArrayBuffer(file); - }, - 'click button' () { - const html = document.getElementById('out').innerHTML; - Meteor.call('download', html, function(err, wb) { - if (err) throw err; - /* "Browser download file" from SheetJS README */ - XLSX.writeFile(wb, 'sheetjs.xlsx'); - }); - }, -}); - diff --git a/demos/meteor/package.json b/demos/meteor/package.json deleted file mode 100644 index 0cc1a39..0000000 --- a/demos/meteor/package.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "meteor-xlsx", - "version": "0.0.0", - "private": true, - "scripts": { - "lint": "eslint .", - "start": "meteor run" - }, - "eslintConfig": { - "extends": "@meteorjs/eslint-config-meteor" - }, - "dependencies": { - "babel-runtime": "^6.20.0", - "meteor-node-stubs": "~0.2.4" - }, - "devDependencies": { - "@meteorjs/eslint-config-meteor": "^1.0.5", - "babel-eslint": "^7.2.3", - "eslint": "^3.19.0", - "eslint-config-airbnb": "^13.0.0", - "eslint-import-resolver-meteor": "^0.3.4", - "eslint-plugin-import": "^2.7.0", - "eslint-plugin-jsx-a11y": "^2.2.3", - "eslint-plugin-meteor": "^4.1.4", - "eslint-plugin-react": "^6.10.3" - } -} diff --git a/demos/meteor/server/main.js b/demos/meteor/server/main.js deleted file mode 100644 index da4ab43..0000000 --- a/demos/meteor/server/main.js +++ /dev/null @@ -1,30 +0,0 @@ -/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */ -import { Meteor } from 'meteor/meteor'; -import { check } from 'meteor/check'; -import XLSX from 'xlsx'; - -Meteor.methods({ - /* read the data and return the workbook object to the frontend */ - uploadU: (ab, name) => { - check(ab, Uint8Array); - check(name, String); - return XLSX.read(ab, { type: 'array' }); - }, - download: (html) => { - check(html, String); - let wb; - if (html.length > 3) { - /* parse workbook if html is available */ - wb = XLSX.read(html, { type: 'binary' }); - } else { - /* generate a workbook object otherwise */ - const data = [['a', 'b', 'c'], [1, 2, 3]]; - const ws = XLSX.utils.aoa_to_sheet(data); - wb = XLSX.utils.book_new(); - XLSX.utils.book_append_sheet(wb, ws, 'SheetJS'); - } - return wb; - }, -}); - -Meteor.startup(() => { }); diff --git a/demos/systemjs/Makefile b/demos/systemjs/Makefile deleted file mode 100644 index 5ca2648..0000000 --- a/demos/systemjs/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -.PHONY: test ctest -test: - cp ../../dist/xlsx.full.min.js . - node test.node.js - -ctest: - python -mSimpleHTTPServer diff --git a/demos/systemjs/README.md b/demos/systemjs/README.md index 12c69fc..eceb198 100644 --- a/demos/systemjs/README.md +++ b/demos/systemjs/README.md @@ -1,89 +1,6 @@ # SystemJS Demos -SystemJS supports both browser and nodejs deployments. It does not recognize -browser environments and automatically suppress node core modules, but with some -configuration magic SystemJS can load the library. - -## Browser - -SystemJS fails by default because the library does not export anything in the -web browser. The `meta` configuration option can be used to expose `XLSX`: - -```js -SystemJS.config({ - meta: { - 'xlsx': { - exports: 'XLSX' // <-- tell SystemJS to expose the XLSX variable - } - }, - map: { - 'xlsx': 'xlsx.full.min.js', // <-- make sure xlsx.full.min.js is in same dir - 'fs': '', // <--| - 'crypto': '', // <--| suppress native node modules - 'stream': '' // <--| - } -}); -SystemJS.import('main.js') -``` - -With the new configuration, `require('xlsx')` will load the library: - -```js -var XLSX = require('xlsx'); -var w = XLSX.read('abc,def\nghi,jkl', {type:'binary'}); -var j = XLSX.utils.sheet_to_json(w.Sheets[w.SheetNames[0]], {header:1}); -console.log(j); -``` - -Note: The `readFile` and `writeFile` functions are not available in the browser. - -## Web Workers - -Web Workers can load the SystemJS library with `importScripts`, but the imported -code cannot assign the original worker's `onmessage` callback. This demo works -around the limitation by exposing the desired function as a global: - -```js -/* main worker script */ -importScripts('system.js'); - -SystemJS.config({ /* ... browser config ... */ }); - -onmessage = function(evt) { - SystemJS.import('xlsxworker.js').then(function() { _cb(evt); }); -}; - -/* xlsxworker.js */ -var XLSX = require('xlsx'); - -_cb = function(evt) { /* ... do work here ... */ }; -``` - -## Node - -The node core modules should be mapped to their `@node` equivalents: - -```js -var SystemJS = require('systemjs'); -SystemJS.config({ - map: { - 'xlsx': 'node_modules/xlsx/xlsx.js', - 'fs': '@node/fs', - 'crypto': '@node/crypto', - 'stream': '@node/stream' - } -}); -``` - -And use is pretty straightforward: - -```js -SystemJS.import('xlsx').then(function(XLSX) { - /* XLSX is available here */ - var w = XLSX.readFile('test.xlsx'); - var j = XLSX.utils.sheet_to_json(w.Sheets[w.SheetNames[0]], {header:1}); - console.log(j); -}); -``` +[The new demo](https://docs.sheetjs.com/docs/getting-started/demos/bundler#systemjs) +includes a live example and improved explanations. [![Analytics](https://ga-beacon.appspot.com/UA-36810333-1/SheetJS/js-xlsx?pixel)](https://github.com/SheetJS/js-xlsx) diff --git a/demos/systemjs/app.node.js b/demos/systemjs/app.node.js deleted file mode 100644 index db2a0ef..0000000 --- a/demos/systemjs/app.node.js +++ /dev/null @@ -1,5 +0,0 @@ -/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */ -var XLSX_1 = require('../../xlsx.js'); -var XLSX_2 = require('../../dist/xlsx.core.min.js'); -var XLSX_3 = require('../../dist/xlsx.full.min.js'); -var XLSX_N = require('xlsx'); diff --git a/demos/systemjs/main.js b/demos/systemjs/main.js deleted file mode 100644 index c29c394..0000000 --- a/demos/systemjs/main.js +++ /dev/null @@ -1,129 +0,0 @@ -/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */ -/*jshint browser:true */ -/*global XLSX */ -var XLSX = require('xlsx'); - -var global_wb; - -var process_wb = (function() { - var OUT = document.getElementById('out'); - var HTMLOUT = document.getElementById('htmlout'); - - var get_format = (function() { - var radios = document.getElementsByName( "format" ); - return function() { - for(var i = 0; i < radios.length; ++i) if(radios[i].checked || radios.length === 1) return radios[i].value; - }; - })(); - - var to_json = function to_json(workbook) { - var result = {}; - workbook.SheetNames.forEach(function(sheetName) { - var roa = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName]); - if(roa.length) result[sheetName] = roa; - }); - return JSON.stringify(result, 2, 2); - }; - - var to_csv = function to_csv(workbook) { - var result = []; - workbook.SheetNames.forEach(function(sheetName) { - var csv = XLSX.utils.sheet_to_csv(workbook.Sheets[sheetName]); - if(csv.length){ - result.push("SHEET: " + sheetName); - result.push(""); - result.push(csv); - } - }); - return result.join("\n"); - }; - - var to_fmla = function to_fmla(workbook) { - var result = []; - workbook.SheetNames.forEach(function(sheetName) { - var formulae = XLSX.utils.get_formulae(workbook.Sheets[sheetName]); - if(formulae.length){ - result.push("SHEET: " + sheetName); - result.push(""); - result.push(formulae.join("\n")); - } - }); - return result.join("\n"); - }; - - var to_html = function to_html(workbook) { - HTMLOUT.innerHTML = ""; - workbook.SheetNames.forEach(function(sheetName) { - var htmlstr = XLSX.write(workbook, {sheet:sheetName, type:'string', bookType:'html'}); - HTMLOUT.innerHTML += htmlstr; - }); - return ""; - }; - - return function process_wb(wb) { - global_wb = wb; - var output = ""; - switch(get_format()) { - case "form": output = to_fmla(wb); break; - case "html": output = to_html(wb); break; - case "json": output = to_json(wb); break; - default: output = to_csv(wb); - } - if(OUT.innerText === undefined) OUT.textContent = output; - else OUT.innerText = output; - if(typeof console !== 'undefined') console.log("output", new Date()); - }; -})(); - -var setfmt = window.setfmt = function setfmt() { if(global_wb) process_wb(global_wb); }; - -var b64it = window.b64it = (function() { - var tarea = document.getElementById('b64data'); - return function b64it() { - if(typeof console !== 'undefined') console.log("onload", new Date()); - var wb = XLSX.read(tarea.value, {type:'base64', WTF:false}); - process_wb(wb); - }; -})(); - -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); -})(); diff --git a/demos/systemjs/main.simple.js b/demos/systemjs/main.simple.js deleted file mode 100644 index a21d1a4..0000000 --- a/demos/systemjs/main.simple.js +++ /dev/null @@ -1,6 +0,0 @@ -/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */ -var XLSX = require('xlsx'); -console.log(XLSX.version); -var w = XLSX.read('abc,def\nghi,jkl', {type:'binary'}); -var j = XLSX.utils.sheet_to_json(w.Sheets[w.SheetNames[0]], {header:1}); -console.log(j); diff --git a/demos/systemjs/simple.html b/demos/systemjs/simple.html deleted file mode 100644 index 2a034de..0000000 --- a/demos/systemjs/simple.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - -
-SheetJS SystemJS Demo - -Source Code Repo -Issues? Something look weird? Click here and report an issue - -Original script: main.simple.js - -Console Output: -- - - - - - - diff --git a/demos/systemjs/systemjs.html b/demos/systemjs/systemjs.html deleted file mode 100644 index 131032b..0000000 --- a/demos/systemjs/systemjs.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - - - -
-SheetJS Data Preview Live Demo -(Base64 text works back to IE6; drag and drop works back to IE10) - -Source Code Repo -Issues? Something look weird? Click here and report an issue -Output Format:- - -
-Drop a spreadsheet file here to see sheet data- ... or click here to select a file - - -
-Advanced Demo Options: -
-SheetJS Data Preview Live Demo - -Source Code Repo -Issues? Something look weird? Click here and report an issue -- -
-
- -- - - - - - diff --git a/demos/xhr/fetch.html b/demos/xhr/fetch.html deleted file mode 100644 index d7da261..0000000 --- a/demos/xhr/fetch.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - -
-SheetJS Data Preview Live Demo - -Source Code Repo -Issues? Something look weird? Click here and report an issue -- -
-
- -- - - - - diff --git a/demos/xhr/package.json b/demos/xhr/package.json deleted file mode 100644 index 749e533..0000000 --- a/demos/xhr/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "sheetjs-xhr-demo", - "author": "sheetjs", - "version": "0.72.62", - "dependencies": { - "printj": "1.1.0", - "express": "4.15.4", - "express-formidable": "1.0.0", - "serve-index": "1.9.0" - }, - "scripts": { - "start": "node server.js 7262" - } -} diff --git a/demos/xhr/server.js b/demos/xhr/server.js deleted file mode 100644 index 464bb3c..0000000 --- a/demos/xhr/server.js +++ /dev/null @@ -1,38 +0,0 @@ -#!/usr/bin/env node -/* xlsx.js (C) 2013-present SheetJS -- http://sheetjs.com */ - -var fs = require('fs'), path = require('path'); -var express = require('express'), app = express(); -var sprintf = require('printj').sprintf; - -function logit(req, res, next) { - console.log(sprintf("%s %s %d", req.method, req.url, res.statusCode)); - next(); -} -function cors(req, res, next) { - if(!res.headersSent) res.header('Access-Control-Allow-Origin', '*'); - next(); -} - -var port = +process.argv[2] || +process.env.PORT || 7262; -var basepath = process.cwd(); - -var dir = path.join(__dirname, "files"); -try { fs.mkdirSync(dir); } catch(e) {} - -app.use(logit); -app.use(cors); -app.use(require('express-formidable')({uploadDir: dir})); -app.post('/upload', function(req, res) { - console.log(req.files); - var f = req.files[Object.keys(req.files)[0]]; - var newpath = path.join(dir, f.name); - fs.renameSync(f.path, newpath); - console.log("moved " + f.path + " to " + newpath); - res.end("wrote to " + f.name); -}); -app.use(express.static(path.resolve(basepath))); -app.use(require('serve-index')(basepath, {'icons':true})); - -app.listen(port, function() { console.log('Serving HTTP on port ' + port); }); - diff --git a/demos/xhr/superagent.html b/demos/xhr/superagent.html deleted file mode 100644 index 10893e8..0000000 --- a/demos/xhr/superagent.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - -
-SheetJS Data Preview Live Demo - -Source Code Repo -Issues? Something look weird? Click here and report an issue -- -
-
- -- - - - - - diff --git a/demos/xhr/xhr.html b/demos/xhr/xhr.html deleted file mode 100644 index 48e5bfc..0000000 --- a/demos/xhr/xhr.html +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - -
-SheetJS Data Preview Live Demo - -Source Code Repo -Issues? Something look weird? Click here and report an issue -- -
-
- -- - - - - diff --git a/demos/xhr/xlsx.full.min.js b/demos/xhr/xlsx.full.min.js deleted file mode 120000 index dbca48d..0000000 --- a/demos/xhr/xlsx.full.min.js +++ /dev/null @@ -1 +0,0 @@ -../../dist/xlsx.full.min.js \ No newline at end of file diff --git a/packages/s2c/README.md b/packages/s2c/README.md new file mode 100644 index 0000000..70acdf4 --- /dev/null +++ b/packages/s2c/README.md @@ -0,0 +1,11 @@ +# s2c + +`mod.ts` exports the following methods: + +- `parse_book_from_request` reads a field from a request, parses the field with + the Drash body parser, and returns a SheetJS workbook object. This does not + use the filesystem, so it supports Deno Deploy and other restricted services. + +`s2c.ts` is the script that powers
+ +Library Version: ${version} + + +`, + ); + } +} + +// Create and run your server +const server = new Drash.Server({ + hostname: "", + port: 3000, + protocol: "http", + resources: [ + S2CResource, + ], +}); + +server.run(); + +console.log(`Server running at ${server.address}.`); diff --git a/packages/s2c/test.ts b/packages/s2c/test.ts new file mode 100644 index 0000000..a4c78e6 --- /dev/null +++ b/packages/s2c/test.ts @@ -0,0 +1,74 @@ +// @deno-types="https://cdn.sheetjs.com/xlsx-latest/package/types/index.d.ts" +import { utils, set_cptable, version } from 'https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs'; +import { parse_book_from_request } from "./mod.ts"; +import * as Drash from "https://deno.land/x/drash@v2.5.4/mod.ts"; + +class S2CResource extends Drash.Resource { + public paths = ["/"]; + + // see https://github.com/drashland/drash/issues/194 + public OPTIONS(request: Drash.Request, response: Drash.Response) { + const allHttpMethods: string[] = [ "GET", "POST", "PUT", "DELETE" ]; + response.headers.set("Allow", allHttpMethods.join()); // Use this + response.headers.set("Access-Control-Allow-Methods", allHttpMethods.join()); // or this + response.headers.set("access-control-allow-origin", "*"); + response.status_code = 204; + return response; + } + + public POST(request: Drash.Request, response: Drash.Response) { + try { response.headers.set("access-control-allow-origin", "*"); } catch(e) {} + var wb = parse_book_from_request(request, "file"); + return response.html( utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]])); + } + + public GET(request: Drash.Request, response: Drash.Response): void { + try { response.headers.set("access-control-allow-origin", "*"); } catch(e) {} + return response.html(`\ + + + +SheetJS Spreadsheet Conversion Service
+API + +Send a POST request to https://s2c.deno.dev/ with the file in the "file" body parameter: + +$ curl -X POST -F"file=@test.xlsx" https://s2c.deno.dev/ + +The response will be an HTML TABLE generated from the first worksheet. + +Try it out!
+ +Library Version: ${version} + + +`, + ); + } +} + +// Create and run your server +const server = new Drash.Server({ + hostname: "", + port: 3000, + protocol: "http", + resources: [ + S2CResource, + ], +}); + +server.run(); + +console.log(`Server running at ${server.address}.`); + diff --git a/test.js b/test.js index a76eccf..1c25e3e 100644 --- a/test.js +++ b/test.js @@ -2197,6 +2197,30 @@ describe('CSV', function() { assert.equal(get_cell(ws, "B2").v, "j" + m[1] + "l"); }); }); + it('should parse date-less meridien time values', function() { + var aoa = [ + ["3a", "3 a", "3 a-1"], + ["3b", "3 b", "3 b-1"], + ["3p", "3 P", "3 p-1"], + ] + var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true}).Sheets.Sheet1; + for(var R = 0; R < 3; ++R) { + assert.equal(get_cell(ws, "A" + (R+1)).v, aoa[R][0]); + assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]); + } + assert.equal(get_cell(ws, "B2").v, "3 b"); + var B1 = get_cell(ws, "B1"); console.log(B1); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3); + var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "d"); assert.equal(B3.v.getHours(), 15); + ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: false}).Sheets.Sheet1; + for(var R = 0; R < 3; ++R) { + assert.equal(get_cell(ws, "A" + (R+1)).v, aoa[R][0]); + assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]); + } + assert.equal(get_cell(ws, "B2").v, "3 b"); + var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "n"); assert.equal(B1.v * 24, 3); + var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "n"); assert.equal(B3.v * 24, 15); + + }); }); describe('output', function(){ var data, ws; diff --git a/test.mjs b/test.mjs index b85edd5..1e7e914 100644 --- a/test.mjs +++ b/test.mjs @@ -2183,6 +2183,30 @@ describe('CSV', function() { assert.equal(get_cell(ws, "B2").v, "j" + m[1] + "l"); }); }); + it('should parse date-less meridien time values', function() { + var aoa = [ + ["3a", "3 a", "3 a-1"], + ["3b", "3 b", "3 b-1"], + ["3p", "3 P", "3 p-1"], + ] + var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true}).Sheets.Sheet1; + for(var R = 0; R < 3; ++R) { + assert.equal(get_cell(ws, "A" + (R+1)).v, aoa[R][0]); + assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]); + } + assert.equal(get_cell(ws, "B2").v, "3 b"); + var B1 = get_cell(ws, "B1"); console.log(B1); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3); + var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "d"); assert.equal(B3.v.getHours(), 15); + ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: false}).Sheets.Sheet1; + for(var R = 0; R < 3; ++R) { + assert.equal(get_cell(ws, "A" + (R+1)).v, aoa[R][0]); + assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]); + } + assert.equal(get_cell(ws, "B2").v, "3 b"); + var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "n"); assert.equal(B1.v * 24, 3); + var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "n"); assert.equal(B3.v * 24, 15); + + }); }); describe('output', function(){ var data, ws; diff --git a/test.mts b/test.mts index ee6731e..1f25456 100644 --- a/test.mts +++ b/test.mts @@ -2139,6 +2139,30 @@ describe('CSV', function() { assert.equal(get_cell(ws, "B2").v, "j" + m[1] + "l"); }); }); + it('should parse date-less meridien time values', function() { + var aoa = [ + ["3a", "3 a", "3 a-1"], + ["3b", "3 b", "3 b-1"], + ["3p", "3 P", "3 p-1"], + ] + var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true}).Sheets.Sheet1; + for(var R = 0; R < 3; ++R) { + assert.equal(get_cell(ws, "A" + (R+1)).v, aoa[R][0]); + assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]); + } + assert.equal(get_cell(ws, "B2").v, "3 b"); + var B1 = get_cell(ws, "B1"); console.log(B1); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3); + var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "d"); assert.equal(B3.v.getHours(), 15); + ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: false}).Sheets.Sheet1; + for(var R = 0; R < 3; ++R) { + assert.equal(get_cell(ws, "A" + (R+1)).v, aoa[R][0]); + assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]); + } + assert.equal(get_cell(ws, "B2").v, "3 b"); + var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "n"); assert.equal(B1.v * 24, 3); + var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "n"); assert.equal(B3.v * 24, 15); + + }); }); describe('output', function(){ var data = [ diff --git a/test.ts b/test.ts index ea02f33..0d8de53 100644 --- a/test.ts +++ b/test.ts @@ -2139,6 +2139,30 @@ Deno.test('CSV', async function(t) { assert.equal(get_cell(ws, "B2").v, "j" + m[1] + "l"); }); }); + await t.step('should parse date-less meridien time values', async function(t) { + var aoa = [ + ["3a", "3 a", "3 a-1"], + ["3b", "3 b", "3 b-1"], + ["3p", "3 P", "3 p-1"], + ] + var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true}).Sheets.Sheet1; + for(var R = 0; R < 3; ++R) { + assert.equal(get_cell(ws, "A" + (R+1)).v, aoa[R][0]); + assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]); + } + assert.equal(get_cell(ws, "B2").v, "3 b"); + var B1 = get_cell(ws, "B1"); console.log(B1); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3); + var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "d"); assert.equal(B3.v.getHours(), 15); + ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: false}).Sheets.Sheet1; + for(var R = 0; R < 3; ++R) { + assert.equal(get_cell(ws, "A" + (R+1)).v, aoa[R][0]); + assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]); + } + assert.equal(get_cell(ws, "B2").v, "3 b"); + var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "n"); assert.equal(B1.v * 24, 3); + var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "n"); assert.equal(B3.v * 24, 15); + + }); }); await t.step('output', async function(t){ var data = [ diff --git a/testnocp.ts b/testnocp.ts index 5d207cc..f8b155d 100644 --- a/testnocp.ts +++ b/testnocp.ts @@ -2138,6 +2138,30 @@ Deno.test('CSV', async function(t) { assert.equal(get_cell(ws, "B2").v, "j" + m[1] + "l"); }); }); + await t.step('should parse date-less meridien time values', async function(t) { + var aoa = [ + ["3a", "3 a", "3 a-1"], + ["3b", "3 b", "3 b-1"], + ["3p", "3 P", "3 p-1"], + ] + var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true}).Sheets.Sheet1; + for(var R = 0; R < 3; ++R) { + assert.equal(get_cell(ws, "A" + (R+1)).v, aoa[R][0]); + assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]); + } + assert.equal(get_cell(ws, "B2").v, "3 b"); + var B1 = get_cell(ws, "B1"); console.log(B1); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3); + var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "d"); assert.equal(B3.v.getHours(), 15); + ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: false}).Sheets.Sheet1; + for(var R = 0; R < 3; ++R) { + assert.equal(get_cell(ws, "A" + (R+1)).v, aoa[R][0]); + assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]); + } + assert.equal(get_cell(ws, "B2").v, "3 b"); + var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "n"); assert.equal(B1.v * 24, 3); + var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "n"); assert.equal(B3.v * 24, 15); + + }); }); await t.step('output', async function(t){ var data = [ diff --git a/tests/core.js b/tests/core.js index 4fefe5e..c697cc8 100644 --- a/tests/core.js +++ b/tests/core.js @@ -2196,6 +2196,30 @@ describe('CSV', function() { assert.equal(get_cell(ws, "B2").v, "j" + m[1] + "l"); }); }); + it('should parse date-less meridien time values', function() { + var aoa = [ + ["3a", "3 a", "3 a-1"], + ["3b", "3 b", "3 b-1"], + ["3p", "3 P", "3 p-1"], + ] + var ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: true}).Sheets.Sheet1; + for(var R = 0; R < 3; ++R) { + assert.equal(get_cell(ws, "A" + (R+1)).v, aoa[R][0]); + assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]); + } + assert.equal(get_cell(ws, "B2").v, "3 b"); + var B1 = get_cell(ws, "B1"); console.log(B1); assert.equal(B1.t, "d"); assert.equal(B1.v.getHours(), 3); + var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "d"); assert.equal(B3.v.getHours(), 15); + ws = X.read(aoa.map(function(row) { return row.join(","); }).join("\n"), {type: "string", cellDates: false}).Sheets.Sheet1; + for(var R = 0; R < 3; ++R) { + assert.equal(get_cell(ws, "A" + (R+1)).v, aoa[R][0]); + assert.equal(get_cell(ws, "C" + (R+1)).v, aoa[R][2]); + } + assert.equal(get_cell(ws, "B2").v, "3 b"); + var B1 = get_cell(ws, "B1"); assert.equal(B1.t, "n"); assert.equal(B1.v * 24, 3); + var B3 = get_cell(ws, "B3"); assert.equal(B3.t, "n"); assert.equal(B3.v * 24, 15); + + }); }); describe('output', function(){ var data, ws; diff --git a/xlsx.flow.js b/xlsx.flow.js index 5f70776..9f9aef5 100644 --- a/xlsx.flow.js +++ b/xlsx.flow.js @@ -3447,22 +3447,22 @@ function fuzzynum(s/*:string*/)/*:number*/ { } /* NOTE: Chrome rejects bare times like 1:23 PM */ -var FDRE1 = /^(0?\d|1[0-2])(?:|:([0-5]?\d)(?:|(\.\d+)(?:|:([0-5]?\d))|:([0-5]?\d)(|\.\d+)))([ap])m?/; +var FDRE1 = /^(0?\d|1[0-2])(?:|:([0-5]?\d)(?:|(\.\d+)(?:|:([0-5]?\d))|:([0-5]?\d)(|\.\d+)))\s+([ap])m?$/; function fuzzytime1(M) /*:Date*/ { - /* TODO: 1904 adjustment */ - if(!M[2]) return new Date(1900,0,0,(+M[1]%12) + (M[7] == "p" ? 12 : 0), 0, 0, 0); + /* TODO: 1904 adjustment, keep in sync with base date */ + if(!M[2]) return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), 0, 0, 0); if(M[3]) { - if(M[4]) return new Date(1900,0,0,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[4], parseFloat(M[3])*1000); - else return new Date(1900,0,0,(M[7] == "p" ? 12 : 0), +M[1], +M[2], parseFloat(M[3])*1000); + if(M[4]) return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[4], parseFloat(M[3])*1000); + else return new Date(1899,11,30,(M[7] == "p" ? 12 : 0), +M[1], +M[2], parseFloat(M[3])*1000); } - else if(M[5]) return new Date(1900, 0, 0, (+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0); - else return new Date(1900,0,0,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], 0, 0); + else if(M[5]) return new Date(1899,11,30, (+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], +M[5], M[6] ? parseFloat(M[6]) * 1000 : 0); + else return new Date(1899,11,30,(+M[1]%12) + (M[7] == "p" ? 12 : 0), +M[2], 0, 0); } var lower_months = ['january', 'february', 'march', 'april', 'may', 'june', 'july', 'august', 'september', 'october', 'november', 'december']; function fuzzydate(s/*:string*/)/*:Date*/ { var lower = s.toLowerCase(); - var lnos = lower.replace(/\s+/g, ""); + var lnos = lower.replace(/\s+/g, " ").trim(); var M = lnos.match(FDRE1); if(M) return fuzzytime1(M); @@ -8064,6 +8064,8 @@ var SYLK = /*#__PURE__*/(function() { } wb.Workbook.Names.push(nn); } break; + // case 'NE': // ?? + // case 'NU': // ?? case 'C': /* cell */ var C_seen_K = false, C_seen_X = false, C_seen_S = false, C_seen_E = false, _R = -1, _C = -1, formula = "", cell_t = "z"; for(rj=1; rjSheetJS Spreadsheet Conversion Service
+API + +Send a POST request to https://s2c.deno.dev/ with the file in the "file" body parameter: + +$ curl -X POST -F"file=@test.xlsx" https://s2c.deno.dev/ + +The response will be an HTML TABLE generated from the first worksheet. + +Try it out!