Skip to content

Commit

Permalink
version bump 0.16.5: sheet_add_dom (fixes SheetJS#2073)
Browse files Browse the repository at this point in the history
  • Loading branch information
SheetJSDev authored and saarCiklum committed Aug 20, 2020
1 parent 05137d6 commit 108e209
Show file tree
Hide file tree
Showing 26 changed files with 944 additions and 564 deletions.
50 changes: 50 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2117,6 +2117,56 @@ var wb = XLSX.utils.table_to_book(tbl);

Note: `XLSX.read` can handle HTML represented as strings.


`XLSX.utils.sheet_add_dom` takes a table DOM element and updates an existing
worksheet object. It follows the same process as `table_to_sheet` and accepts
an options argument:

| Option Name | Default | Description |
| :---------- | :------: | :-------------------------------------------------- |
|`raw` | | If true, every cell will hold raw strings |
|`dateNF` | FMT 14 | Use specified date format in string output |
|`cellDates` | false | Store dates as type `d` (default is `n`) |
|`sheetRows` | 0 | If >0, read the first `sheetRows` rows of the table |
|`display` | false | If true, hidden rows and cells will not be parsed |

`origin` is expected to be one of:

| `origin` | Description |
| :--------------- | :-------------------------------------------------------- |
| (cell object) | Use specified cell (cell object) |
| (string) | Use specified cell (A1-style cell) |
| (number >= 0) | Start from the first column at specified row (0-indexed) |
| -1 | Append to bottom of worksheet starting on first column |
| (default) | Start from cell A1 |


<details>
<summary><b>Examples</b> (click to show)</summary>

A small helper function can create gap rows between tables:

```js
function create_gap_rows(ws, nrows) {
var ref = XLSX.utils.decode_range(ws["!ref"]); // get original range
ref.e.r += nrows; // add to ending row
ws["!ref"] = XLSX.utils.encode_range(ref); // reassign row
}

/* first table */
var ws = XLSX.utils.table_to_sheet(document.getElementById('table1'));
create_gap_rows(ws, 1); // one row gap after first table

/* second table */
XLSX.utils.sheet_add_dom(ws, document.getElementById('table2'), {origin: -1});
create_gap_rows(ws, 3); // three rows gap after second table

/* third table */
XLSX.utils.sheet_add_dom(ws, document.getElementById('table3'), {origin: -1});
```

</details>

### Formulae Output

`XLSX.utils.sheet_to_formulae` generates an array of commands that represent
Expand Down
2 changes: 1 addition & 1 deletion bits/01_version.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
XLSX.version = '0.16.4';
XLSX.version = '0.16.5';
7 changes: 6 additions & 1 deletion bits/27_csfutils.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ function encode_cell(cell/*:CellAddress*/)/*:string*/ {
for(; col; col=((col-1)/26)|0) s = String.fromCharCode(((col-1)%26) + 65) + s;
return s + (cell.r + 1);
}
function decode_range(range/*:string*/)/*:Range*/ { var x =range.split(":"); return {s:decode_cell(x[0]),e:decode_cell(x[x.length-1])}; }
function decode_range(range/*:string*/)/*:Range*/ {
var idx = range.indexOf(":");
if(idx == -1) return { s: decode_cell(range), e: decode_cell(range) };
return { s: decode_cell(range.slice(0, idx)), e: decode_cell(range.slice(idx + 1)) };
}
/*# if only one arg, it is assumed to be a Range. If 2 args, both are cell addresses */
function encode_range(cs/*:CellAddrSpec|Range*/,ce/*:?CellAddrSpec*/)/*:string*/ {
if(typeof ce === 'undefined' || typeof ce === 'number') {
Expand Down Expand Up @@ -105,6 +109,7 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh
var _origin/*:CellAddress*/ = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
_R = _origin.r; _C = _origin.c;
}
if(!ws["!ref"]) ws["!ref"] = "A1:A1";
}
var range/*:Range*/ = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}}/*:any*/);
if(ws['!ref']) {
Expand Down
2 changes: 1 addition & 1 deletion bits/62_fxls.js
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,7 @@ var PtgBinOp = {
};

// List of invalid characters needs to be tested further
var quoteCharacters /*:RegExp */ = new RegExp(/[^\w\u4E00-\u9FFF\u3040-\u30FF]/)
var quoteCharacters /*:RegExp */ = new RegExp(/[^\w\u4E00-\u9FFF\u3040-\u30FF]/);
function formula_quote_sheet_name(sname/*:string*/, opts)/*:string*/ {
if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name");
if (quoteCharacters.test(sname)) return "'" + sname + "'";
Expand Down
49 changes: 35 additions & 14 deletions bits/79_html.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,16 +119,32 @@ var HTML_ = (function() {
};
})();

function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
var opts = _opts || {};
if(DENSE != null) opts.dense = DENSE;
var ws/*:Worksheet*/ = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
var or_R = 0, or_C = 0;
if(opts.origin != null) {
if(typeof opts.origin == 'number') or_R = opts.origin;
else {
var _origin/*:CellAddress*/ = typeof opts.origin == "string" ? decode_cell(opts.origin) : opts.origin;
or_R = _origin.r; or_C = _origin.c;
}
}
var rows/*:HTMLCollection<HTMLTableRowElement>*/ = table.getElementsByTagName('tr');
var sheetRows = opts.sheetRows || 10000000;
var range/*:Range*/ = {s:{r:0,c:0},e:{r:0,c:0}};
var sheetRows = Math.min(opts.sheetRows||10000000, rows.length);
var range/*:Range*/ = {s:{r:0,c:0},e:{r:or_R,c:or_C}};
if(ws["!ref"]) {
var _range/*:Range*/ = decode_range(ws["!ref"]);
range.s.r = Math.min(range.s.r, _range.s.r);
range.s.c = Math.min(range.s.c, _range.s.c);
range.e.r = Math.max(range.e.r, _range.e.r);
range.e.c = Math.max(range.e.c, _range.e.c);
if(or_R == -1) range.e.r = or_R = _range.e.r + 1;
}
var merges/*:Array<Range>*/ = [], midx = 0;
var rowinfo/*:Array<RowInfo>*/ = [];
var rowinfo/*:Array<RowInfo>*/ = ws["!rows"] || (ws["!rows"] = []);
var _R = 0, R = 0, _C = 0, C = 0, RS = 0, CS = 0;
if(!ws["!cols"]) ws['!cols'] = [];
for(; _R < rows.length && R < sheetRows; ++_R) {
var row/*:HTMLTableRowElement*/ = rows[_R];
if (is_dom_element_hidden(row)) {
Expand All @@ -143,11 +159,11 @@ function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
var z/*:?string*/ = elt.getAttribute('z');
for(midx = 0; midx < merges.length; ++midx) {
var m/*:Range*/ = merges[midx];
if(m.s.c == C && m.s.r <= R && R <= m.e.r) { C = m.e.c+1; midx = -1; }
if(m.s.c == C + or_C && m.s.r < R + or_R && R + or_R <= m.e.r) { C = m.e.c+1 - or_C; midx = -1; }
}
/* TODO: figure out how to extract nonstandard mso- style */
CS = +elt.getAttribute("colspan") || 1;
if((RS = +elt.getAttribute("rowspan"))>0 || CS>1) merges.push({s:{r:R,c:C},e:{r:R + (RS||1) - 1, c:C + CS - 1}});
if( ((RS = (+elt.getAttribute("rowspan") || 1)))>1 || CS>1) merges.push({s:{r:R + or_R,c:C + or_C},e:{r:R + or_R + (RS||1) - 1, c:C + or_C + (CS||1) - 1}});
var o/*:Cell*/ = {t:'s', v:v};
var _t/*:string*/ = elt.getAttribute("t") || "";
if(v != null) {
Expand All @@ -163,21 +179,26 @@ function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
}
}
if(o.z === undefined && z != null) o.z = z;
if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o;}
else ws[encode_cell({c:C, r:R})] = o;
if(range.e.c < C) range.e.c = C;
if(opts.dense) { if(!ws[R + or_R]) ws[R + or_R] = []; ws[R + or_R][C + or_C] = o; }
else ws[encode_cell({c:C + or_C, r:R + or_R})] = o;
if(range.e.c < C + or_C) range.e.c = C + or_C;
C += CS;
}
++R;
}
if(merges.length) ws['!merges'] = merges;
if(rowinfo.length) ws['!rows'] = rowinfo;
range.e.r = R - 1;
if(merges.length) ws['!merges'] = (ws["!merges"] || []).concat(merges);
range.e.r = Math.max(range.e.r, R - 1 + or_R);
ws['!ref'] = encode_range(range);
if(R >= sheetRows) ws['!fullref'] = encode_range((range.e.r = rows.length-_R+R-1,range)); // We can count the real number of rows to parse but we don't to improve the performance
if(R >= sheetRows) ws['!fullref'] = encode_range((range.e.r = rows.length-_R+R-1 + or_R,range)); // We can count the real number of rows to parse but we don't to improve the performance
return ws;
}

