Skip to content

Commit 227f970

Browse files
committed
version bump 0.16.5: sheet_add_dom (fixes #2073)
1 parent 41cc307 commit 227f970

26 files changed

+944
-564
lines changed

README.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2116,6 +2116,56 @@ var wb = XLSX.utils.table_to_book(tbl);
21162116

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

2119+
2120+
`XLSX.utils.sheet_add_dom` takes a table DOM element and updates an existing
2121+
worksheet object. It follows the same process as `table_to_sheet` and accepts
2122+
an options argument:
2123+
2124+
| Option Name | Default | Description |
2125+
| :---------- | :------: | :-------------------------------------------------- |
2126+
|`raw` | | If true, every cell will hold raw strings |
2127+
|`dateNF` | FMT 14 | Use specified date format in string output |
2128+
|`cellDates` | false | Store dates as type `d` (default is `n`) |
2129+
|`sheetRows` | 0 | If >0, read the first `sheetRows` rows of the table |
2130+
|`display` | false | If true, hidden rows and cells will not be parsed |
2131+
2132+
`origin` is expected to be one of:
2133+
2134+
| `origin` | Description |
2135+
| :--------------- | :-------------------------------------------------------- |
2136+
| (cell object) | Use specified cell (cell object) |
2137+
| (string) | Use specified cell (A1-style cell) |
2138+
| (number >= 0) | Start from the first column at specified row (0-indexed) |
2139+
| -1 | Append to bottom of worksheet starting on first column |
2140+
| (default) | Start from cell A1 |
2141+
2142+
2143+
<details>
2144+
<summary><b>Examples</b> (click to show)</summary>
2145+
2146+
A small helper function can create gap rows between tables:
2147+
2148+
```js
2149+
function create_gap_rows(ws, nrows) {
2150+
var ref = XLSX.utils.decode_range(ws["!ref"]); // get original range
2151+
ref.e.r += nrows; // add to ending row
2152+
ws["!ref"] = XLSX.utils.encode_range(ref); // reassign row
2153+
}
2154+
2155+
/* first table */
2156+
var ws = XLSX.utils.table_to_sheet(document.getElementById('table1'));
2157+
create_gap_rows(ws, 1); // one row gap after first table
2158+
2159+
/* second table */
2160+
XLSX.utils.sheet_add_dom(ws, document.getElementById('table2'), {origin: -1});
2161+
create_gap_rows(ws, 3); // three rows gap after second table
2162+
2163+
/* third table */
2164+
XLSX.utils.sheet_add_dom(ws, document.getElementById('table3'), {origin: -1});
2165+
```
2166+
2167+
</details>
2168+
21192169
### Formulae Output
21202170

21212171
`XLSX.utils.sheet_to_formulae` generates an array of commands that represent

bits/01_version.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
XLSX.version = '0.16.4';
1+
XLSX.version = '0.16.5';

bits/27_csfutils.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@ function encode_cell(cell/*:CellAddress*/)/*:string*/ {
2626
for(; col; col=((col-1)/26)|0) s = String.fromCharCode(((col-1)%26) + 65) + s;
2727
return s + (cell.r + 1);
2828
}
29-
function decode_range(range/*:string*/)/*:Range*/ { var x =range.split(":"); return {s:decode_cell(x[0]),e:decode_cell(x[x.length-1])}; }
29+
function decode_range(range/*:string*/)/*:Range*/ {
30+
var idx = range.indexOf(":");
31+
if(idx == -1) return { s: decode_cell(range), e: decode_cell(range) };
32+
return { s: decode_cell(range.slice(0, idx)), e: decode_cell(range.slice(idx + 1)) };
33+
}
3034
/*# if only one arg, it is assumed to be a Range. If 2 args, both are cell addresses */
3135
function encode_range(cs/*:CellAddrSpec|Range*/,ce/*:?CellAddrSpec*/)/*:string*/ {
3236
if(typeof ce === 'undefined' || typeof ce === 'number') {
@@ -105,6 +109,7 @@ function sheet_add_aoa(_ws/*:?Worksheet*/, data/*:AOA*/, opts/*:?any*/)/*:Worksh
105109
var _origin/*:CellAddress*/ = typeof o.origin == "string" ? decode_cell(o.origin) : o.origin;
106110
_R = _origin.r; _C = _origin.c;
107111
}
112+
if(!ws["!ref"]) ws["!ref"] = "A1:A1";
108113
}
109114
var range/*:Range*/ = ({s: {c:10000000, r:10000000}, e: {c:0, r:0}}/*:any*/);
110115
if(ws['!ref']) {

bits/62_fxls.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,7 @@ var PtgBinOp = {
690690
};
691691

692692
// List of invalid characters needs to be tested further
693-
var quoteCharacters /*:RegExp */ = new RegExp(/[^\w\u4E00-\u9FFF\u3040-\u30FF]/)
693+
var quoteCharacters /*:RegExp */ = new RegExp(/[^\w\u4E00-\u9FFF\u3040-\u30FF]/);
694694
function formula_quote_sheet_name(sname/*:string*/, opts)/*:string*/ {
695695
if(!sname && !(opts && opts.biff <= 5 && opts.biff >= 2)) throw new Error("empty sheet name");
696696
if (quoteCharacters.test(sname)) return "'" + sname + "'";

bits/79_html.js

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -119,16 +119,32 @@ var HTML_ = (function() {
119119
};
120120
})();
121121

122-
function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
122+
function sheet_add_dom(ws/*:Worksheet*/, table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
123123
var opts = _opts || {};
124124
if(DENSE != null) opts.dense = DENSE;
125-
var ws/*:Worksheet*/ = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
125+
var or_R = 0, or_C = 0;
126+
if(opts.origin != null) {
127+
if(typeof opts.origin == 'number') or_R = opts.origin;
128+
else {
129+
var _origin/*:CellAddress*/ = typeof opts.origin == "string" ? decode_cell(opts.origin) : opts.origin;
130+
or_R = _origin.r; or_C = _origin.c;
131+
}
132+
}
126133
var rows/*:HTMLCollection<HTMLTableRowElement>*/ = table.getElementsByTagName('tr');
127-
var sheetRows = opts.sheetRows || 10000000;
128-
var range/*:Range*/ = {s:{r:0,c:0},e:{r:0,c:0}};
134+
var sheetRows = Math.min(opts.sheetRows||10000000, rows.length);
135+
var range/*:Range*/ = {s:{r:0,c:0},e:{r:or_R,c:or_C}};
136+
if(ws["!ref"]) {
137+
var _range/*:Range*/ = decode_range(ws["!ref"]);
138+
range.s.r = Math.min(range.s.r, _range.s.r);
139+
range.s.c = Math.min(range.s.c, _range.s.c);
140+
range.e.r = Math.max(range.e.r, _range.e.r);
141+
range.e.c = Math.max(range.e.c, _range.e.c);
142+
if(or_R == -1) range.e.r = or_R = _range.e.r + 1;
143+
}
129144
var merges/*:Array<Range>*/ = [], midx = 0;
130-
var rowinfo/*:Array<RowInfo>*/ = [];
145+
var rowinfo/*:Array<RowInfo>*/ = ws["!rows"] || (ws["!rows"] = []);
131146
var _R = 0, R = 0, _C = 0, C = 0, RS = 0, CS = 0;
147+
if(!ws["!cols"]) ws['!cols'] = [];
132148
for(; _R < rows.length && R < sheetRows; ++_R) {
133149
var row/*:HTMLTableRowElement*/ = rows[_R];
134150
if (is_dom_element_hidden(row)) {
@@ -143,11 +159,11 @@ function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
143159
var z/*:?string*/ = elt.getAttribute('z');
144160
for(midx = 0; midx < merges.length; ++midx) {
145161
var m/*:Range*/ = merges[midx];
146-
if(m.s.c == C && m.s.r <= R && R <= m.e.r) { C = m.e.c+1; midx = -1; }
162+
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; }
147163
}
148164
/* TODO: figure out how to extract nonstandard mso- style */
149165
CS = +elt.getAttribute("colspan") || 1;
150-
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}});
166+
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}});
151167
var o/*:Cell*/ = {t:'s', v:v};
152168
var _t/*:string*/ = elt.getAttribute("t") || "";
153169
if(v != null) {
@@ -163,21 +179,26 @@ function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
163179
}
164180
}
165181
if(o.z === undefined && z != null) o.z = z;
166-
if(opts.dense) { if(!ws[R]) ws[R] = []; ws[R][C] = o;}
167-
else ws[encode_cell({c:C, r:R})] = o;
168-
if(range.e.c < C) range.e.c = C;
182+
if(opts.dense) { if(!ws[R + or_R]) ws[R + or_R] = []; ws[R + or_R][C + or_C] = o; }
183+
else ws[encode_cell({c:C + or_C, r:R + or_R})] = o;
184+
if(range.e.c < C + or_C) range.e.c = C + or_C;
169185
C += CS;
170186
}
171187
++R;
172188
}
173-
if(merges.length) ws['!merges'] = merges;
174-
if(rowinfo.length) ws['!rows'] = rowinfo;
175-
range.e.r = R - 1;
189+
if(merges.length) ws['!merges'] = (ws["!merges"] || []).concat(merges);
190+
range.e.r = Math.max(range.e.r, R - 1 + or_R);
176191
ws['!ref'] = encode_range(range);
177-
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
192+
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
178193
return ws;
179194
}
180195

