version bump 0.11.7: VFP DBF write
- DBF writer (dBASE II + VFP extensions) - updated CFB to 0.13.2 - BIFF8 XLS write VBA
This commit is contained in:
parent
ed4348a6b6
commit
825830d1cd
8
Makefile
8
Makefile
@ -53,6 +53,7 @@ init: ## Initial setup for development
|
||||
DISTHDR=misc/suppress_export.js
|
||||
.PHONY: dist
|
||||
dist: dist-deps $(TARGET) bower.json ## Prepare JS files for distribution
|
||||
mkdir -p dist
|
||||
<$(TARGET) sed "s/require('stream')/{}/g;s/require('....*')/undefined/g" > dist/$(TARGET)
|
||||
cp LICENSE dist/
|
||||
uglifyjs $(DISTHDR) dist/$(TARGET) $(UGLIFYOPTS) -o dist/$(LIB).min.js --source-map dist/$(LIB).min.map --preamble "$$(head -n 1 bits/00_header.js)"
|
||||
@ -64,15 +65,17 @@ dist: dist-deps $(TARGET) bower.json ## Prepare JS files for distribution
|
||||
|
||||
.PHONY: dist-deps
|
||||
dist-deps: ## Copy dependencies for distribution
|
||||
mkdir -p dist
|
||||
cp node_modules/codepage/dist/cpexcel.full.js dist/cpexcel.js
|
||||
cp jszip.js dist/jszip.js
|
||||
|
||||
.PHONY: aux
|
||||
aux: $(AUXTARGETS)
|
||||
|
||||
BYTEFILE=dist/xlsx.min.js dist/xlsx.{core,full}.min.js
|
||||
.PHONY: bytes
|
||||
bytes: ## Display minified and gzipped file sizes
|
||||
for i in dist/xlsx.min.js dist/xlsx.{core,full}.min.js; do printj "%-30s %7d %10d" $$i $$(wc -c < $$i) $$(gzip --best --stdout $$i | wc -c); done
|
||||
for i in $(BYTEFILE); do printj "%-30s %7d %10d" $$i $$(wc -c < $$i) $$(gzip --best --stdout $$i | wc -c); done
|
||||
|
||||
.PHONY: graph
|
||||
graph: formats.png legend.png ## Rebuild format conversion graph
|
||||
@ -176,7 +179,8 @@ old-lint: $(TARGET) $(AUXTARGETS) ## Run jshint and jscs checks
|
||||
.PHONY: tslint
|
||||
tslint: $(TARGET) ## Run typescript checks
|
||||
#@npm install dtslint typescript
|
||||
@npm run-script dtslint
|
||||
#@npm run-script dtslint
|
||||
dtslint types
|
||||
|
||||
.PHONY: flow
|
||||
flow: lint ## Run flow checker
|
||||
|
15
README.md
15
README.md
@ -1439,8 +1439,9 @@ if a sheet is visible is to check if the `Hidden` property is logical truth:
|
||||
|
||||
VBA Macros are stored in a special data blob that is exposed in the `vbaraw`
|
||||
property of the workbook object when the `bookVBA` option is `true`. They are
|
||||
supported in `XLSM`, `XLSB`, and `BIFF8 XLS` formats. The `XLSM` and `XLSB`
|
||||
writers automatically insert the data blobs if it is present in the workbook.
|
||||
supported in `XLSM`, `XLSB`, and `BIFF8 XLS` formats. The supported format
|
||||
writers automatically insert the data blobs if it is present in the workbook and
|
||||
associate with the worksheet names.
|
||||
|
||||
<details>
|
||||
<summary><b>Macrosheets</b> (click to show)</summary>
|
||||
@ -1640,6 +1641,7 @@ output formats. The specific file type is controlled with `bookType` option:
|
||||
| `sylk` | `.sylk` | none | single | Symbolic Link (SYLK) |
|
||||
| `html` | `.html` | none | single | HTML Document |
|
||||
| `dif` | `.dif` | none | single | Data Interchange Format (DIF) |
|
||||
| `dbf` | `.dbf` | none | single | dBASE II + VFP Extensions (DBF) |
|
||||
| `rtf` | `.rtf` | none | single | Rich Text Format (RTF) |
|
||||
| `prn` | `.prn` | none | single | Lotus Formatted Text |
|
||||
|
||||
@ -1973,7 +1975,7 @@ Despite the library name `xlsx`, it supports numerous spreadsheet file formats:
|
||||
| OpenDocument Spreadsheet (ODS) | :o: | :o: |
|
||||
| Flat XML ODF Spreadsheet (FODS) | :o: | :o: |
|
||||
| Uniform Office Format Spreadsheet (标文通 UOS1/UOS2) | :o: | |
|
||||
| dBASE II/III/IV / Visual FoxPro (DBF) | :o: | |
|
||||
| dBASE II/III/IV / Visual FoxPro (DBF) | :o: | :o: |
|
||||
| Lotus 1-2-3 (WKS/WK1/WK2/WK3/WK4/123) | :o: | |
|
||||
| Quattro Pro Spreadsheet (WQ1/WQ2/WB1/WB2/WB3/QPW) | :o: | |
|
||||
| **Other Common Spreadsheet Output Formats** |:-----:|:-----:|
|
||||
@ -2142,10 +2144,12 @@ Many older formats supported only one worksheet:
|
||||
|
||||
DBF is really a typed table format: each column can only hold one data type and
|
||||
each record omits type information. The parser generates a header row and
|
||||
inserts records starting at the second row of the worksheet.
|
||||
inserts records starting at the second row of the worksheet. The writer makes
|
||||
files compatible with Visual FoxPro extensions.
|
||||
|
||||
Multi-file extensions like external memos and tables are currently unsupported,
|
||||
limited by the general ability to read arbitrary files in the web browser.
|
||||
limited by the general ability to read arbitrary files in the web browser. The
|
||||
reader understands DBF Level 7 extensions like DATETIME.
|
||||
|
||||
</details>
|
||||
|
||||
@ -2479,4 +2483,3 @@ granted by the Apache 2.0 License are reserved by the Original Author.
|
||||
- ISO/IEC 29500:2012(E) "Information technology — Document description and processing languages — Office Open XML File Formats"
|
||||
- Open Document Format for Office Applications Version 1.2 (29 September 2011)
|
||||
- Worksheet File Format (From Lotus) December 1984
|
||||
|
||||
|
@ -34,6 +34,7 @@ program
|
||||
.option('-A, --arrays', 'emit rows as JS objects (raw numbers)')
|
||||
.option('-H, --html', 'emit HTML to <sheetname> or <file>.html')
|
||||
.option('-D, --dif', 'emit DIF to <sheetname> or <file>.dif (Lotus DIF)')
|
||||
.option('-U, --dbf', 'emit DBF to <sheetname> or <file>.dbf (MSVFP DBF)')
|
||||
.option('-K, --sylk', 'emit SYLK to <sheetname> or <file>.slk (Excel SYLK)')
|
||||
.option('-P, --prn', 'emit PRN to <sheetname> or <file>.prn (Lotus PRN)')
|
||||
.option('-t, --txt', 'emit TXT to <sheetname> or <file>.txt (UTF-8 TSV)')
|
||||
@ -186,6 +187,7 @@ try {
|
||||
['prn', '.prn'],
|
||||
['rtf', '.rtf'],
|
||||
['txt', '.txt'],
|
||||
['dbf', '.dbf'],
|
||||
['dif', '.dif']
|
||||
].forEach(function(m) { if(program[m[0]] || isfmt(m[1])) {
|
||||
wopts.bookType = m[0];
|
||||
|
@ -1 +1 @@
|
||||
XLSX.version = '0.11.6';
|
||||
XLSX.version = '0.11.7';
|
||||
|
@ -38,7 +38,7 @@ type CFBFiles = {[n:string]:CFBEntry};
|
||||
/* [MS-CFB] v20130118 */
|
||||
var CFB = (function _CFB(){
|
||||
var exports/*:CFBModule*/ = /*::(*/{}/*:: :any)*/;
|
||||
exports.version = '0.13.1';
|
||||
exports.version = '0.13.2';
|
||||
/* [MS-CFB] 2.6.4 */
|
||||
function namecmp(l/*:string*/, r/*:string*/)/*:number*/ {
|
||||
var L = l.split("/"), R = r.split("/");
|
||||
@ -59,6 +59,8 @@ function filename(p/*:string*/)/*:string*/ {
|
||||
var c = p.lastIndexOf("/");
|
||||
return (c === -1) ? p : p.slice(c+1);
|
||||
}
|
||||
var fs/*:: = require('fs'); */;
|
||||
function get_fs() { return fs || (fs = require('fs')); }
|
||||
function parse(file/*:RawBytes*/, options/*:CFBReadOpts*/)/*:CFBContainer*/ {
|
||||
var mver = 3;
|
||||
var ssz = 512;
|
||||
@ -356,9 +358,8 @@ function read_date(blob/*:RawBytes|CFBlob*/, offset/*:number*/)/*:Date*/ {
|
||||
return new Date(( ( (__readUInt32LE(blob,offset+4)/1e7)*Math.pow(2,32)+__readUInt32LE(blob,offset)/1e7 ) - 11644473600)*1000);
|
||||
}
|
||||
|
||||
var fs/*:: = require('fs'); */;
|
||||
function read_file(filename/*:string*/, options/*:CFBReadOpts*/) {
|
||||
if(fs == null) fs = require('fs');
|
||||
get_fs();
|
||||
return parse(fs.readFileSync(filename), options);
|
||||
}
|
||||
|
||||
@ -638,6 +639,7 @@ var consts = {
|
||||
};
|
||||
|
||||
function write_file(cfb/*:CFBContainer*/, filename/*:string*/, options/*:CFBWriteOpts*/)/*:void*/ {
|
||||
get_fs();
|
||||
var o = _write(cfb, options);
|
||||
/*:: if(typeof Buffer == 'undefined' || !Buffer.isBuffer(o) || !(o instanceof Buffer)) throw new Error("unreachable"); */
|
||||
fs.writeFileSync(filename, o);
|
||||
@ -652,7 +654,7 @@ function a2s(o/*:RawBytes*/)/*:string*/ {
|
||||
function write(cfb/*:CFBContainer*/, options/*:CFBWriteOpts*/)/*:RawBytes|string*/ {
|
||||
var o = _write(cfb, options);
|
||||
switch(options && options.type) {
|
||||
case "file": fs.writeFileSync(options.filename, (o/*:any*/)); return o;
|
||||
case "file": get_fs(); fs.writeFileSync(options.filename, (o/*:any*/)); return o;
|
||||
case "binary": return a2s(o);
|
||||
case "base64": return Base64.encode(a2s(o));
|
||||
}
|
||||
@ -668,13 +670,13 @@ function cfb_add(cfb/*:CFBContainer*/, name/*:string*/, content/*:?RawBytes*/, o
|
||||
init_cfb(cfb);
|
||||
var file = CFB.find(cfb, name);
|
||||
if(!file) {
|
||||
var fpath = cfb.FullPaths[0];
|
||||
var fpath/*:string*/ = cfb.FullPaths[0];
|
||||
if(name.slice(0, fpath.length) == fpath) fpath = name;
|
||||
else {
|
||||
if(fpath.slice(-1) != "/") fpath += "/";
|
||||
fpath = (fpath + name).replace("//","/");
|
||||
}
|
||||
file = ({name: filename(name)}/*:any*/);
|
||||
file = ({name: filename(name), type: 2}/*:any*/);
|
||||
cfb.FileIndex.push(file);
|
||||
cfb.FullPaths.push(fpath);
|
||||
CFB.utils.cfb_gc(cfb);
|
||||
|
@ -362,6 +362,14 @@ function parse_XLUnicodeString2(blob, length, opts) {
|
||||
if(cch === 0) { blob.l++; return ""; }
|
||||
return blob.read_shift(cch, 'sbcs-cont');
|
||||
}
|
||||
/* TODO: BIFF5 and lower, codepage awareness */
|
||||
function write_XLUnicodeString(str, opts, o) {
|
||||
if(!o) o = new_buf(3 + 2 * str.length);
|
||||
o.write_shift(2, str.length);
|
||||
o.write_shift(1, 1);
|
||||
o.write_shift(31, str, 'utf16le');
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLS] 2.5.61 ControlInfo */
|
||||
function parse_ControlInfo(blob, length, opts) {
|
||||
|
@ -193,9 +193,105 @@ function dbf_to_workbook(buf, opts)/*:Workbook*/ {
|
||||
catch(e) { if(opts && opts.WTF) throw e; }
|
||||
return ({SheetNames:[],Sheets:{}});
|
||||
}
|
||||
|
||||
var _RLEN = { 'B': 8, 'C': 250, 'L': 1, 'D': 8, '?': 0, '': 0 };
|
||||
function sheet_to_dbf(ws/*:Worksheet*/, opts/*:WriteOpts*/) {
|
||||
var o = opts || {};
|
||||
if(o.type == "string") throw new Error("Cannot write DBF to JS string");
|
||||
var ba = buf_array();
|
||||
var aoa/*:AOA*/ = sheet_to_json(ws, {header:1, raw:true, cellDates:true});
|
||||
var headers = aoa[0], data = aoa.slice(1);
|
||||
var i = 0, j = 0, hcnt = 0, rlen = 1;
|
||||
for(i = 0; i < headers.length; ++i) {
|
||||
if(i == null) continue;
|
||||
++hcnt;
|
||||
if(typeof headers[i] !== 'string') throw new Error("DBF Invalid column name");
|
||||
if(headers.indexOf(headers[i]) !== i) for(j=0; j<1024;++j)
|
||||
if(headers.indexOf(headers[i] + "_" + j) == -1) { headers[i] += "_" + j; break; }
|
||||
}
|
||||
var range = safe_decode_range(ws['!ref']);
|
||||
var coltypes = [];
|
||||
for(i = 0; i <= range.e.c - range.s.c; ++i) {
|
||||
var col/*:Array<any>*/ = [];
|
||||
for(j=0; j < data.length; ++j) {
|
||||
if(data[j][i] != null) col.push(data[j][i]);
|
||||
}
|
||||
if(col.length == 0 || headers[i] == null) { coltypes[i] = '?'; continue; }
|
||||
var guess = '', _guess = '';
|
||||
for(j = 0; j < col.length; ++j) {
|
||||
switch(typeof col[j]) {
|
||||
/* TODO: check if L2 compat is desired */
|
||||
case 'number': _guess = 'B'; break;
|
||||
case 'string': _guess = 'C'; break;
|
||||
case 'boolean': _guess = 'L'; break;
|
||||
case 'object': _guess = col[j] instanceof Date ? 'D' : 'C'; break;
|
||||
default: _guess = 'C';
|
||||
}
|
||||
guess = guess && guess != _guess ? 'C' : _guess;
|
||||
if(guess == 'C') break;
|
||||
}
|
||||
rlen += _RLEN[guess] || 0;
|
||||
coltypes[i] = guess;
|
||||
}
|
||||
|
||||
var h = ba.next(32);
|
||||
h.write_shift(4, 0x13021130);
|
||||
h.write_shift(4, data.length);
|
||||
h.write_shift(2, 296 + 32 * hcnt);
|
||||
h.write_shift(2, rlen);
|
||||
for(i=0; i < 4; ++i) h.write_shift(4, 0);
|
||||
h.write_shift(4, 0x00000300); // TODO: CP
|
||||
|
||||
for(i = 0, j = 0; i < headers.length; ++i) {
|
||||
if(headers[i] == null) continue;
|
||||
var hf = ba.next(32);
|
||||
var _f = (headers[i].slice(-10) + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00").slice(0, 11);
|
||||
hf.write_shift(1, _f, "sbcs");
|
||||
hf.write_shift(1, coltypes[i] == '?' ? 'C' : coltypes[i], "sbcs");
|
||||
hf.write_shift(4, j);
|
||||
hf.write_shift(1, _RLEN[coltypes[i]] || 0);
|
||||
hf.write_shift(1, 0);
|
||||
hf.write_shift(1, 0x02);
|
||||
hf.write_shift(4, 0);
|
||||
hf.write_shift(1, 0);
|
||||
hf.write_shift(4, 0);
|
||||
hf.write_shift(4, 0);
|
||||
j += _RLEN[coltypes[i]] || 0;
|
||||
}
|
||||
|
||||
var hb = ba.next(264);
|
||||
hb.write_shift(4, 0x0000000D);
|
||||
for(i=0; i < 65;++i) hb.write_shift(4, 0x00000000);
|
||||
for(i=0; i < data.length; ++i) {
|
||||
var rout = ba.next(rlen);
|
||||
rout.write_shift(1, 0);
|
||||
for(j=0; j<headers.length; ++j) {
|
||||
if(headers[j] == null) continue;
|
||||
switch(coltypes[j]) {
|
||||
case 'L': rout.write_shift(1, data[i][j] == null ? 0x3F : data[i][j] ? 0x54 : 0x46); break;
|
||||
case 'B': rout.write_shift(8, data[i][j]||0, 'f'); break;
|
||||
case 'D':
|
||||
if(!data[i][j]) rout.write_shift(8, "00000000", "sbcs");
|
||||
else {
|
||||
rout.write_shift(4, ("0000"+data[i][j].getFullYear()).slice(-4), "sbcs");
|
||||
rout.write_shift(2, ("00"+(data[i][j].getMonth()+1)).slice(-2), "sbcs");
|
||||
rout.write_shift(2, ("00"+data[i][j].getDate()).slice(-2), "sbcs");
|
||||
} break;
|
||||
case 'C':
|
||||
var _s = String(data[i][j]||"");
|
||||
rout.write_shift(1, _s, "sbcs");
|
||||
for(hcnt=0; hcnt < 250-_s.length; ++hcnt) rout.write_shift(1, 0x20); break;
|
||||
}
|
||||
}
|
||||
// data
|
||||
}
|
||||
ba.next(1).write_shift(1, 0x1A);
|
||||
return ba.end();
|
||||
}
|
||||
return {
|
||||
to_workbook: dbf_to_workbook,
|
||||
to_sheet: dbf_to_sheet
|
||||
to_sheet: dbf_to_sheet,
|
||||
from_sheet: sheet_to_dbf
|
||||
};
|
||||
})();
|
||||
|
||||
|
@ -7,3 +7,12 @@ function make_vba_xls(cfb/*:CFBContainer*/) {
|
||||
});
|
||||
return CFB.write(newcfb);
|
||||
}
|
||||
|
||||
function fill_vba_xls(cfb/*:CFBContainer*/, vba/*:CFBContainer*/)/*:void*/ {
|
||||
vba.FullPaths.forEach(function(p, i) {
|
||||
if(i == 0) return;
|
||||
var newpath = p.replace(/[^/]*[/]/, "/_VBA_PROJECT_CUR/");
|
||||
if(newpath.slice(-1) !== "/") CFB.utils.cfb_add(cfb, newpath, vba.FileIndex[i].content);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -660,7 +660,8 @@ function parse_workbook(blob, options/*:ParseOpts*/)/*:Workbook*/ {
|
||||
/* empty */
|
||||
} break;
|
||||
case 'CodeName': {
|
||||
/* empty */
|
||||
/*:: if(!Workbook.WBProps) Workbook.WBProps = {}; */
|
||||
if(!cur_sheet) Workbook.WBProps.codeName = val;
|
||||
} break;
|
||||
case 'GUIDTypeLib': {
|
||||
/* empty */
|
||||
@ -894,5 +895,6 @@ function write_xlscfb(wb/*:Workbook*/, opts/*:WriteOpts*/)/*:CFBContainer*/ {
|
||||
}
|
||||
CFB.utils.cfb_add(cfb, wbpath, write_biff_buf(wb, o));
|
||||
// TODO: SI, DSI, CO
|
||||
if(o.biff == 8 && wb.vbaraw) fill_vba_xls(cfb, CFB.read(wb.vbaraw, {type: typeof wb.vbaraw == "string" ? "binary" : "buffer"}));
|
||||
return cfb;
|
||||
}
|
||||
|
@ -138,6 +138,8 @@ function write_ws_biff8(idx/*:number*/, opts, wb/*:Workbook*/) {
|
||||
write_ws_biff8_cell(ba, cell, R, C, opts);
|
||||
}
|
||||
}
|
||||
var cname = ((((wb||{}).Workbook||{}).Sheets||[])[idx]||{}).name||s;
|
||||
write_biff_rec(ba, "CodeName", write_XLUnicodeString(cname, opts));
|
||||
/* ... */
|
||||
write_biff_rec(ba, "EOF");
|
||||
return ba.end();
|
||||
@ -157,6 +159,11 @@ function write_biff8_global(wb/*:Workbook*/, bufs, opts/*:WriteOpts*/) {
|
||||
write_biff_rec(A, "CodePage", writeuint16(b8 ? 0x04b0 : 0x04E4));
|
||||
if(b8) write_biff_rec(A, "DSF", writeuint16(0));
|
||||
write_biff_rec(A, "RRTabId", write_RRTabId(wb.SheetNames.length));
|
||||
if(b8 && wb.vbaraw) {
|
||||
write_biff_rec(A, "ObProj");
|
||||
var cname = ((wb.Workbook||{}).WBProps||{}).codeName || "ThisWorkbook";
|
||||
write_biff_rec(A, "CodeName", write_XLUnicodeString(cname, opts));
|
||||
}
|
||||
write_biff_rec(A, "BuiltInFnGroupCount", writeuint16(0x11));
|
||||
write_biff_rec(A, "WinProtect", writebool(false));
|
||||
write_biff_rec(A, "Protect", writebool(false));
|
||||
|
@ -1,9 +1,13 @@
|
||||
/* actual implementation elsewhere, wrappers are for read/write */
|
||||
function write_sheet_index(wb/*:Workbook*/, sheet/*:?string*/)/*:number*/ {
|
||||
if(!sheet) return 0;
|
||||
var idx = wb.SheetNames.indexOf(sheet);
|
||||
if(idx == -1) throw new Error("Sheet not found: " + sheet);
|
||||
return idx;
|
||||
}
|
||||
|
||||
function write_obj_str(factory/*:WriteObjStrFactory*/) {
|
||||
return function write_str(wb/*:Workbook*/, o/*:WriteOpts*/)/*:string*/ {
|
||||
var idx = 0;
|
||||
for(var i=0;i<wb.SheetNames.length;++i) if(wb.SheetNames[i] == o.sheet) idx=i;
|
||||
if(idx == 0 && !!o.sheet && wb.SheetNames[0] != o.sheet) throw new Error("Sheet not found: " + o.sheet);
|
||||
var idx = write_sheet_index(wb, o.sheet);
|
||||
return factory.from_sheet(wb.Sheets[wb.SheetNames[idx]], o, wb);
|
||||
};
|
||||
}
|
||||
@ -15,3 +19,6 @@ var write_dif_str = write_obj_str(DIF);
|
||||
var write_prn_str = write_obj_str(PRN);
|
||||
var write_rtf_str = write_obj_str(RTF);
|
||||
var write_txt_str = write_obj_str({from_sheet:sheet_to_txt});
|
||||
// $FlowIgnore
|
||||
var write_dbf_buf = write_obj_str(DBF);
|
||||
|
||||
|
@ -87,13 +87,15 @@ function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
|
||||
case 'txt': return write_stxt_type(write_txt_str(wb, o), o);
|
||||
case 'csv': return write_string_type(write_csv_str(wb, o), o, "\ufeff");
|
||||
case 'dif': return write_string_type(write_dif_str(wb, o), o);
|
||||
// $FlowIgnore
|
||||
case 'dbf': return write_binary_type(write_dbf_buf(wb, o), o);
|
||||
case 'prn': return write_string_type(write_prn_str(wb, o), o);
|
||||
case 'rtf': return write_string_type(write_rtf_str(wb, o), o);
|
||||
case 'fods': return write_string_type(write_ods(wb, o), o);
|
||||
case 'biff2': if(!o.biff) o.biff = 2; /* falls through */
|
||||
case 'biff3': if(!o.biff) o.biff = 3; /* falls through */
|
||||
case 'biff4': if(!o.biff) o.biff = 4; return write_binary_type(write_biff_buf(wb, o), o);
|
||||
case 'biff5': if(!o.biff) o.biff = 5; return write_cfb_type(wb, o);
|
||||
case 'biff5': if(!o.biff) o.biff = 5; /* falls through */
|
||||
case 'biff8':
|
||||
case 'xls': if(!o.biff) o.biff = 8; return write_cfb_type(wb, o);
|
||||
case 'xlsx':
|
||||
@ -104,26 +106,17 @@ function writeSync(wb/*:Workbook*/, opts/*:?WriteOpts*/) {
|
||||
}
|
||||
}
|
||||
|
||||
function resolve_book_type(o/*?WriteFileOpts*/) {
|
||||
if(!o.bookType) switch(o.file.slice(o.file.lastIndexOf(".")).toLowerCase()) {
|
||||
case '.xlsx': o.bookType = 'xlsx'; break;
|
||||
case '.xlsm': o.bookType = 'xlsm'; break;
|
||||
case '.xlsb': o.bookType = 'xlsb'; break;
|
||||
case '.fods': o.bookType = 'fods'; break;
|
||||
case '.xlml': o.bookType = 'xlml'; break;
|
||||
case '.sylk': o.bookType = 'sylk'; break;
|
||||
case '.html': o.bookType = 'html'; break;
|
||||
case '.xls': o.bookType = 'biff8'; break;
|
||||
case '.xml': o.bookType = 'xml'; break;
|
||||
case '.ods': o.bookType = 'ods'; break;
|
||||
case '.csv': o.bookType = 'csv'; break;
|
||||
case '.txt': o.bookType = 'txt'; break;
|
||||
case '.dif': o.bookType = 'dif'; break;
|
||||
case '.prn': o.bookType = 'prn'; break;
|
||||
case '.rtf': o.bookType = 'rtf'; break;
|
||||
case '.slk': o.bookType = 'sylk'; break;
|
||||
case '.htm': o.bookType = 'html'; break;
|
||||
}
|
||||
function resolve_book_type(o/*:WriteFileOpts*/) {
|
||||
if(o.bookType) return;
|
||||
var _BT = {
|
||||
"xls": "biff8",
|
||||
"htm": "html",
|
||||
"slk": "sylk",
|
||||
"Sh33tJS": "WTF"
|
||||
};
|
||||
var ext = o.file.slice(o.file.lastIndexOf(".")).toLowerCase();
|
||||
if(ext.match(/^\.[a-z]+$/)) o.bookType = ext.slice(1);
|
||||
o.bookType = _BT[o.bookType] || o.bookType;
|
||||
}
|
||||
|
||||
function writeFileSync(wb/*:Workbook*/, filename/*:string*/, opts/*:?WriteFileOpts*/) {
|
||||
|
@ -3,15 +3,19 @@
|
||||
if [ ! -e SheetJS ]; then
|
||||
react-native init SheetJS
|
||||
cd SheetJS
|
||||
npm i -S xlsx react react-native react-native-table-component react-native-fs
|
||||
npm i -S xlsx react-native-table-component react-native-fs
|
||||
cd -
|
||||
fi
|
||||
if [ ! -e SheetJS/logo.png ]; then
|
||||
curl -O http://oss.sheetjs.com/assets/img/logo.png
|
||||
mv logo.png SheetJS/logo.png
|
||||
fi
|
||||
cp react-native.js SheetJS/index.ios.js
|
||||
cp react-native.js SheetJS/index.android.js
|
||||
if [ -e SheetJS/index.ios.js ]; then
|
||||
cp react-native.js SheetJS/index.ios.js
|
||||
cp react-native.js SheetJS/index.android.js
|
||||
else
|
||||
cp react-native.js SheetJS/index.js
|
||||
fi
|
||||
cd SheetJS;
|
||||
RNFB_ANDROID_PERMISSIONS=true react-native link
|
||||
cd -;
|
||||
|
24
dist/xlsx.core.min.js
vendored
24
dist/xlsx.core.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.core.min.map
vendored
2
dist/xlsx.core.min.map
vendored
File diff suppressed because one or more lines are too long
26
dist/xlsx.full.min.js
vendored
26
dist/xlsx.full.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.full.min.map
vendored
2
dist/xlsx.full.min.map
vendored
File diff suppressed because one or more lines are too long
195
dist/xlsx.js
vendored
195
dist/xlsx.js
vendored
@ -4,7 +4,7 @@
|
||||
/*global global, exports, module, require:false, process:false, Buffer:false */
|
||||
var XLSX = {};
|
||||
(function make_xlsx(XLSX){
|
||||
XLSX.version = '0.11.6';
|
||||
XLSX.version = '0.11.7';
|
||||
var current_codepage = 1200;
|
||||
/*global cptable:true */
|
||||
if(typeof module !== "undefined" && typeof require !== 'undefined') {
|
||||
@ -1026,7 +1026,7 @@ var DO_NOT_EXPORT_CFB = true;
|
||||
/* [MS-CFB] v20130118 */
|
||||
var CFB = (function _CFB(){
|
||||
var exports = {};
|
||||
exports.version = '0.13.1';
|
||||
exports.version = '0.13.2';
|
||||
/* [MS-CFB] 2.6.4 */
|
||||
function namecmp(l, r) {
|
||||
var L = l.split("/"), R = r.split("/");
|
||||
@ -1047,6 +1047,8 @@ function filename(p) {
|
||||
var c = p.lastIndexOf("/");
|
||||
return (c === -1) ? p : p.slice(c+1);
|
||||
}
|
||||
var fs;
|
||||
function get_fs() { return fs || (fs = require('fs')); }
|
||||
function parse(file, options) {
|
||||
var mver = 3;
|
||||
var ssz = 512;
|
||||
@ -1344,9 +1346,8 @@ function read_date(blob, offset) {
|
||||
return new Date(( ( (__readUInt32LE(blob,offset+4)/1e7)*Math.pow(2,32)+__readUInt32LE(blob,offset)/1e7 ) - 11644473600)*1000);
|
||||
}
|
||||
|
||||
var fs;
|
||||
function read_file(filename, options) {
|
||||
if(fs == null) fs = require('fs');
|
||||
get_fs();
|
||||
return parse(fs.readFileSync(filename), options);
|
||||
}
|
||||
|
||||
@ -1621,6 +1622,7 @@ var consts = {
|
||||
};
|
||||
|
||||
function write_file(cfb, filename, options) {
|
||||
get_fs();
|
||||
var o = _write(cfb, options);
|
||||
fs.writeFileSync(filename, o);
|
||||
}
|
||||
@ -1634,7 +1636,7 @@ function a2s(o) {
|
||||
function write(cfb, options) {
|
||||
var o = _write(cfb, options);
|
||||
switch(options && options.type) {
|
||||
case "file": fs.writeFileSync(options.filename, (o)); return o;
|
||||
case "file": get_fs(); fs.writeFileSync(options.filename, (o)); return o;
|
||||
case "binary": return a2s(o);
|
||||
case "base64": return Base64.encode(a2s(o));
|
||||
}
|
||||
@ -1656,7 +1658,7 @@ function cfb_add(cfb, name, content, opts) {
|
||||
if(fpath.slice(-1) != "/") fpath += "/";
|
||||
fpath = (fpath + name).replace("//","/");
|
||||
}
|
||||
file = ({name: filename(name)});
|
||||
file = ({name: filename(name), type: 2});
|
||||
cfb.FileIndex.push(file);
|
||||
cfb.FullPaths.push(fpath);
|
||||
CFB.utils.cfb_gc(cfb);
|
||||
@ -4339,6 +4341,14 @@ function parse_XLUnicodeString2(blob, length, opts) {
|
||||
if(cch === 0) { blob.l++; return ""; }
|
||||
return blob.read_shift(cch, 'sbcs-cont');
|
||||
}
|
||||
/* TODO: BIFF5 and lower, codepage awareness */
|
||||
function write_XLUnicodeString(str, opts, o) {
|
||||
if(!o) o = new_buf(3 + 2 * str.length);
|
||||
o.write_shift(2, str.length);
|
||||
o.write_shift(1, 1);
|
||||
o.write_shift(31, str, 'utf16le');
|
||||
return o;
|
||||
}
|
||||
|
||||
/* [MS-XLS] 2.5.61 ControlInfo */
|
||||
function parse_ControlInfo(blob, length, opts) {
|
||||
@ -5579,9 +5589,105 @@ function dbf_to_workbook(buf, opts) {
|
||||
catch(e) { if(opts && opts.WTF) throw e; }
|
||||
return ({SheetNames:[],Sheets:{}});
|
||||
}
|
||||
|
||||
var _RLEN = { 'B': 8, 'C': 250, 'L': 1, 'D': 8, '?': 0, '': 0 };
|
||||
function sheet_to_dbf(ws, opts) {
|
||||
var o = opts || {};
|
||||
if(o.type == "string") throw new Error("Cannot write DBF to JS string");
|
||||
var ba = buf_array();
|
||||
var aoa = sheet_to_json(ws, {header:1, raw:true, cellDates:true});
|
||||
var headers = aoa[0], data = aoa.slice(1);
|
||||
var i = 0, j = 0, hcnt = 0, rlen = 1;
|
||||
for(i = 0; i < headers.length; ++i) {
|
||||
if(i == null) continue;
|
||||
++hcnt;
|
||||
if(typeof headers[i] !== 'string') throw new Error("DBF Invalid column name");
|
||||
if(headers.indexOf(headers[i]) !== i) for(j=0; j<1024;++j)
|
||||
if(headers.indexOf(headers[i] + "_" + j) == -1) { headers[i] += "_" + j; break; }
|
||||
}
|
||||
var range = safe_decode_range(ws['!ref']);
|
||||
var coltypes = [];
|
||||
for(i = 0; i <= range.e.c - range.s.c; ++i) {
|
||||
var col = [];
|
||||
for(j=0; j < data.length; ++j) {
|
||||
if(data[j][i] != null) col.push(data[j][i]);
|
||||
}
|
||||
if(col.length == 0 || headers[i] == null) { coltypes[i] = '?'; continue; }
|
||||
var guess = '', _guess = '';
|
||||
for(j = 0; j < col.length; ++j) {
|
||||
switch(typeof col[j]) {
|
||||
/* TODO: check if L2 compat is desired */
|
||||
case 'number': _guess = 'B'; break;
|
||||
case 'string': _guess = 'C'; break;
|
||||
case 'boolean': _guess = 'L'; break;
|
||||
case 'object': _guess = col[j] instanceof Date ? 'D' : 'C'; break;
|
||||
default: _guess = 'C';
|
||||
}
|
||||
guess = guess && guess != _guess ? 'C' : _guess;
|
||||
if(guess == 'C') break;
|
||||
}
|
||||
rlen += _RLEN[guess] || 0;
|
||||
coltypes[i] = guess;
|
||||
}
|
||||
|
||||
var h = ba.next(32);
|
||||
h.write_shift(4, 0x13021130);
|
||||
h.write_shift(4, data.length);
|
||||
h.write_shift(2, 296 + 32 * hcnt);
|
||||
h.write_shift(2, rlen);
|
||||
for(i=0; i < 4; ++i) h.write_shift(4, 0);
|
||||
h.write_shift(4, 0x00000300); // TODO: CP
|
||||
|
||||
for(i = 0, j = 0; i < headers.length; ++i) {
|
||||
if(headers[i] == null) continue;
|
||||
var hf = ba.next(32);
|
||||
var _f = (headers[i].slice(-10) + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00").slice(0, 11);
|
||||
hf.write_shift(1, _f, "sbcs");
|
||||
hf.write_shift(1, coltypes[i] == '?' ? 'C' : coltypes[i], "sbcs");
|
||||
hf.write_shift(4, j);
|
||||
hf.write_shift(1, _RLEN[coltypes[i]] || 0);
|
||||
hf.write_shift(1, 0);
|
||||
hf.write_shift(1, 0x02);
|
||||
hf.write_shift(4, 0);
|
||||
hf.write_shift(1, 0);
|
||||
hf.write_shift(4, 0);
|
||||
hf.write_shift(4, 0);
|
||||
j += _RLEN[coltypes[i]] || 0;
|
||||
}
|
||||
|
||||
var hb = ba.next(264);
|
||||
hb.write_shift(4, 0x0000000D);
|
||||
for(i=0; i < 65;++i) hb.write_shift(4, 0x00000000);
|
||||
for(i=0; i < data.length; ++i) {
|
||||
var rout = ba.next(rlen);
|
||||
rout.write_shift(1, 0);
|
||||
for(j=0; j<headers.length; ++j) {
|
||||
if(headers[j] == null) continue;
|
||||
switch(coltypes[j]) {
|
||||
case 'L': rout.write_shift(1, data[i][j] == null ? 0x3F : data[i][j] ? 0x54 : 0x46); break;
|
||||
case 'B': rout.write_shift(8, data[i][j]||0, 'f'); break;
|
||||
case 'D':
|
||||
if(!data[i][j]) rout.write_shift(8, "00000000", "sbcs");
|
||||
else {
|
||||
rout.write_shift(4, ("0000"+data[i][j].getFullYear()).slice(-4), "sbcs");
|
||||
rout.write_shift(2, ("00"+(data[i][j].getMonth()+1)).slice(-2), "sbcs");
|
||||
rout.write_shift(2, ("00"+data[i][j].getDate()).slice(-2), "sbcs");
|
||||
} break;
|
||||
case 'C':
|
||||
var _s = String(data[i][j]||"");
|
||||
rout.write_shift(1, _s, "sbcs");
|
||||
for(hcnt=0; hcnt < 250-_s.length; ++hcnt) rout.write_shift(1, 0x20); break;
|
||||
}
|
||||
}
|
||||
// data
|
||||
}
|
||||
ba.next(1).write_shift(1, 0x1A);
|
||||
return ba.end();
|
||||
}
|
||||
return {
|
||||
to_workbook: dbf_to_workbook,
|
||||
to_sheet: dbf_to_sheet
|
||||
to_sheet: dbf_to_sheet,
|
||||
from_sheet: sheet_to_dbf
|
||||
};
|
||||
})();
|
||||
|
||||
@ -8670,6 +8776,15 @@ function make_vba_xls(cfb) {
|
||||
});
|
||||
return CFB.write(newcfb);
|
||||
}
|
||||
|
||||
function fill_vba_xls(cfb, vba) {
|
||||
vba.FullPaths.forEach(function(p, i) {
|
||||
if(i == 0) return;
|
||||
var newpath = p.replace(/[^/]*[/]/, "/_VBA_PROJECT_CUR/");
|
||||
if(newpath.slice(-1) !== "/") CFB.utils.cfb_add(cfb, newpath, vba.FileIndex[i].content);
|
||||
});
|
||||
}
|
||||
|
||||
RELS.DS = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/dialogsheet";
|
||||
RELS.MS = "http://schemas.microsoft.com/office/2006/relationships/xlMacrosheet";
|
||||
|
||||
@ -14570,10 +14685,10 @@ function safe_format_xf(p, opts, date1904) {
|
||||
else p.w = SSF._general(p.v);
|
||||
}
|
||||
else p.w = SSF.format(fmtid,p.v, {date1904:!!date1904});
|
||||
if(opts.cellDates && fmtid && p.t == 'n' && SSF.is_date(SSF._table[fmtid] || String(fmtid))) {
|
||||
var _d = SSF.parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
|
||||
}
|
||||
} catch(e) { if(opts.WTF) throw e; }
|
||||
if(opts.cellDates && fmtid && p.t == 'n' && SSF.is_date(SSF._table[fmtid] || String(fmtid))) {
|
||||
var _d = SSF.parse_date_code(p.v); if(_d) { p.t = 'd'; p.v = new Date(_d.y, _d.m-1,_d.d,_d.H,_d.M,_d.S,_d.u); }
|
||||
}
|
||||
}
|
||||
|
||||
function make_cell(val, ixfe, t) {
|
||||
@ -15147,7 +15262,7 @@ wb.opts.Date1904 = Workbook.WBProps.date1904 = val; break;
|
||||
/* empty */
|
||||
} break;
|
||||
case 'CodeName': {
|
||||
/* empty */
|
||||
if(!cur_sheet) Workbook.WBProps.codeName = val;
|
||||
} break;
|
||||
case 'GUIDTypeLib': {
|
||||
/* empty */
|
||||
@ -15381,6 +15496,7 @@ function write_xlscfb(wb, opts) {
|
||||
}
|
||||
CFB.utils.cfb_add(cfb, wbpath, write_biff_buf(wb, o));
|
||||
// TODO: SI, DSI, CO
|
||||
if(o.biff == 8 && wb.vbaraw) fill_vba_xls(cfb, CFB.read(wb.vbaraw, {type: typeof wb.vbaraw == "string" ? "binary" : "buffer"}));
|
||||
return cfb;
|
||||
}
|
||||
/* [MS-XLSB] 2.3 Record Enumeration */
|
||||
@ -16777,6 +16893,8 @@ function write_ws_biff8(idx, opts, wb) {
|
||||
write_ws_biff8_cell(ba, cell, R, C, opts);
|
||||
}
|
||||
}
|
||||
var cname = ((((wb||{}).Workbook||{}).Sheets||[])[idx]||{}).name||s;
|
||||
write_biff_rec(ba, "CodeName", write_XLUnicodeString(cname, opts));
|
||||
/* ... */
|
||||
write_biff_rec(ba, "EOF");
|
||||
return ba.end();
|
||||
@ -16796,6 +16914,11 @@ function write_biff8_global(wb, bufs, opts) {
|
||||
write_biff_rec(A, "CodePage", writeuint16(b8 ? 0x04b0 : 0x04E4));
|
||||
if(b8) write_biff_rec(A, "DSF", writeuint16(0));
|
||||
write_biff_rec(A, "RRTabId", write_RRTabId(wb.SheetNames.length));
|
||||
if(b8 && wb.vbaraw) {
|
||||
write_biff_rec(A, "ObProj");
|
||||
var cname = ((wb.Workbook||{}).WBProps||{}).codeName || "ThisWorkbook";
|
||||
write_biff_rec(A, "CodeName", write_XLUnicodeString(cname, opts));
|
||||
}
|
||||
write_biff_rec(A, "BuiltInFnGroupCount", writeuint16(0x11));
|
||||
write_biff_rec(A, "WinProtect", writebool(false));
|
||||
write_biff_rec(A, "Protect", writebool(false));
|
||||
@ -17768,12 +17891,16 @@ var zip = new jszip();
|
||||
return zip;
|
||||
}
|
||||
|
||||
/* actual implementation elsewhere, wrappers are for read/write */
|
||||
function write_sheet_index(wb, sheet) {
|
||||
if(!sheet) return 0;
|
||||
var idx = wb.SheetNames.indexOf(sheet);
|
||||
if(idx == -1) throw new Error("Sheet not found: " + sheet);
|
||||
return idx;
|
||||
}
|
||||
|
||||
function write_obj_str(factory) {
|
||||
return function write_str(wb, o) {
|
||||
var idx = 0;
|
||||
for(var i=0;i<wb.SheetNames.length;++i) if(wb.SheetNames[i] == o.sheet) idx=i;
|
||||
if(idx == 0 && !!o.sheet && wb.SheetNames[0] != o.sheet) throw new Error("Sheet not found: " + o.sheet);
|
||||
var idx = write_sheet_index(wb, o.sheet);
|
||||
return factory.from_sheet(wb.Sheets[wb.SheetNames[idx]], o, wb);
|
||||
};
|
||||
}
|
||||
@ -17785,6 +17912,9 @@ var write_dif_str = write_obj_str(DIF);
|
||||
var write_prn_str = write_obj_str(PRN);
|
||||
var write_rtf_str = write_obj_str(RTF);
|
||||
var write_txt_str = write_obj_str({from_sheet:sheet_to_txt});
|
||||
// $FlowIgnore
|
||||
var write_dbf_buf = write_obj_str(DBF);
|
||||
|
||||
function fix_opts_func(defaults) {
|
||||
return function fix_opts(opts) {
|
||||
for(var i = 0; i != defaults.length; ++i) {
|
||||
@ -18358,13 +18488,15 @@ function writeSync(wb, opts) {
|
||||
case 'txt': return write_stxt_type(write_txt_str(wb, o), o);
|
||||
case 'csv': return write_string_type(write_csv_str(wb, o), o, "\ufeff");
|
||||
case 'dif': return write_string_type(write_dif_str(wb, o), o);
|
||||
// $FlowIgnore
|
||||
case 'dbf': return write_binary_type(write_dbf_buf(wb, o), o);
|
||||
case 'prn': return write_string_type(write_prn_str(wb, o), o);
|
||||
case 'rtf': return write_string_type(write_rtf_str(wb, o), o);
|
||||
case 'fods': return write_string_type(write_ods(wb, o), o);
|
||||
case 'biff2': if(!o.biff) o.biff = 2; /* falls through */
|
||||
case 'biff3': if(!o.biff) o.biff = 3; /* falls through */
|
||||
case 'biff4': if(!o.biff) o.biff = 4; return write_binary_type(write_biff_buf(wb, o), o);
|
||||
case 'biff5': if(!o.biff) o.biff = 5; return write_cfb_type(wb, o);
|
||||
case 'biff5': if(!o.biff) o.biff = 5; /* falls through */
|
||||
case 'biff8':
|
||||
case 'xls': if(!o.biff) o.biff = 8; return write_cfb_type(wb, o);
|
||||
case 'xlsx':
|
||||
@ -18375,26 +18507,17 @@ function writeSync(wb, opts) {
|
||||
}
|
||||
}
|
||||
|
||||
function resolve_book_type(o/*?WriteFileOpts*/) {
|
||||
if(!o.bookType) switch(o.file.slice(o.file.lastIndexOf(".")).toLowerCase()) {
|
||||
case '.xlsx': o.bookType = 'xlsx'; break;
|
||||
case '.xlsm': o.bookType = 'xlsm'; break;
|
||||
case '.xlsb': o.bookType = 'xlsb'; break;
|
||||
case '.fods': o.bookType = 'fods'; break;
|
||||
case '.xlml': o.bookType = 'xlml'; break;
|
||||
case '.sylk': o.bookType = 'sylk'; break;
|
||||
case '.html': o.bookType = 'html'; break;
|
||||
case '.xls': o.bookType = 'biff8'; break;
|
||||
case '.xml': o.bookType = 'xml'; break;
|
||||
case '.ods': o.bookType = 'ods'; break;
|
||||
case '.csv': o.bookType = 'csv'; break;
|
||||
case '.txt': o.bookType = 'txt'; break;
|
||||
case '.dif': o.bookType = 'dif'; break;
|
||||
case '.prn': o.bookType = 'prn'; break;
|
||||
case '.rtf': o.bookType = 'rtf'; break;
|
||||
case '.slk': o.bookType = 'sylk'; break;
|
||||
case '.htm': o.bookType = 'html'; break;
|
||||
}
|
||||
function resolve_book_type(o) {
|
||||
if(o.bookType) return;
|
||||
var _BT = {
|
||||
"xls": "biff8",
|
||||
"htm": "html",
|
||||
"slk": "sylk",
|
||||
"Sh33tJS": "WTF"
|
||||
};
|
||||
var ext = o.file.slice(o.file.lastIndexOf(".")).toLowerCase();
|
||||
if(ext.match(/^\.[a-z]+$/)) o.bookType = ext.slice(1);
|
||||
o.bookType = _BT[o.bookType] || o.bookType;
|
||||
}
|
||||
|
||||
function writeFileSync(wb, filename, opts) {
|
||||
|
24
dist/xlsx.min.js
vendored
24
dist/xlsx.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/xlsx.min.map
vendored
2
dist/xlsx.min.map
vendored
File diff suppressed because one or more lines are too long
@ -2,8 +2,9 @@
|
||||
|
||||
VBA Macros are stored in a special data blob that is exposed in the `vbaraw`
|
||||
property of the workbook object when the `bookVBA` option is `true`. They are
|
||||
supported in `XLSM`, `XLSB`, and `BIFF8 XLS` formats. The `XLSM` and `XLSB`
|
||||
writers automatically insert the data blobs if it is present in the workbook.
|
||||
supported in `XLSM`, `XLSB`, and `BIFF8 XLS` formats. The supported format
|
||||
writers automatically insert the data blobs if it is present in the workbook and
|
||||
associate with the worksheet names.
|
||||
|
||||
<details>
|
||||
<summary><b>Macrosheets</b> (click to show)</summary>
|
||||
|
@ -46,6 +46,7 @@ output formats. The specific file type is controlled with `bookType` option:
|
||||
| `sylk` | `.sylk` | none | single | Symbolic Link (SYLK) |
|
||||
| `html` | `.html` | none | single | HTML Document |
|
||||
| `dif` | `.dif` | none | single | Data Interchange Format (DIF) |
|
||||
| `dbf` | `.dbf` | none | single | dBASE II + VFP Extensions (DBF) |
|
||||
| `rtf` | `.rtf` | none | single | Rich Text Format (RTF) |
|
||||
| `prn` | `.prn` | none | single | Lotus Formatted Text |
|
||||
|
||||
|
@ -23,7 +23,7 @@ Despite the library name `xlsx`, it supports numerous spreadsheet file formats:
|
||||
| OpenDocument Spreadsheet (ODS) | :o: | :o: |
|
||||
| Flat XML ODF Spreadsheet (FODS) | :o: | :o: |
|
||||
| Uniform Office Format Spreadsheet (标文通 UOS1/UOS2) | :o: | |
|
||||
| dBASE II/III/IV / Visual FoxPro (DBF) | :o: | |
|
||||
| dBASE II/III/IV / Visual FoxPro (DBF) | :o: | :o: |
|
||||
| Lotus 1-2-3 (WKS/WK1/WK2/WK3/WK4/123) | :o: | |
|
||||
| Quattro Pro Spreadsheet (WQ1/WQ2/WB1/WB2/WB3/QPW) | :o: | |
|
||||
| **Other Common Spreadsheet Output Formats** |:-----:|:-----:|
|
||||
@ -192,10 +192,12 @@ Many older formats supported only one worksheet:
|
||||
|
||||
DBF is really a typed table format: each column can only hold one data type and
|
||||
each record omits type information. The parser generates a header row and
|
||||
inserts records starting at the second row of the worksheet.
|
||||
inserts records starting at the second row of the worksheet. The writer makes
|
||||
files compatible with Visual FoxPro extensions.
|
||||
|
||||
Multi-file extensions like external memos and tables are currently unsupported,
|
||||
limited by the general ability to read arbitrary files in the web browser.
|
||||
limited by the general ability to read arbitrary files in the web browser. The
|
||||
reader understands DBF Level 7 extensions like DATETIME.
|
||||
|
||||
</details>
|
||||
|
||||
|
@ -72,6 +72,7 @@ digraph G {
|
||||
txt -> csf
|
||||
csf -> txt
|
||||
dbf -> csf
|
||||
csf -> dbf
|
||||
html -> csf
|
||||
csf -> html
|
||||
}
|
||||
|
BIN
formats.png
BIN
formats.png
Binary file not shown.
Before Width: | Height: | Size: 181 KiB After Width: | Height: | Size: 184 KiB |
@ -1319,8 +1319,9 @@ if a sheet is visible is to check if the `Hidden` property is logical truth:
|
||||
|
||||
VBA Macros are stored in a special data blob that is exposed in the `vbaraw`
|
||||
property of the workbook object when the `bookVBA` option is `true`. They are
|
||||
supported in `XLSM`, `XLSB`, and `BIFF8 XLS` formats. The `XLSM` and `XLSB`
|
||||
writers automatically insert the data blobs if it is present in the workbook.
|
||||
supported in `XLSM`, `XLSB`, and `BIFF8 XLS` formats. The supported format
|
||||
writers automatically insert the data blobs if it is present in the workbook and
|
||||
associate with the worksheet names.
|
||||
|
||||
|
||||
Older versions of Excel also supported a non-VBA "macrosheet" sheet type that
|
||||
@ -1508,6 +1509,7 @@ output formats. The specific file type is controlled with `bookType` option:
|
||||
| `sylk` | `.sylk` | none | single | Symbolic Link (SYLK) |
|
||||
| `html` | `.html` | none | single | HTML Document |
|
||||
| `dif` | `.dif` | none | single | Data Interchange Format (DIF) |
|
||||
| `dbf` | `.dbf` | none | single | dBASE II + VFP Extensions (DBF) |
|
||||
| `rtf` | `.rtf` | none | single | Rich Text Format (RTF) |
|
||||
| `prn` | `.prn` | none | single | Lotus Formatted Text |
|
||||
|
||||
@ -1820,7 +1822,7 @@ Despite the library name `xlsx`, it supports numerous spreadsheet file formats:
|
||||
| OpenDocument Spreadsheet (ODS) | :o: | :o: |
|
||||
| Flat XML ODF Spreadsheet (FODS) | :o: | :o: |
|
||||
| Uniform Office Format Spreadsheet (标文通 UOS1/UOS2) | :o: | |
|
||||
| dBASE II/III/IV / Visual FoxPro (DBF) | :o: | |
|
||||
| dBASE II/III/IV / Visual FoxPro (DBF) | :o: | :o: |
|
||||
| Lotus 1-2-3 (WKS/WK1/WK2/WK3/WK4/123) | :o: | |
|
||||
| Quattro Pro Spreadsheet (WQ1/WQ2/WB1/WB2/WB3/QPW) | :o: | |
|
||||
| **Other Common Spreadsheet Output Formats** |:-----:|:-----:|
|
||||
@ -1954,10 +1956,12 @@ Many older formats supported only one worksheet:
|
||||
|
||||
DBF is really a typed table format: each column can only hold one data type and
|
||||
each record omits type information. The parser generates a header row and
|
||||
inserts records starting at the second row of the worksheet.
|
||||
inserts records starting at the second row of the worksheet. The writer makes
|
||||
files compatible with Visual FoxPro extensions.
|
||||
|
||||
Multi-file extensions like external memos and tables are currently unsupported,
|
||||
limited by the general ability to read arbitrary files in the web browser.
|
||||
limited by the general ability to read arbitrary files in the web browser. The
|
||||
reader understands DBF Level 7 extensions like DATETIME.
|
||||
|
||||
|
||||
#### Symbolic Link (SYLK)
|
||||
@ -2248,4 +2252,3 @@ granted by the Apache 2.0 License are reserved by the Original Author.
|
||||
- ISO/IEC 29500:2012(E) "Information technology — Document description and processing languages — Office Open XML File Formats"
|
||||
- Open Document Format for Office Applications Version 1.2 (29 September 2011)
|
||||
- Worksheet File Format (From Lotus) December 1984
|
||||
|
||||
|
@ -86,4 +86,4 @@
|
||||
* [Windows](README.md#windows)
|
||||
* [Tests](README.md#tests)
|
||||
- [License](README.md#license)
|
||||
- [References](README.md#references)
|
||||
- [References](README.md#references)
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xlsx",
|
||||
"version": "0.11.6",
|
||||
"version": "0.11.7",
|
||||
"author": "sheetjs",
|
||||
"description": "SheetJS Spreadsheet data parser and writer",
|
||||
"keywords": [ "excel", "xls", "xlsx", "xlsb", "xlsm", "ods", "csv", "dbf", "dif", "sylk", "office", "spreadsheet" ],
|
||||
@ -20,7 +20,7 @@
|
||||
"exit-on-epipe": "~1.0.1",
|
||||
"ssf": "~0.10.1",
|
||||
"codepage": "~1.11.0",
|
||||
"cfb": "~0.13.1",
|
||||
"cfb": "~0.13.2",
|
||||
"crc-32": "~1.1.1",
|
||||
"adler-32": "~1.1.0",
|
||||
"commander": "~2.11.0"
|
||||
|
30
test.js
30
test.js
@ -22,7 +22,7 @@ var opts = ({cellNF: true}/*:any*/);
|
||||
var TYPE = browser ? "binary" : "buffer";
|
||||
opts.type = TYPE;
|
||||
var fullex = [".xlsb", /*".xlsm",*/ ".xlsx"/*, ".xlml", ".xls"*/];
|
||||
var ofmt = ["xlsb", "xlsm", "xlsx", "ods", "biff2", "biff5", "biff8", "xlml", "sylk", "dif"];
|
||||
var ofmt = ["xlsb", "xlsm", "xlsx", "ods", "biff2", "biff5", "biff8", "xlml", "sylk", "dif", "dbf"];
|
||||
var ex = fullex.slice(); ex = ex.concat([".ods", ".xls", ".xml", ".fods"]);
|
||||
if(typeof process != 'undefined' && ((process||{}).env)) {
|
||||
opts.WTF = true;
|
||||
@ -505,7 +505,7 @@ describe('parse options', function() {
|
||||
X.utils.sheet_to_csv(wb.Sheets.Merge);
|
||||
X.utils.sheet_to_json(wb.Sheets.Merge);
|
||||
X.utils.sheet_to_formulae(wb.Sheets.Merge);
|
||||
ofmt.forEach(function(f) { X.write(wb, {type:TYPE, bookType:f}); });
|
||||
ofmt.forEach(function(f) { if(f != "dbf") X.write(wb, {type:TYPE, bookType:f}); });
|
||||
});
|
||||
});
|
||||
function checkcells(wb, A46, B26, C16, D2) {
|
||||
@ -625,6 +625,7 @@ describe('output formats', function() {
|
||||
["sylk", false, true],
|
||||
["html", true, true],
|
||||
["dif", false, true],
|
||||
["dbf", false, false],
|
||||
["prn", false, true]
|
||||
];
|
||||
function RT(T) {
|
||||
@ -764,7 +765,7 @@ describe('parse features', function() {
|
||||
|
||||
describe('comments', function() {
|
||||
if(fs.existsSync(paths.swcxlsx)) it('should have comment as part of cell properties', function(){
|
||||
var X = require(modp);
|
||||
X = require(modp);
|
||||
var sheet = 'Sheet1';
|
||||
var wb1=X.read(fs.readFileSync(paths.swcxlsx), {type:TYPE});
|
||||
var wb2=X.read(fs.readFileSync(paths.swcxlsb), {type:TYPE});
|
||||
@ -1867,10 +1868,11 @@ describe('js -> file -> js', function() {
|
||||
var wb, BIN="binary";
|
||||
var bef = (function() {
|
||||
var ws = X.utils.aoa_to_sheet([
|
||||
[1,2,3],
|
||||
[true, false, null, "sheetjs"],
|
||||
["foo", "bar", fixdate, "0.3"],
|
||||
["baz", 6.9, "qux"]
|
||||
["number", "bool", "string", "date"],
|
||||
[1, true, "sheet"],
|
||||
[2, false, "dot"],
|
||||
[6.9, false, "JS", fixdate],
|
||||
[72.62, true, "0.3"]
|
||||
]);
|
||||
wb = { SheetNames: ['Sheet1'], Sheets: {Sheet1: ws} };
|
||||
});
|
||||
@ -1884,13 +1886,13 @@ describe('js -> file -> js', function() {
|
||||
it(f, function() {
|
||||
var newwb = X.read(X.write(wb, {type:BIN, bookType: f}), {type:BIN});
|
||||
var cb = function(cell) { eqcell(wb, newwb, 'Sheet1', cell); };
|
||||
['A1', 'B1', 'C1'].forEach(cb); /* int */
|
||||
['B4'].forEach(cb); /* double */
|
||||
['A2', 'B2'].forEach(cb); /* bool */
|
||||
['D2', 'A3', 'B3', 'A4', 'C4'].forEach(cb); /* string */
|
||||
if(!DIF_XL) cb('C3'); /* date */
|
||||
if(DIF_XL && f == "dif") assert.equal(get_cell(newwb.Sheets.Sheet1, 'D3').v, '=""0.3""');// dif forces string formula
|
||||
else eqcell(wb, newwb, 'Sheet1', 'D3');
|
||||
['A2', 'A3'].forEach(cb); /* int */
|
||||
['A4', 'A5'].forEach(cb); /* double */
|
||||
['B2', 'B3'].forEach(cb); /* bool */
|
||||
['C2', 'C3'].forEach(cb); /* string */
|
||||
if(!DIF_XL) cb('D4'); /* date */
|
||||
if(DIF_XL && f == "dif") assert.equal(get_cell(newwb.Sheets.Sheet1, 'C5').v, '=""0.3""');// dif forces string formula
|
||||
else eqcell(wb, newwb, 'Sheet1', 'C5');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -22,7 +22,7 @@ var opts = ({cellNF: true}/*:any*/);
|
||||
var TYPE = browser ? "binary" : "buffer";
|
||||
opts.type = TYPE;
|
||||
var fullex = [".xlsb", /*".xlsm",*/ ".xlsx"/*, ".xlml", ".xls"*/];
|
||||
var ofmt = ["xlsb", "xlsm", "xlsx", "ods", "biff2", "biff5", "biff8", "xlml", "sylk", "dif"];
|
||||
var ofmt = ["xlsb", "xlsm", "xlsx", "ods", "biff2", "biff5", "biff8", "xlml", "sylk", "dif", "dbf"];
|
||||
var ex = fullex.slice(); ex = ex.concat([".ods", ".xls", ".xml", ".fods"]);
|
||||
if(typeof process != 'undefined' && ((process||{}).env)) {
|
||||
opts.WTF = true;
|
||||
@ -505,7 +505,7 @@ describe('parse options', function() {
|
||||
X.utils.sheet_to_csv(wb.Sheets.Merge);
|
||||
X.utils.sheet_to_json(wb.Sheets.Merge);
|
||||
X.utils.sheet_to_formulae(wb.Sheets.Merge);
|
||||
ofmt.forEach(function(f) { X.write(wb, {type:TYPE, bookType:f}); });
|
||||
ofmt.forEach(function(f) { if(f != "dbf") X.write(wb, {type:TYPE, bookType:f}); });
|
||||
});
|
||||
});
|
||||
function checkcells(wb, A46, B26, C16, D2) {
|
||||
@ -541,6 +541,7 @@ describe('parse options', function() {
|
||||
});
|
||||
it('bookProps && bookSheets should not generate sheets', function() {
|
||||
PMPaths.forEach(function(p) {
|
||||
if(!fs.existsSync(p)) return;
|
||||
var wb = X.read(fs.readFileSync(p), {type:TYPE, bookProps:true, bookSheets:true});
|
||||
assert(typeof wb.Sheets === 'undefined');
|
||||
});
|
||||
@ -624,6 +625,7 @@ describe('output formats', function() {
|
||||
["sylk", false, true],
|
||||
["html", true, true],
|
||||
["dif", false, true],
|
||||
["dbf", false, false],
|
||||
["prn", false, true]
|
||||
];
|
||||
function RT(T) {
|
||||
@ -763,7 +765,7 @@ describe('parse features', function() {
|
||||
|
||||
describe('comments', function() {
|
||||
if(fs.existsSync(paths.swcxlsx)) it('should have comment as part of cell properties', function(){
|
||||
var X = require(modp);
|
||||
X = require(modp);
|
||||
var sheet = 'Sheet1';
|
||||
var wb1=X.read(fs.readFileSync(paths.swcxlsx), {type:TYPE});
|
||||
var wb2=X.read(fs.readFileSync(paths.swcxlsb), {type:TYPE});
|
||||
@ -1866,10 +1868,11 @@ describe('js -> file -> js', function() {
|
||||
var wb, BIN="binary";
|
||||
var bef = (function() {
|
||||
var ws = X.utils.aoa_to_sheet([
|
||||
[1,2,3],
|
||||
[true, false, null, "sheetjs"],
|
||||
["foo", "bar", fixdate, "0.3"],
|
||||
["baz" |