function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
var opts = _opts || {};
var ws/*:Worksheet*/ = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
return sheet_add_dom(ws, table, _opts);
}

function table_to_book(table/*:HTMLElement*/, opts/*:?any*/)/*:Workbook*/ {
return sheet_to_workbook(parse_dom_table(table, opts), opts);
}
Expand Down
4 changes: 4 additions & 0 deletions bits/90_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array<string>*/ {
}

function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet*/ {
if(!js.length) return _ws;
var o = opts || {};
var offset = +!o.skipHeader;
var ws/*:Worksheet*/ = _ws || ({}/*:any*/);
Expand All @@ -197,6 +198,8 @@ function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet
range.e.c = Math.max(range.e.c, _range.e.c);
range.e.r = Math.max(range.e.r, _range.e.r);
if(_R == -1) { _R = _range.e.r + 1; range.e.r = _R + js.length - 1 + offset; }
} else {
if(_R == -1) { _R = 0; range.e.r = js.length - 1 + offset; }
}
var hdr/*:Array<string>*/ = o.header || [], C = 0;

Expand Down Expand Up @@ -254,6 +257,7 @@ var utils/*:any*/ = {
make_formulae: sheet_to_formulae,
sheet_add_aoa: sheet_add_aoa,
sheet_add_json: sheet_add_json,
sheet_add_dom: sheet_add_dom,
aoa_to_sheet: aoa_to_sheet,
json_to_sheet: json_to_sheet,
table_to_sheet: parse_dom_table,
Expand Down
26 changes: 13 additions & 13 deletions dist/xlsx.core.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/xlsx.core.min.map

Large diffs are not rendered by default.

Loading

0 comments on commit 108e209

Please sign in to comment.