196+
function parse_dom_table(table/*:HTMLElement*/, _opts/*:?any*/)/*:Worksheet*/ {
197+
var opts = _opts || {};
198+
var ws/*:Worksheet*/ = opts.dense ? ([]/*:any*/) : ({}/*:any*/);
199+
return sheet_add_dom(ws, table, _opts);
200+
}
201+
181202
function table_to_book(table/*:HTMLElement*/, opts/*:?any*/)/*:Workbook*/ {
182203
return sheet_to_workbook(parse_dom_table(table, opts), opts);
183204
}

bits/90_utils.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ function sheet_to_formulae(sheet/*:Worksheet*/)/*:Array<string>*/ {
179179
}
180180

181181
function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet*/ {
182+
if(!js.length) return _ws;
182183
var o = opts || {};
183184
var offset = +!o.skipHeader;
184185
var ws/*:Worksheet*/ = _ws || ({}/*:any*/);
@@ -197,6 +198,8 @@ function sheet_add_json(_ws/*:?Worksheet*/, js/*:Array<any>*/, opts)/*:Worksheet
197198
range.e.c = Math.max(range.e.c, _range.e.c);
198199
range.e.r = Math.max(range.e.r, _range.e.r);
199200
if(_R == -1) { _R = _range.e.r + 1; range.e.r = _R + js.length - 1 + offset; }
201+
} else {
202+
if(_R == -1) { _R = 0; range.e.r = js.length - 1 + offset; }
200203
}
201204
var hdr/*:Array<string>*/ = o.header || [], C = 0;
202205

@@ -254,6 +257,7 @@ var utils/*:any*/ = {
254257
make_formulae: sheet_to_formulae,
255258
sheet_add_aoa: sheet_add_aoa,
256259
sheet_add_json: sheet_add_json,
260+
sheet_add_dom: sheet_add_dom,
257261
aoa_to_sheet: aoa_to_sheet,
258262
json_to_sheet: json_to_sheet,
259263
table_to_sheet: parse_dom_table,

dist/xlsx.core.min.js

Lines changed: 13 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/xlsx.core.min.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)