提交 c3c0bc52 编写于 作者: S SheetJS

version bump 0.10.1: json_to_sheet, misc fmts

- SYLK auto fail into DSV on bad header (fixes #651 h/t @mmancosu)
- CSV automatically wrap `ID` in quotes
- json_to_sheet (see issue #610)
上级 7b4bafba
......@@ -98,6 +98,7 @@ enhancements, additional features by request, and dedicated support.
* [Output Type](#output-type)
- [Utility Functions](#utility-functions)
* [Array of Arrays Input](#array-of-arrays-input)
* [Array of Objects Input](#array-of-objects-input)
* [HTML Table Input](#html-table-input)
* [Formulae Output](#formulae-output)
* [Delimiter-Separated Output](#delimiter-separated-output)
......@@ -553,6 +554,7 @@ Utilities are available in the `XLSX.utils` object:
**Importing:**
- `aoa_to_sheet` converts an array of arrays of JS data to a worksheet.
- `json_to_sheet` converts an array of JS objects to a worksheet.
**Exporting:**
......@@ -560,7 +562,7 @@ Utilities are available in the `XLSX.utils` object:
- `sheet_to_csv` generates delimiter-separated-values output.
- `sheet_to_formulae` generates a list of the formulae (with value fallbacks).
Exporters are described in the [Utility Functions](#utility-functions) section.
These utilities are described in [Utility Functions](#utility-functions) below.
**Cell and cell address manipulation:**
......@@ -1394,6 +1396,25 @@ var ws = XLSX.utils.aoa_to_sheet([
```
</details>
### Array of Objects Input
`XLSX.utils.json_to_sheet` takes an array of objects and returns a worksheet
with automatically-generated "headers" based on the keys of the objects.
<details>
<summary><b>Examples</b> (click to show)</summary>
The original sheet cannot be reproduced because JS object keys must be unique.
After replacing the second `e` and `S` with `e_1` and `S_1`:
```js
var ws = XLSX.utils.json_to_sheet([
{S:1,h:2,e:3,e_1:4,t:5,J:6,S_1:7},
{S:2,h:3,e:4,e_1:5,t:6,J:7,S_1:8}
]);
```
</details>
### HTML Table Input
`XLSX.utils.table_to_sheet` takes a table DOM element and returns a worksheet
......
XLSX.version = '0.10.0';
XLSX.version = '0.10.1';
......@@ -599,3 +599,17 @@ var PRN = (function() {
};
})();
/* Excel defaults to SYLK but warns if data is not valid */
function read_wb_ID(d, opts) {
var o = opts || {}, OLD_WTF = !!o.WTF; o.WTF = true;
try {
var out = SYLK.to_workbook(d, o);
o.WTF = OLD_WTF;
return out;
} catch(e) {
o.WTF = OLD_WTF;
if(!e.message.match(/SYLK bad record ID/) && OLD_WTF) throw e;
return PRN.to_workbook(d, opts);
}
}
......@@ -49,7 +49,7 @@ function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
case 0xD0: return read_cfb(CFB.read(d, o), o);
case 0x09: return parse_xlscfb(s2a(o.type === 'base64' ? Base64.decode(d) : d), o);
case 0x3C: return parse_xlml(d, o);
case 0x49: if(n[1] == 0x44) return SYLK.to_workbook(d, o); break;
case 0x49: if(n[1] == 0x44) return read_wb_ID(d, o); break;
case 0x54: if(n[1] == 0x41 && n[2] == 0x42 && n[3] == 0x4C) return DIF.to_workbook(d, o); break;
case 0x50: if(n[1] == 0x4B && n[2] < 0x20 && n[3] < 0x20) return read_zip(d, o); break;
case 0xEF: return n[3] == 0x3C ? parse_xlml(d, o) : PRN.to_workbook(d,o);
......
......@@ -88,8 +88,8 @@ function make_csv_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Arr
else if(val.v != null) {
isempty = false;
txt = ''+format_cell(val, null, o);
for(var i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) {
txt = "\"" + txt.replace(qreg, '""') + "\""; break; }
for(var i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) {txt = "\"" + txt.replace(qreg, '""') + "\""; break; }
if(txt == "ID") txt = '"ID"';
} else if(val.f != null && !val.F) {
isempty = false;
txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"';
......@@ -166,6 +166,30 @@ function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array<string>*/ {
return cmds;
}
function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ {
var o = opts || {};
var ws = ({}/*:any*/);
var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:js.length}}/*:any*/);
var hdr = o.header || [], C = 0;
for(var R = 0; R != js.length; ++R) {
Object.keys(js[R]).filter(function(x) { return js[R].hasOwnProperty(x); }).forEach(function(k) {
if((C=hdr.indexOf(k)) == -1) hdr[C=hdr.length] = k;
var v = js[R][k];
var t = 'z';
if(typeof v == 'number') t = 'n';
else if(typeof v == 'boolean') t = 'b';
else if(typeof v == 'string') t = 's';
else if(v instanceof Date) t = 'd';
ws[encode_cell({c:C,r:R+1})] = {t:t, v:v};
});
}
range.e.c = hdr.length - 1;
for(C = 0; C < hdr.length; ++C) ws[encode_col(C) + "1"] = {t:'s', v:hdr[C]};
ws['!ref'] = encode_range(range);
return ws;
}
var utils = {
encode_col: encode_col,
encode_row: encode_row,
......@@ -182,6 +206,7 @@ var utils = {
make_json: sheet_to_json,
make_formulae: sheet_to_formulae,
aoa_to_sheet: aoa_to_sheet,
json_to_sheet: json_to_sheet,
table_to_sheet: parse_dom_table,
table_to_book: table_to_book,
sheet_to_csv: sheet_to_csv,
......
......@@ -92,11 +92,11 @@ utils.sheet_set_array_formula = function(ws/*:Worksheet*/, range, formula/*:stri
var cell = ws_get_cell_stub(ws, R, C);
cell.t = 'n';
cell.F = rngstr;
delete cell.v;
delete cell.v;
if(R == rng.s.r && C == rng.s.c) cell.f = formula;
}
return ws;
}
};
return utils;
})(utils);
......
此差异由.gitattributes 抑制。
此差异由.gitattributes 抑制。
此差异由.gitattributes 抑制。
此差异由.gitattributes 抑制。
此差异由.gitattributes 抑制。
此差异由.gitattributes 抑制。
此差异由.gitattributes 抑制。
......@@ -34,6 +34,7 @@ Utilities are available in the `XLSX.utils` object:
**Importing:**
- `aoa_to_sheet` converts an array of arrays of JS data to a worksheet.
- `json_to_sheet` converts an array of JS objects to a worksheet.
**Exporting:**
......@@ -41,7 +42,7 @@ Utilities are available in the `XLSX.utils` object:
- `sheet_to_csv` generates delimiter-separated-values output.
- `sheet_to_formulae` generates a list of the formulae (with value fallbacks).
Exporters are described in the [Utility Functions](#utility-functions) section.
These utilities are described in [Utility Functions](#utility-functions) below.
**Cell and cell address manipulation:**
......
......@@ -42,6 +42,25 @@ var ws = XLSX.utils.aoa_to_sheet([
```
</details>
### Array of Objects Input
`XLSX.utils.json_to_sheet` takes an array of objects and returns a worksheet
with automatically-generated "headers" based on the keys of the objects.
<details>
<summary><b>Examples</b> (click to show)</summary>
The original sheet cannot be reproduced because JS object keys must be unique.
After replacing the second `e` and `S` with `e_1` and `S_1`:
```js
var ws = XLSX.utils.json_to_sheet([
{S:1,h:2,e:3,e_1:4,t:5,J:6,S_1:7},
{S:2,h:3,e:4,e_1:5,t:6,J:7,S_1:8}
]);
```
</details>
### HTML Table Input
`XLSX.utils.table_to_sheet` takes a table DOM element and returns a worksheet
......
......@@ -46,6 +46,7 @@
* [Output Type](README.md#output-type)
- [Utility Functions](README.md#utility-functions)
* [Array of Arrays Input](README.md#array-of-arrays-input)
* [Array of Objects Input](README.md#array-of-objects-input)
* [HTML Table Input](README.md#html-table-input)
* [Formulae Output](README.md#formulae-output)
* [Delimiter-Separated Output](README.md#delimiter-separated-output)
......
{
"name": "xlsx",
"version": "0.10.0",
"version": "0.10.1",
"author": "sheetjs",
"description": "Excel (XLSB/XLSX/XLSM/XLS/XML) and ODS (ODS/FODS/UOS) spreadsheet parser and writer",
"keywords": [ "excel", "xls", "xlsx", "xlsb", "xlsm", "ods", "office", "spreadsheet" ],
......
......@@ -1413,6 +1413,21 @@ describe('roundtrip features', function() {
});
});
});
it('should preserve js objects', function() {
var data = [
{a:1},
{b:2,c:3},
{b:"a",d:"b"},
{a:true, c:false},
{c:new Date("2017-02-19T14:30Z")}
];
var wb = X.utils.json_to_sheet(data);
var out = X.utils.sheet_to_json(wb, {raw:true});
data.forEach(function(row, i) {
Object.keys(row).forEach(function(k) { assert.equal(row[k], out[i][k]); });
});
});
});
//function password_file(x){return x.match(/^password.*\.xls$/); }
......
此差异由.gitattributes 抑制。
此差异由.gitattributes 抑制。
......@@ -70,3 +70,4 @@
./test_files/2011/apachepoi_SimpleWithComments.xls.xml
./test_files/apachepoi_SimpleWithComments.xlsx
./test_files/2013/apachepoi_SimpleWithComments.xlsx.xlsb
./test_files/password_2002_40_xor.xls
......@@ -6,7 +6,7 @@
/*global exports, module, require:false, process:false, Buffer:false */
var XLSX = {};
(function make_xlsx(XLSX){
XLSX.version = '0.10.0';
XLSX.version = '0.10.1';
var current_codepage = 1200;
/*:: declare var cptable:any; */
/*global cptable:true */
......@@ -5736,6 +5736,20 @@ var PRN = (function() {
};
})();
/* Excel defaults to SYLK but warns if data is not valid */
function read_wb_ID(d, opts) {
var o = opts || {}, OLD_WTF = !!o.WTF; o.WTF = true;
try {
var out = SYLK.to_workbook(d, o);
o.WTF = OLD_WTF;
return out;
} catch(e) {
o.WTF = OLD_WTF;
if(!e.message.match(/SYLK bad record ID/) && OLD_WTF) throw e;
return PRN.to_workbook(d, opts);
}
}
var WK_ = (function() {
function lotushopper(data, cb/*:RecordHopperCB*/, opts/*:any*/) {
if(!data) return;
......@@ -17260,7 +17274,7 @@ function readSync(data/*:RawData*/, opts/*:?ParseOpts*/)/*:Workbook*/ {
case 0xD0: return read_cfb(CFB.read(d, o), o);
case 0x09: return parse_xlscfb(s2a(o.type === 'base64' ? Base64.decode(d) : d), o);
case 0x3C: return parse_xlml(d, o);
case 0x49: if(n[1] == 0x44) return SYLK.to_workbook(d, o); break;
case 0x49: if(n[1] == 0x44) return read_wb_ID(d, o); break;
case 0x54: if(n[1] == 0x41 && n[2] == 0x42 && n[3] == 0x4C) return DIF.to_workbook(d, o); break;
case 0x50: if(n[1] == 0x4B && n[2] < 0x20 && n[3] < 0x20) return read_zip(d, o); break;
case 0xEF: return n[3] == 0x3C ? parse_xlml(d, o) : PRN.to_workbook(d,o);
......@@ -17484,8 +17498,8 @@ function make_csv_row(sheet/*:Worksheet*/, r/*:Range*/, R/*:number*/, cols/*:Arr
else if(val.v != null) {
isempty = false;
txt = ''+format_cell(val, null, o);
for(var i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) {
txt = "\"" + txt.replace(qreg, '""') + "\""; break; }
for(var i = 0, cc = 0; i !== txt.length; ++i) if((cc = txt.charCodeAt(i)) === fs || cc === rs || cc === 34) {txt = "\"" + txt.replace(qreg, '""') + "\""; break; }
if(txt == "ID") txt = '"ID"';
} else if(val.f != null && !val.F) {
isempty = false;
txt = '=' + val.f; if(txt.indexOf(",") >= 0) txt = '"' + txt.replace(qreg, '""') + '"';
......@@ -17562,6 +17576,30 @@ function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array<string>*/ {
return cmds;
}
function json_to_sheet(js/*:Array<any>*/, opts)/*:Worksheet*/ {
var o = opts || {};
var ws = ({}/*:any*/);
var range/*:Range*/ = ({s: {c:0, r:0}, e: {c:0, r:js.length}}/*:any*/);
var hdr = o.header || [], C = 0;
for(var R = 0; R != js.length; ++R) {
Object.keys(js[R]).filter(function(x) { return js[R].hasOwnProperty(x); }).forEach(function(k) {
if((C=hdr.indexOf(k)) == -1) hdr[C=hdr.length] = k;
var v = js[R][k];
var t = 'z';
if(typeof v == 'number') t = 'n';
else if(typeof v == 'boolean') t = 'b';
else if(typeof v == 'string') t = 's';
else if(v instanceof Date) t = 'd';
ws[encode_cell({c:C,r:R+1})] = {t:t, v:v};
});
}
range.e.c = hdr.length - 1;
for(C = 0; C < hdr.length; ++C) ws[encode_col(C) + "1"] = {t:'s', v:hdr[C]};
ws['!ref'] = encode_range(range);
return ws;
}
var utils = {
encode_col: encode_col,
encode_row: encode_row,
......@@ -17578,6 +17616,7 @@ var utils = {
make_json: sheet_to_json,
make_formulae: sheet_to_formulae,
aoa_to_sheet: aoa_to_sheet,
json_to_sheet: json_to_sheet,
table_to_sheet: parse_dom_table,
table_to_book: table_to_book,
sheet_to_csv: sheet_to_csv,
......@@ -17680,11 +17719,11 @@ utils.sheet_set_array_formula = function(ws/*:Worksheet*/, range, formula/*:stri
var cell = ws_get_cell_stub(ws, R, C);
cell.t = 'n';
cell.F = rngstr;
delete cell.v;
delete cell.v;
if(R == rng.s.r && C == rng.s.c) cell.f = formula;
}
return ws;
}
};
return utils;
})(utils);
......
此差异由.gitattributes 抑制。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册