forked from sheetjs/sheetjs
Compare commits
104 Commits
master
...
protobi/ma
Author | SHA1 | Date | |
---|---|---|---|
|
8f7a29464d | ||
|
6d0f51fc98 | ||
|
6226e1afe8 | ||
|
92333227c4 | ||
|
c86472d281 | ||
|
f2520b7223 | ||
|
68ba4e8f58 | ||
|
c224819b16 | ||
|
a03dc219ab | ||
|
f959b02ae9 | ||
|
9edf279467 | ||
|
1903cff791 | ||
|
6e6678960c | ||
|
d5092b42cb | ||
|
d3f63434a0 | ||
|
796fbb515a | ||
|
3c7f807bfa | ||
|
34d618c8fe | ||
|
245ffb895a | ||
|
8198744d58 | ||
|
2424890518 | ||
|
0b8e5386bb | ||
|
eef7da3099 | ||
|
876c4a0552 | ||
|
bed6327d22 | ||
|
2ec18e96ba | ||
|
050b74edbf | ||
|
0e62411e83 | ||
|
aceebf4690 | ||
|
9407fe8aeb | ||
|
166d0e33bf | ||
|
fe748adc01 | ||
|
f984bd6479 | ||
|
7de41c2657 | ||
|
0bf1153da5 | ||
|
376096b151 | ||
|
bbeec3edfd | ||
|
43f569884a | ||
|
d4e0b8b172 | ||
|
634699fb16 | ||
|
2886195440 | ||
|
8b1add6659 | ||
|
fd83f20b40 | ||
|
03b755b3ae | ||
|
d00f36f94f | ||
|
599f285dfd | ||
|
905c51206b | ||
|
7461389d49 | ||
|
57b6fd4662 | ||
|
348c533f6c | ||
|
3e3633ad52 | ||
|
d76234ae80 | ||
|
0d1281cc94 | ||
|
dcf6f17455 | ||
|
f52c80eef6 | ||
|
e7b06d7a62 | ||
|
1ca3c3e6b5 | ||
|
c034eda675 | ||
|
3010d93f40 | ||
|
d60a0a5b89 | ||
|
a6023550ee | ||
|
9145958b40 | ||
|
0096c09dd3 | ||
|
8801e76e3f | ||
|
0255a05f14 | ||
|
4099a24cfa | ||
|
ed0cd9b2c1 | ||
|
858abf1103 | ||
|
21e1976f82 | ||
|
40cfb0cf8f | ||
|
acf60c22bc | ||
|
c2873831ca | ||
|
5dbf215c9c | ||
|
89066b45b6 | ||
|
51b7cabd2c | ||
|
08e648bbb5 | ||
|
0b1a0408cb | ||
|
5f9576a6d2 | ||
|
114f257ce4 | ||
|
9102c8214d | ||
|
8da3738378 | ||
|
995f5e89bf | ||
|
37a031caee | ||
|
27a300b862 | ||
|
33c32f0647 | ||
|
4f4f7fc6bc | ||
|
ad2a1203f1 | ||
|
0e2b8a499d | ||
|
1a51c40423 | ||
|
9b76f6b1f5 | ||
|
aa8f3a759f | ||
|
33dc7b883d | ||
|
97d4001343 | ||
|
c3af249415 | ||
|
5e443310f8 | ||
|
91ec052ae6 | ||
|
1f02e5bea2 | ||
|
05b58d839a | ||
|
576b59f96a | ||
|
cd2b20f7e5 | ||
|
5f7a0f2ad2 | ||
|
a562150b96 | ||
|
845d2a8880 | ||
|
0227496616 |
BIN
.DS_Store
vendored
Normal file
BIN
.DS_Store
vendored
Normal file
Binary file not shown.
6
.gitignore
vendored
6
.gitignore
vendored
@ -19,3 +19,9 @@ tmp
|
||||
*.htm
|
||||
*.html
|
||||
*.sheetjs
|
||||
|
||||
lab/
|
||||
test_files
|
||||
example.js
|
||||
example2.js
|
||||
.idea
|
||||
|
197
README.md
197
README.md
@ -1,7 +1,18 @@
|
||||
# xlsx
|
||||
# xlsx-style
|
||||
|
||||
Parser and writer for various spreadsheet formats. Pure-JS cleanroom
|
||||
implementation from official specifications and related documents.
|
||||
Parser and writer for various spreadsheet formats. Pure-JS cleanroom implementation from official specifications and related documents.
|
||||
|
||||
# About this fork
|
||||
**NOTE:** [This project](https://github.com/SheetJS/js-xlsx/tree/beta) is a fork of the original (and awesome) [SheetJS/xlsx](https://github.com/SheetJS/js-xlsx) project.
|
||||
It is extended to enable cell formats to be read from and written to .xlsx workbooks.
|
||||
The intent is to provide a temporary means of using these features in practice, and ultimately to merge this into the primary project.
|
||||
Report any issues to https://github.com/protobi/js-xlsx/issues.
|
||||
|
||||
For those contributing to this fork:
|
||||
* `master` is the main branch, which follows the original repo to enable a future pull request.
|
||||
* `beta` branch is published to npm and bower to make this fork available for use.
|
||||
|
||||
# Supported formats
|
||||
|
||||
Supported read formats:
|
||||
|
||||
@ -24,17 +35,23 @@ Source: <http://git.io/xlsx>
|
||||
|
||||
## Installation
|
||||
|
||||
With [npm](https://www.npmjs.org/package/xlsx):
|
||||
With [npm](https://www.npmjs.org/package/xlsx-style):
|
||||
|
||||
npm install xlsx
|
||||
```sh
|
||||
npm install xlsx-style --save
|
||||
```
|
||||
|
||||
In the browser:
|
||||
|
||||
<script lang="javascript" src="dist/xlsx.core.min.js"></script>
|
||||
```html
|
||||
<script lang="javascript" src="dist/xlsx.core.min.js"></script>
|
||||
```
|
||||
|
||||
With [bower](http://bower.io/search/?q=js-xlsx):
|
||||
|
||||
bower install js-xlsx
|
||||
```sh
|
||||
bower install js-xlsx-style#beta
|
||||
```
|
||||
|
||||
CDNjs automatically pulls the latest version and makes all versions available at
|
||||
<http://cdnjs.com/libraries/xlsx>
|
||||
@ -46,10 +63,12 @@ of these modules are rather large in size and are only needed in special
|
||||
circumstances, so they do not ship with the core. For browser use, they must
|
||||
be included directly:
|
||||
|
||||
<!-- international support from https://github.com/sheetjs/js-codepage -->
|
||||
<script src="dist/cpexcel.js"></script>
|
||||
<!-- ODS support -->
|
||||
<script src="dist/ods.js"></script>
|
||||
```html
|
||||
<!-- international support from https://github.com/sheetjs/js-codepage -->
|
||||
<script src="dist/cpexcel.js"></script>
|
||||
<!-- ODS support -->
|
||||
<script src="dist/ods.js"></script>
|
||||
```
|
||||
|
||||
An appropriate version for each dependency is included in the dist/ directory.
|
||||
|
||||
@ -63,7 +82,9 @@ Since xlsx.js uses ES5 functions like `Array#forEach`, older browsers require
|
||||
|
||||
To use the shim, add the shim before the script tag that loads xlsx.js:
|
||||
|
||||
<script type="text/javascript" src="/path/to/shim.js"></script>
|
||||
```html
|
||||
<script type="text/javascript" src="/path/to/shim.js"></script>
|
||||
```
|
||||
|
||||
## Parsing Workbooks
|
||||
|
||||
@ -72,7 +93,7 @@ data and feeding it into the library. Here are a few common scenarios:
|
||||
|
||||
- node readFile:
|
||||
|
||||
```
|
||||
```js
|
||||
if(typeof require !== 'undefined') XLSX = require('xlsx');
|
||||
var workbook = XLSX.readFile('test.xlsx');
|
||||
/* DO SOMETHING WITH workbook HERE */
|
||||
@ -81,10 +102,11 @@ var workbook = XLSX.readFile('test.xlsx');
|
||||
- ajax (for a more complete example that works in older browsers, check the demo
|
||||
at <http://oss.sheetjs.com/js-xlsx/ajax.html>):
|
||||
|
||||
```
|
||||
```js
|
||||
/* set up XMLHttpRequest */
|
||||
var url = "test_files/formula_stress_test_ajax.xlsx";
|
||||
var oReq = new XMLHttpRequest();
|
||||
|
||||
oReq.open("GET", url, true);
|
||||
oReq.responseType = "arraybuffer";
|
||||
|
||||
@ -108,13 +130,14 @@ oReq.send();
|
||||
|
||||
- HTML5 drag-and-drop using readAsBinaryString:
|
||||
|
||||
```
|
||||
```js
|
||||
/* set up drag-and-drop event */
|
||||
function handleDrop(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
var files = e.dataTransfer.files;
|
||||
var i,f;
|
||||
var i, f;
|
||||
|
||||
for (i = 0, f = files[i]; i != files.length; ++i) {
|
||||
var reader = new FileReader();
|
||||
var name = f.name;
|
||||
@ -134,10 +157,11 @@ drop_dom_element.addEventListener('drop', handleDrop, false);
|
||||
|
||||
- HTML5 input file element using readAsBinaryString:
|
||||
|
||||
```
|
||||
```js
|
||||
function handleFile(e) {
|
||||
var files = e.target.files;
|
||||
var i,f;
|
||||
var i, f;
|
||||
|
||||
for (i = 0, f = files[i]; i != files.length; ++i) {
|
||||
var reader = new FileReader();
|
||||
var name = f.name;
|
||||
@ -160,7 +184,7 @@ The full object format is described later in this README.
|
||||
|
||||
This example extracts the value stored in cell A1 from the first worksheet:
|
||||
|
||||
```
|
||||
```js
|
||||
var first_sheet_name = workbook.SheetNames[0];
|
||||
var address_of_cell = 'A1';
|
||||
|
||||
@ -176,8 +200,9 @@ var desired_value = desired_cell.v;
|
||||
|
||||
This example iterates through every nonempty of every sheet and dumps values:
|
||||
|
||||
```
|
||||
```js
|
||||
var sheet_name_list = workbook.SheetNames;
|
||||
|
||||
sheet_name_list.forEach(function(y) { /* iterate through sheets */
|
||||
var worksheet = workbook.Sheets[y];
|
||||
for (z in worksheet) {
|
||||
@ -195,7 +220,9 @@ Complete examples:
|
||||
Note that older versions of IE does not support HTML5 File API, so the base64
|
||||
mode is provided for testing. On OSX you can get the base64 encoding with:
|
||||
|
||||
$ <target_file.xlsx base64 | pbcopy
|
||||
```sh
|
||||
$ <target_file.xlsx base64 | pbcopy
|
||||
```
|
||||
|
||||
- <http://oss.sheetjs.com/js-xlsx/ajax.html> XMLHttpRequest
|
||||
|
||||
@ -220,7 +247,7 @@ Assuming `workbook` is a workbook object:
|
||||
|
||||
- nodejs write to file:
|
||||
|
||||
```
|
||||
```js
|
||||
/* output format determined by filename */
|
||||
XLSX.writeFile(workbook, 'out.xlsx');
|
||||
/* at this point, out.xlsx is a file that you can distribute */
|
||||
@ -228,7 +255,7 @@ XLSX.writeFile(workbook, 'out.xlsx');
|
||||
|
||||
- write to binary string (using FileSaver.js):
|
||||
|
||||
```
|
||||
```js
|
||||
/* bookType can be 'xlsx' or 'xlsm' or 'xlsb' */
|
||||
var wopts = { bookType:'xlsx', bookSST:false, type:'binary' };
|
||||
|
||||
@ -303,7 +330,7 @@ Cell range objects are stored as `{s:S, e:E}` where `S` is the first cell and
|
||||
range `A3:B7` is represented by the object `{s:{c:0, r:2}, e:{c:1, r:6}}`. Utils
|
||||
use the following pattern to walk each of the cells in a range:
|
||||
|
||||
```
|
||||
```js
|
||||
for(var R = range.s.r; R <= range.e.r; ++R) {
|
||||
for(var C = range.s.c; C <= range.e.c; ++C) {
|
||||
var cell_address = {c:C, r:R};
|
||||
@ -331,6 +358,9 @@ is available. To change a value, be sure to delete `cell.w` (or set it to
|
||||
`undefined`) before attempting to export. The utilities will regenerate the `w`
|
||||
text from the number format (`cell.z`) and the raw value if possible.
|
||||
|
||||
**Note**: The .z attribute is now deprecated. Use the `.s` attribute to specify cell styles including number formats.
|
||||
To specify a number format, use `s.numFmt`, e.g. `{v: 42145.822, s: { numFmt: "m/dd/yy"}}` described below.
|
||||
|
||||
### Data Types
|
||||
|
||||
The raw value is stored in the `v` field, interpreted based on the `t` field.
|
||||
@ -400,14 +430,39 @@ Special worksheet keys (accessible as `worksheet[key]`, each starting with `!`):
|
||||
will write all cells in the merge range if they exist, so be sure that only
|
||||
the first cell (upper-left) in the range is set.
|
||||
|
||||
- `ws['!printHeader']`: array of row indices for repeating row headers on print, e.g. `[1:1]` to repeat just the first row.
|
||||
|
||||
The following properties are currently used when generating an XLSX file, but not yet parsed:
|
||||
|
||||
- `ws['!rowBreaks']`: array of row break points, e.g. `[16,32]`
|
||||
- `ws['!colBreaks']`: array of col break points, e.g. `[8,16]`
|
||||
- `ws['!pageSetup']`: `{scale: '100', orientation: 'portrait'||'landscape'}
|
||||
- `ws['!printHeader']`: array of first and last row indexes for repeat header on printing, e.g. `[1,1]` to repeat just first row
|
||||
- `ws['!freeze']`: string cell reference for breakpoint, e.g. the following will freeze the first row and first column:
|
||||
{
|
||||
xSplit: "1",
|
||||
ySplit: "1",
|
||||
topLeftCell: "B2",
|
||||
activePane: "bottomRight",
|
||||
state: "frozen"
|
||||
}
|
||||
|
||||
|
||||
### Workbook Object
|
||||
|
||||
`workbook.SheetNames` is an ordered list of the sheets in the workbook
|
||||
|
||||
`wb.Sheets[sheetname]` returns an object representing the worksheet.
|
||||
|
||||
`wb.Props` is an object storing the standard properties. `wb.Custprops` stores
|
||||
custom properties. Since the XLS standard properties deviate from the XLSX
|
||||
`wb.Props` is an object storing the standard properties. The following properties are currently used when
|
||||
generating an XLSX file, but not yet parsed:
|
||||
- `title`
|
||||
- `subject`
|
||||
- `description`
|
||||
- `keywords`
|
||||
- `creator`
|
||||
|
||||
`wb.Custprops` stores custom properties. Since the XLS standard properties deviate from the XLSX
|
||||
standard, XLS parsing stores core properties in both places. .
|
||||
|
||||
|
||||
@ -459,6 +514,12 @@ The exported `write` and `writeFile` functions accept an options argument:
|
||||
| cellDates | false | Store dates as type `d` (default is `n`) |
|
||||
| bookSST | false | Generate Shared String Table ** |
|
||||
| bookType | 'xlsx' | Type of Workbook ("xlsx" or "xlsm" or "xlsb") |
|
||||
| showGridLines | true | Show gridlines on all pages |
|
||||
| tabSelected | '1' | Initial tab selected |
|
||||
| Props | null | Workbook properties |
|
||||
|
||||
|
||||
|
||||
|
||||
- `bookSST` is slower and more memory intensive, but has better compatibility
|
||||
with older versions of iOS Numbers
|
||||
@ -468,6 +529,84 @@ The exported `write` and `writeFile` functions accept an options argument:
|
||||
- `cellDates` only applies to XLSX output and is not guaranteed to work with
|
||||
third-party readers. Excel itself does not usually write cells with type `d`
|
||||
so non-Excel tools may ignore the data or blow up in the presence of dates.
|
||||
- showGridLines and tabSelected are currently used when generating an XLSX file but not yet parse.
|
||||
- Props specifies workbook properties
|
||||
|
||||
|
||||
|
||||
|
||||
## Cell Styles
|
||||
|
||||
Cell styles are specified by a style object that roughly parallels the OpenXML structure. The style object has five
|
||||
top-level attributes: `fill`, `font`, `numFmt`, `alignment`, and `border`.
|
||||
|
||||
|
||||
| Style Attribute | Sub Attributes | Values |
|
||||
| :-------------- | :------------- | :------------- |
|
||||
| fill | patternType | `"solid"` or `"none"`
|
||||
| | fgColor | `COLOR_SPEC`
|
||||
| | bgColor | `COLOR_SPEC`
|
||||
| font | name | `"Calibri"` // default
|
||||
| | sz | `"11"` // font size in points
|
||||
| | color | `COLOR_SPEC`
|
||||
| | bold | `true` or `false`
|
||||
| | underline | `true` or `false`
|
||||
| | italic | `true` or `false`
|
||||
| | strike | `true` or `false`
|
||||
| | outline | `true` or `false`
|
||||
| | shadow | `true` or `false`
|
||||
| | vertAlign | `true` or `false`
|
||||
| numFmt | | `"0"` // integer index to built in formats, see StyleBuilder.SSF property
|
||||
| | | `"0.00%"` // string matching a built-in format, see StyleBuilder.SSF
|
||||
| | | `"0.0%"` // string specifying a custom format
|
||||
| | | `"0.00%;\\(0.00%\\);\\-;@"` // string specifying a custom format, escaping special characters
|
||||
| | | `"m/dd/yy"` // string a date format using Excel's format notation
|
||||
| alignment | vertical | `"bottom"` or `"center"` or `"top"`
|
||||
| | horizontal | `"left"` or `"center"` or `"right"`
|
||||
| | wrapText | `true ` or ` false`
|
||||
| | readingOrder | `2` // for right-to-left
|
||||
| | textRotation | Number from `0` to `180` or `255` (default is `0`)
|
||||
| | | `90` is rotated up 90 degrees
|
||||
| | | `45` is rotated up 45 degrees
|
||||
| | | `135` is rotated down 45 degrees
|
||||
| | | `180` is rotated down 180 degrees
|
||||
| | | `255` is special, aligned vertically
|
||||
| border | top | `{ style: BORDER_STYLE, color: COLOR_SPEC }`
|
||||
| | bottom | `{ style: BORDER_STYLE, color: COLOR_SPEC }`
|
||||
| | left | `{ style: BORDER_STYLE, color: COLOR_SPEC }`
|
||||
| | right | `{ style: BORDER_STYLE, color: COLOR_SPEC }`
|
||||
| | diagonal | `{ style: BORDER_STYLE, color: COLOR_SPEC }`
|
||||
| | diagonalUp | `true` or `false`
|
||||
| | diagonalDown | `true` or `false`
|
||||
|
||||
**COLOR_SPEC**: Colors for `fill`, `font`, and `border` are specified as objects, either:
|
||||
* `{ auto: 1}` specifying automatic values
|
||||
* `{ rgb: "FFFFAA00" }` specifying a hex ARGB value
|
||||
* `{ theme: "1", tint: "-0.25"}` specifying an integer index to a theme color and a tint value (default 0)
|
||||
* `{ indexed: 64}` default value for `fill.bgColor`
|
||||
|
||||
**BORDER_STYLE**: Border style is a string value which may take on one of the following values:
|
||||
* `thin`
|
||||
* `medium`
|
||||
* `thick`
|
||||
* `dotted`
|
||||
* `hair`
|
||||
* `dashed`
|
||||
* `mediumDashed`
|
||||
* `dashDot`
|
||||
* `mediumDashDot`
|
||||
* `dashDotDot`
|
||||
* `mediumDashDotDot`
|
||||
* `slantDashDot`
|
||||
|
||||
|
||||
Borders for merged areas are specified for each cell within the merged area. So to apply a box border to a merged area of 3x3 cells, border styles would need to be specified for eight different cells:
|
||||
* left borders for the three cells on the left,
|
||||
* right borders for the cells on the right
|
||||
* top borders for the cells on the top
|
||||
* bottom borders for the cells on the left
|
||||
|
||||
|
||||
|
||||
## Tested Environments
|
||||
|
||||
@ -494,7 +633,7 @@ Running `make init` will refresh the `test_files` submodule and get the files.
|
||||
[the oss.sheetjs.com repo](https://github.com/SheetJS/SheetJS.github.io) and
|
||||
replace the xlsx.js file (then fire up the browser and go to `stress.html`):
|
||||
|
||||
```
|
||||
```sh
|
||||
$ cp xlsx.js ../SheetJS.github.io
|
||||
$ cd ../SheetJS.github.io
|
||||
$ simplehttpserver # or "python -mSimpleHTTPServer" or "serve"
|
||||
@ -513,7 +652,7 @@ build script (run `make`) will concatenate the individual bits to produce the
|
||||
script. Before submitting a contribution, ensure that running make will produce
|
||||
the xlsx.js file exactly. The simplest way to test is to move the script:
|
||||
|
||||
```
|
||||
```sh
|
||||
$ mv xlsx.js xlsx.new.js
|
||||
$ make
|
||||
$ diff xlsx.js xlsx.new.js
|
||||
@ -564,5 +703,3 @@ Open Document Format for Office Applications Version 1.2 (29 September 2011)
|
||||
[![Build Status](https://travis-ci.org/SheetJS/js-xlsx.svg?branch=master)](https://travis-ci.org/SheetJS/js-xlsx)
|
||||
|
||||
[![Coverage Status](http://img.shields.io/coveralls/SheetJS/js-xlsx/master.svg)](https://coveralls.io/r/SheetJS/js-xlsx?branch=master)
|
||||
|
||||
[![githalytics.com alpha](https://cruel-carlota.pagodabox.com/ed5bb2c4c4346a474fef270f847f3f78 "githalytics.com")](http://githalytics.com/SheetJS/js-xlsx)
|
||||
|
@ -1 +1 @@
|
||||
XLSX.version = '0.8.0';
|
||||
XLSX.version = '0.8.20';
|
||||
|
@ -15,8 +15,14 @@ function getdata(data) {
|
||||
|
||||
function safegetzipfile(zip, file) {
|
||||
var f = file; if(zip.files[f]) return zip.files[f];
|
||||
f = file.toLowerCase(); if(zip.files[f]) return zip.files[f];
|
||||
f = f.replace(/\//g,'\\'); if(zip.files[f]) return zip.files[f];
|
||||
|
||||
var lowerCaseFiles = {};
|
||||
for (var key in zip.files) {
|
||||
lowerCaseFiles[key.toLowerCase()] = zip.files[key];
|
||||
}
|
||||
|
||||
f = file.toLowerCase(); if(lowerCaseFiles[f]) return lowerCaseFiles[f];
|
||||
f = f.replace(/\//g,'\\'); if(lowerCaseFiles[f]) return lowerCaseFiles[f];
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -60,13 +60,20 @@ function cp_doit(f, g, h, o, p) {
|
||||
|
||||
function write_core_props(cp, opts) {
|
||||
var o = [XML_HEADER, CORE_PROPS_XML_ROOT], p = {};
|
||||
if(!cp) return o.join("");
|
||||
if (opts && opts.Props) {
|
||||
if (opts.Props.title) o[o.length] = '<dc:title>' + opts.Props.title + '</dc:title>';
|
||||
if (opts.Props.subject) o[o.length] = '<dc:subject>' + opts.Props.subject + '</dc:subject>';
|
||||
if (opts.Props.creator) o[o.length] = '<dc:creator>' + opts.Props.creator + '</dc:creator>';
|
||||
if (opts.Props.keywords) o[o.length] = '<cp:keywords>' + opts.Props.keywords + '</cp:keywords>';
|
||||
if (opts.Props.description) o[o.length] = '<dc:description>' + opts.Props.description + '</dc:description>';
|
||||
}
|
||||
if(cp) {
|
||||
|
||||
if(cp.CreatedDate != null) cp_doit("dcterms:created", typeof cp.CreatedDate === "string" ? cp.CreatedDate : write_w3cdtf(cp.CreatedDate, opts.WTF), {"xsi:type":"dcterms:W3CDTF"}, o, p);
|
||||
if(cp.ModifiedDate != null) cp_doit("dcterms:modified", typeof cp.ModifiedDate === "string" ? cp.ModifiedDate : write_w3cdtf(cp.ModifiedDate, opts.WTF), {"xsi:type":"dcterms:W3CDTF"}, o, p);
|
||||
|
||||
if(cp.CreatedDate != null) cp_doit("dcterms:created", typeof cp.CreatedDate === "string" ? cp.CreatedDate : write_w3cdtf(cp.CreatedDate, opts.WTF), {"xsi:type":"dcterms:W3CDTF"}, o, p);
|
||||
if(cp.ModifiedDate != null) cp_doit("dcterms:modified", typeof cp.ModifiedDate === "string" ? cp.ModifiedDate : write_w3cdtf(cp.ModifiedDate, opts.WTF), {"xsi:type":"dcterms:W3CDTF"}, o, p);
|
||||
|
||||
for(var i = 0; i != CORE_PROPS.length; ++i) { var f = CORE_PROPS[i]; cp_doit(f[0], cp[f[1]], null, o, p); }
|
||||
if(o.length>2){ o[o.length] = ('</cp:coreProperties>'); o[1]=o[1].replace("/>",">"); }
|
||||
return o.join("");
|
||||
for(var i = 0; i != CORE_PROPS.length; ++i) { var f = CORE_PROPS[i]; cp_doit(f[0], cp[f[1]], null, o, p); }
|
||||
}
|
||||
if(o.length>2){ o[o.length] = ('</cp:coreProperties>'); o[1]=o[1].replace("/>",">"); }
|
||||
return o.join("");
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
function hex2RGB(h) {
|
||||
var o = h.substr(h[0]==="#"?1:0,6);
|
||||
return [parseInt(o.substr(0,2),16),parseInt(o.substr(0,2),16),parseInt(o.substr(0,2),16)];
|
||||
return [parseInt(o.substr(0,2),16),parseInt(o.substr(2,2),16),parseInt(o.substr(4,2),16)];
|
||||
}
|
||||
function rgb2Hex(rgb) {
|
||||
for(var i=0,o=1; i!=3; ++i) o = o*256 + (rgb[i]>255?255:rgb[i]<0?0:rgb[i]);
|
||||
@ -42,11 +42,12 @@ function hsl2RGB(hsl){
|
||||
|
||||
/* 18.8.3 bgColor tint algorithm */
|
||||
function rgb_tint(hex, tint) {
|
||||
if(tint === 0) return hex;
|
||||
if(tint == 0) return hex;
|
||||
var hsl = rgb2HSL(hex2RGB(hex));
|
||||
if (tint < 0) hsl[2] = hsl[2] * (1 + tint);
|
||||
else hsl[2] = 1 - (1 - hsl[2]) * (1 - tint);
|
||||
return rgb2Hex(hsl2RGB(hsl));
|
||||
var rev =rgb2Hex(hsl2RGB(hsl))
|
||||
return rev;
|
||||
}
|
||||
|
||||
/* 18.3.1.13 width calculations */
|
||||
|
@ -1,169 +1,400 @@
|
||||
/* 18.8.21 fills CT_Fills */
|
||||
function parse_fills(t, opts) {
|
||||
styles.Fills = [];
|
||||
var fill = {};
|
||||
t[0].match(tagregex).forEach(function(x) {
|
||||
var y = parsexmltag(x);
|
||||
switch(y[0]) {
|
||||
case '<fills': case '<fills>': case '</fills>': break;
|
||||
styles.Fills = [];
|
||||
var fill = {};
|
||||
t[0].match(tagregex).forEach(function (x) {
|
||||
var y = parsexmltag(x);
|
||||
switch (y[0]) {
|
||||
case '<fills':
|
||||
case '<fills>':
|
||||
case '</fills>':
|
||||
break;
|
||||
|
||||
/* 18.8.20 fill CT_Fill */
|
||||
case '<fill>': break;
|
||||
case '</fill>': styles.Fills.push(fill); fill = {}; break;
|
||||
/* 18.8.20 fill CT_Fill */
|
||||
case '<fill>':
|
||||
break;
|
||||
case '</fill>':
|
||||
styles.Fills.push(fill);
|
||||
fill = {};
|
||||
break;
|
||||
|
||||
/* 18.8.32 patternFill CT_PatternFill */
|
||||
case '<patternFill':
|
||||
if(y.patternType) fill.patternType = y.patternType;
|
||||
break;
|
||||
case '<patternFill/>': case '</patternFill>': break;
|
||||
/* 18.8.32 patternFill CT_PatternFill */
|
||||
case '<patternFill':
|
||||
if (y.patternType) fill.patternType = y.patternType;
|
||||
break;
|
||||
case '<patternFill/>':
|
||||
case '</patternFill>':
|
||||
break;
|
||||
|
||||
/* 18.8.3 bgColor CT_Color */
|
||||
case '<bgColor':
|
||||
if(!fill.bgColor) fill.bgColor = {};
|
||||
if(y.indexed) fill.bgColor.indexed = parseInt(y.indexed, 10);
|
||||
if(y.theme) fill.bgColor.theme = parseInt(y.theme, 10);
|
||||
if(y.tint) fill.bgColor.tint = parseFloat(y.tint);
|
||||
/* Excel uses ARGB strings */
|
||||
if(y.rgb) fill.bgColor.rgb = y.rgb.substring(y.rgb.length - 6);
|
||||
break;
|
||||
case '<bgColor/>': case '</bgColor>': break;
|
||||
/* 18.8.3 bgColor CT_Color */
|
||||
case '<bgColor':
|
||||
if (!fill.bgColor) fill.bgColor = {};
|
||||
if (y.indexed) fill.bgColor.indexed = parseInt(y.indexed, 10);
|
||||
if (y.theme) fill.bgColor.theme = parseInt(y.theme, 10);
|
||||
if (y.tint) fill.bgColor.tint = parseFloat(y.tint);
|
||||
|
||||
/* 18.8.19 fgColor CT_Color */
|
||||
case '<fgColor':
|
||||
if(!fill.fgColor) fill.fgColor = {};
|
||||
if(y.theme) fill.fgColor.theme = parseInt(y.theme, 10);
|
||||
if(y.tint) fill.fgColor.tint = parseFloat(y.tint);
|
||||
/* Excel uses ARGB strings */
|
||||
if(y.rgb) fill.fgColor.rgb = y.rgb.substring(y.rgb.length - 6);
|
||||
break;
|
||||
case '<fgColor/>': case '</fgColor>': break;
|
||||
|
||||
default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in fills';
|
||||
}
|
||||
});
|
||||
if (y.theme && themes.themeElements && themes.themeElements.clrScheme) {
|
||||
fill.bgColor.rgb = rgb_tint(themes.themeElements.clrScheme[fill.bgColor.theme].rgb, fill.bgColor.tint || 0);
|
||||
if (opts.WTF) fill.bgColor.raw_rgb = rgb_tint(themes.themeElements.clrScheme[fill.bgColor.theme].rgb,0);
|
||||
}
|
||||
/* Excel uses ARGB strings */
|
||||
if (y.rgb) fill.bgColor.rgb = y.rgb;//.substring(y.rgb.length - 6);
|
||||
break;
|
||||
case '<bgColor/>':
|
||||
case '</bgColor>':
|
||||
break;
|
||||
|
||||
/* 18.8.19 fgColor CT_Color */
|
||||
case '<fgColor':
|
||||
if (!fill.fgColor) fill.fgColor = {};
|
||||
if (y.theme) fill.fgColor.theme = parseInt(y.theme, 10);
|
||||
if (y.tint) fill.fgColor.tint = parseFloat(y.tint);
|
||||
|
||||
if (y.theme && themes.themeElements && themes.themeElements.clrScheme) {
|
||||
fill.fgColor.rgb = rgb_tint(themes.themeElements.clrScheme[fill.fgColor.theme].rgb, fill.fgColor.tint || 0);
|
||||
if (opts.WTF) fill.fgColor.raw_rgb = rgb_tint(themes.themeElements.clrScheme[fill.fgColor.theme].rgb,0);
|
||||
}
|
||||
|
||||
/* Excel uses ARGB strings */
|
||||
if (y.rgb) fill.fgColor.rgb = y.rgb;//.substring(y.rgb.length - 6);
|
||||
break;
|
||||
case '<fgColor/>':
|
||||
case '</fgColor>':
|
||||
break;
|
||||
|
||||
default:
|
||||
if (opts.WTF) throw 'unrecognized ' + y[0] + ' in fills';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function parse_fonts(t, opts) {
|
||||
styles.Fonts = [];
|
||||
var font = {};
|
||||
t[0].match(tagregex).forEach(function (x) {
|
||||
var y = parsexmltag(x);
|
||||
switch (y[0]) {
|
||||
|
||||
case '<fonts':
|
||||
case '<fonts>':
|
||||
case '</fonts>':
|
||||
break;
|
||||
case '<font':
|
||||
break;
|
||||
case '</font>':
|
||||
styles.Fonts.push(font);
|
||||
;
|
||||
font = {};
|
||||
break;
|
||||
|
||||
case '<name':
|
||||
if (y.val) font.name = y.val;
|
||||
break;
|
||||
case '<name/>':
|
||||
case '</name>':
|
||||
break;
|
||||
|
||||
|
||||
case '<b/>':
|
||||
font.bold = true;
|
||||
break;
|
||||
case '<u/>':
|
||||
font.underline = true;
|
||||
break;
|
||||
case '<i/>':
|
||||
font.italic = true;
|
||||
break;
|
||||
case '<strike/>':
|
||||
font.strike = true;
|
||||
break;
|
||||
case '<outline/>':
|
||||
font.outline = true;
|
||||
break;
|
||||
case '<shadow/>':
|
||||
font.shadow = true;
|
||||
break;
|
||||
|
||||
|
||||
case '<sz':
|
||||
if (y.val) font.sz = y.val;
|
||||
break;
|
||||
case '<sz/>':
|
||||
case '</sz>':
|
||||
break;
|
||||
|
||||
case '<vertAlign':
|
||||
if (y.val) font.vertAlign = y.val;
|
||||
break;
|
||||
case '<vertAlign/>':
|
||||
case '</vertAlign>':
|
||||
break;
|
||||
|
||||
|
||||
case '<color':
|
||||
if (!font.color) font.color = {};
|
||||
if (y.theme) font.color.theme = y.theme;
|
||||
if (y.tint) font.color.tint = y.tint;
|
||||
if (y.theme && themes.themeElements && themes.themeElements.clrScheme) {
|
||||
font.color.rgb = rgb_tint(themes.themeElements.clrScheme[font.color.theme].rgb, font.color.tint || 0);
|
||||
}
|
||||
if (y.rgb) font.color.rgb = y.rgb;
|
||||
break;
|
||||
case '<color/>':
|
||||
case '</color>':
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function parse_borders(t, opts) {
|
||||
styles.Borders = [];
|
||||
var border = {}, sub_border = {};
|
||||
t[0].match(tagregex).forEach(function (x) {
|
||||
var y = parsexmltag(x);
|
||||
switch (y[0]) {
|
||||
case '<borders':
|
||||
case '<borders>':
|
||||
case '</borders>':
|
||||
break;
|
||||
case '<border':
|
||||
case '<border>':
|
||||
border = {};
|
||||
if (y.diagonalUp) { border.diagonalUp = y.diagonalUp; }
|
||||
if (y.diagonalDown) { border.diagonalDown = y.diagonalDown; }
|
||||
styles.Borders.push(border);
|
||||
|
||||
break;
|
||||
break;
|
||||
case '</border>':
|
||||
break;
|
||||
|
||||
case '<left':
|
||||
sub_border = border.left = {};
|
||||
if (y.style) {
|
||||
sub_border.style = y.style;
|
||||
}
|
||||
break;
|
||||
case '<right':
|
||||
sub_border = border.right = {};
|
||||
if (y.style) {
|
||||
sub_border.style = y.style;
|
||||
}
|
||||
break;
|
||||
case '<top':
|
||||
sub_border = border.top = {};
|
||||
if (y.style) {
|
||||
sub_border.style = y.style;
|
||||
}
|
||||
break;
|
||||
case '<bottom':
|
||||
sub_border = border.bottom = {};
|
||||
if (y.style) {
|
||||
sub_border.style = y.style;
|
||||
}
|
||||
break;
|
||||
case '<diagonal':
|
||||
sub_border = border.diagonal = {};
|
||||
if (y.style) {
|
||||
sub_border.style = y.style;
|
||||
}
|
||||
break;
|
||||
|
||||
case '<color':
|
||||
sub_border.color = {};
|
||||
if (y.theme) sub_border.color.theme = y.theme;
|
||||
if (y.theme && themes.themeElements && themes.themeElements.clrScheme) {
|
||||
sub_border.color.rgb = rgb_tint(themes.themeElements.clrScheme[sub_border.color.theme].rgb, sub_border.color.tint || 0);
|
||||
}
|
||||
|
||||
if (y.tint) sub_border.color.tint = y.tint;
|
||||
if (y.rgb) sub_border.color.rgb = y.rgb;
|
||||
if (y.auto) sub_border.color.auto = y.auto;
|
||||
break;
|
||||
case '<name/>':
|
||||
case '</name>':
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/* 18.8.31 numFmts CT_NumFmts */
|
||||
function parse_numFmts(t, opts) {
|
||||
styles.NumberFmt = [];
|
||||
var k = keys(SSF._table);
|
||||
for(var i=0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]];
|
||||
var m = t[0].match(tagregex);
|
||||
for(i=0; i < m.length; ++i) {
|
||||
var y = parsexmltag(m[i]);
|
||||
switch(y[0]) {
|
||||
case '<numFmts': case '</numFmts>': case '<numFmts/>': case '<numFmts>': break;
|
||||
case '<numFmt': {
|
||||
var f=unescapexml(utf8read(y.formatCode)), j=parseInt(y.numFmtId,10);
|
||||
styles.NumberFmt[j] = f; if(j>0) SSF.load(f,j);
|
||||
} break;
|
||||
default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in numFmts';
|
||||
}
|
||||
}
|
||||
styles.NumberFmt = [];
|
||||
var k = keys(SSF._table);
|
||||
for (var i = 0; i < k.length; ++i) styles.NumberFmt[k[i]] = SSF._table[k[i]];
|
||||
var m = t[0].match(tagregex);
|
||||
for (i = 0; i < m.length; ++i) {
|
||||
var y = parsexmltag(m[i]);
|
||||
switch (y[0]) {
|
||||
case '<numFmts':
|
||||
case '</numFmts>':
|
||||
case '<numFmts/>':
|
||||
case '<numFmts>':
|
||||
break;
|
||||
case '<numFmt':
|
||||
{
|
||||
var f = unescapexml(utf8read(y.formatCode)), j = parseInt(y.numFmtId, 10);
|
||||
styles.NumberFmt[j] = f;
|
||||
if (j > 0) SSF.load(f, j);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (opts.WTF) throw 'unrecognized ' + y[0] + ' in numFmts';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function write_numFmts(NF, opts) {
|
||||
var o = ["<numFmts>"];
|
||||
[[5,8],[23,26],[41,44],[63,66],[164,392]].forEach(function(r) {
|
||||
for(var i = r[0]; i <= r[1]; ++i) if(NF[i] !== undefined) o[o.length] = (writextag('numFmt',null,{numFmtId:i,formatCode:escapexml(NF[i])}));
|
||||
});
|
||||
if(o.length === 1) return "";
|
||||
o[o.length] = ("</numFmts>");
|
||||
o[0] = writextag('numFmts', null, { count:o.length-2 }).replace("/>", ">");
|
||||
return o.join("");
|
||||
var o = ["<numFmts>"];
|
||||
[
|
||||
[5, 8],
|
||||
[23, 26],
|
||||
[41, 44],
|
||||
[63, 66],
|
||||
[164, 392]
|
||||
].forEach(function (r) {
|
||||
for (var i = r[0]; i <= r[1]; ++i) if (NF[i] !== undefined) o[o.length] = (writextag('numFmt', null, {numFmtId: i, formatCode: escapexml(NF[i])}));
|
||||
});
|
||||
if (o.length === 1) return "";
|
||||
o[o.length] = ("</numFmts>");
|
||||
o[0] = writextag('numFmts', null, { count: o.length - 2 }).replace("/>", ">");
|
||||
return o.join("");
|
||||
}
|
||||
|
||||
/* 18.8.10 cellXfs CT_CellXfs */
|
||||
function parse_cellXfs(t, opts) {
|
||||
styles.CellXf = [];
|
||||
t[0].match(tagregex).forEach(function(x) {
|
||||
var y = parsexmltag(x);
|
||||
switch(y[0]) {
|
||||
case '<cellXfs': case '<cellXfs>': case '<cellXfs/>': case '</cellXfs>': break;
|
||||
styles.CellXf = [];
|
||||
var xf;
|
||||
t[0].match(tagregex).forEach(function (x) {
|
||||
var y = parsexmltag(x);
|
||||
switch (y[0]) {
|
||||
case '<cellXfs':
|
||||
case '<cellXfs>':
|
||||
case '<cellXfs/>':
|
||||
case '</cellXfs>':
|
||||
break;
|
||||
|
||||
/* 18.8.45 xf CT_Xf */
|
||||
case '<xf': delete y[0];
|
||||
if(y.numFmtId) y.numFmtId = parseInt(y.numFmtId, 10);
|
||||
if(y.fillId) y.fillId = parseInt(y.fillId, 10);
|
||||
styles.CellXf.push(y); break;
|
||||
case '</xf>': break;
|
||||
/* 18.8.45 xf CT_Xf */
|
||||
case '<xf':
|
||||
xf = y;
|
||||
delete xf[0];
|
||||
delete y[0];
|
||||
if (xf.numFmtId) xf.numFmtId = parseInt(xf.numFmtId, 10);
|
||||
if (xf.fillId) xf.fillId = parseInt(xf.fillId, 10);
|
||||
styles.CellXf.push(xf);
|
||||
break;
|
||||
case '</xf>':
|
||||
break;
|
||||
|
||||
/* 18.8.1 alignment CT_CellAlignment */
|
||||
case '<alignment': case '<alignment/>': break;
|
||||
/* 18.8.1 alignment CT_CellAlignment */
|
||||
case '<alignment':
|
||||
case '<alignment/>':
|
||||
var alignment = {}
|
||||
if (y.vertical) { alignment.vertical = y.vertical;}
|
||||
if (y.horizontal) { alignment.horizontal = y.horizontal;}
|
||||
if (y.textRotation != undefined) { alignment.textRotation = y.textRotation; }
|
||||
if (y.indent) { alignment.indent = y.indent; }
|
||||
if (y.wrapText) { alignment.wrapText = y.wrapText; }
|
||||
xf.alignment = alignment;
|
||||
|
||||
/* 18.8.33 protection CT_CellProtection */
|
||||
case '<protection': case '</protection>': case '<protection/>': break;
|
||||
break;
|
||||
|
||||
case '<extLst': case '</extLst>': break;
|
||||
case '<ext': break;
|
||||
default: if(opts.WTF) throw 'unrecognized ' + y[0] + ' in cellXfs';
|
||||
}
|
||||
});
|
||||
/* 18.8.33 protection CT_CellProtection */
|
||||
case '<protection':
|
||||
case '</protection>':
|
||||
case '<protection/>':
|
||||
break;
|
||||
|
||||
case '<extLst':
|
||||
case '</extLst>':
|
||||
break;
|
||||
case '<ext':
|
||||
break;
|
||||
default:
|
||||
if (opts.WTF) throw 'unrecognized ' + y[0] + ' in cellXfs';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function write_cellXfs(cellXfs) {
|
||||