xmldom
This commit is contained in:
parent
a36dee9eeb
commit
b6095aff3f
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@
|
||||
*.bak
|
||||
package-lock.json
|
||||
pnpm-lock.yaml
|
||||
docs
|
||||
|
@ -37,7 +37,7 @@ const workbook = XLSX.utils.table_to_book(tbl);
|
||||
XLSX.writeFile(workbook, "SheetJSDOM.xlsx");
|
||||
```
|
||||
|
||||
<details open><summary><b>Complete Demo</b> (click to hide)</summary>
|
||||
<details><summary><b>Complete Demo</b> (click to show)</summary>
|
||||
|
||||
:::note
|
||||
|
||||
@ -81,6 +81,61 @@ node SheetJSDOM.js
|
||||
|
||||
The script will create a file `SheetJSDOM.xlsx` that can be opened.
|
||||
|
||||
</details>
|
||||
|
||||
### XMLDOM
|
||||
|
||||
XMLDOM provides a DOM framework for NodeJS. Given an HTML string, a reference to
|
||||
the table element works with the SheetJS DOM methods after patching the object.
|
||||
|
||||
<details><summary><b>Complete Demo</b> (click to show)</summary>
|
||||
|
||||
:::note
|
||||
|
||||
This demo was last tested on 2023 May 18 against XMLDOM `0.8.7`
|
||||
|
||||
:::
|
||||
|
||||
1) Install SheetJS and XMLDOM libraries:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @xmldom/xmldom@0.8.7`}
|
||||
</CodeBlock>
|
||||
|
||||
2) Save the following codeblock to `SheetJSXMLDOM.js`:
|
||||
|
||||
```js title="SheetJSXMLDOM.js"
|
||||
const XLSX = require("xlsx");
|
||||
const { DOMParser, XMLSerializer } = require("@xmldom/xmldom");
|
||||
|
||||
(async() => {
|
||||
const text = await (await fetch('https://docs.sheetjs.com/dom/SheetJSTable.html')).text();
|
||||
const doc = new DOMParser().parseFromString( text, "text/html");
|
||||
const tbl = doc.getElementsByTagName("table")[0];
|
||||
|
||||
/* patch XMLDOM */
|
||||
tbl.rows = Array.from(tbl.getElementsByTagName("tr"));
|
||||
tbl.rows.forEach(row => row.cells = Array.from(row.getElementsByTagName("td")))
|
||||
Object.defineProperty(tbl.__proto__, "innerHTML", { get: function() {
|
||||
var outerHTML = new XMLSerializer().serializeToString(this);
|
||||
if(outerHTML.match(/</g).length == 1) return "";
|
||||
return outerHTML.slice(0, outerHTML.lastIndexOf("</")).replace(/<[^"'>]*(("[^"]*"|'[^']*')[^"'>]*)*>/, "");
|
||||
}});
|
||||
|
||||
const workbook = XLSX.utils.table_to_book(tbl);
|
||||
XLSX.writeFile(workbook, "SheetJSXMLDOM.xlsx");
|
||||
})();
|
||||
```
|
||||
|
||||
3) Run the script:
|
||||
|
||||
```bash
|
||||
node SheetJSXMLDOM.js
|
||||
```
|
||||
|
||||
The script will create a file `SheetJSXMLDOM.xlsx` that can be opened.
|
||||
|
||||
|
||||
</details>
|
||||
|
||||
### CheerioJS
|
||||
|
@ -144,28 +144,32 @@ The following code block fetches the file, parses and prints info on cell `D1`:
|
||||
```jsx live
|
||||
/* The live editor requires this function wrapper */
|
||||
function ConcatFormula(props) {
|
||||
const [text, setText] = React.useState([]);
|
||||
const [ws, setWS] = React.useState({"!ref":"A1"});
|
||||
const [addr, setAddr] = React.useState("D1");
|
||||
const setaddr = React.useCallback((evt)=>{ setAddr(evt.target.value) });
|
||||
|
||||
/* Fetch and display formula */
|
||||
/* Process ArrayBuffer */
|
||||
const process_ab = (ab) => {
|
||||
const wb = XLSX.read(ab, {cellFormula: true, sheetStubs: true});
|
||||
setWS(wb.Sheets[wb.SheetNames[0]]);
|
||||
};
|
||||
|
||||
/* Fetch sample file */
|
||||
React.useEffect(async() => {
|
||||
/* Fetch file */
|
||||
const ab = await (await fetch("/files/concat.xlsx")).arrayBuffer();
|
||||
|
||||
/* Parse file */
|
||||
const wb = XLSX.read(ab, {cellFormula: true});
|
||||
const ws = wb.Sheets[wb.SheetNames[0]];
|
||||
|
||||
/* Look at cell D1 */
|
||||
const addr = "D1";
|
||||
const { t, v, f } = ws[addr];
|
||||
setText(`\
|
||||
CELL ADDRESS: ${addr}\n\
|
||||
CELL FORMULA: ${f}\n\
|
||||
VALUE (TYPE): "${v}" ("${t}")\n\
|
||||
`);
|
||||
process_ab(await (await fetch("/files/concat.xlsx")).arrayBuffer());
|
||||
}, []);
|
||||
|
||||
return (<pre>{text}</pre>);
|
||||
const process_file = async(e) => {
|
||||
process_ab(await e.target.files[0].arrayBuffer());
|
||||
};
|
||||
return ( <>
|
||||
<input type="file" onChange={process_file}/><br/>
|
||||
<b>addr: </b><input type="text" value={addr} onChange={setaddr} size="6"/>
|
||||
{!ws[addr] ? ( <b>Cell {addr} not found</b> ) : ( <table>
|
||||
<tr><td>Formula</td><td><code>{ws[addr].f}</code></td></tr>
|
||||
<tr><td>Value</td><td><code>{ws[addr].v}</code></td></tr>
|
||||
<tr><td>Cell Type</td><td><code>{ws[addr].t}</code></td></tr>
|
||||
</table> )}
|
||||
</> );
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -21,9 +21,10 @@ allow users to "reply". The original "Comments" were renamed to "Notes".
|
||||
| XLML | ✔ | ✔ | * |
|
||||
| SYLK | | * | * |
|
||||
| ODS / FODS / UOS | ✔ | R | * |
|
||||
| NUMBERS | * | * | |
|
||||
|
||||
Asterisks (*) mark features that are not supported by the file formats. There is
|
||||
no way to specify a threaded comment in the SYLK format.
|
||||
Asterisks (*) mark features that are not supported by the file formats. Numbers
|
||||
supports plaintext threaded comments but does not support Excel styled comments.
|
||||
|
||||
The letter R (R) marks features parsed but not written in the format.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user