Merge pull request #1 from DavidBruant/date-and-number-columns-repeated-and-split-exports
Date and number columns repeated and split exports
This commit is contained in:
commit
fbf5f8abc9
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,3 +1,5 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
|
|
||||||
build/*
|
build/*
|
||||||
|
|
||||||
|
.~lock*
|
||||||
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "front-end-template",
|
"name": "front-end-template",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "front-end-template",
|
"name": "front-end-template",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@xmldom/xmldom": "^0.8.10",
|
"@xmldom/xmldom": "^0.8.10",
|
||||||
"unzipit": "^1.4.3"
|
"unzipit": "^1.4.3"
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "ods-xlsx",
|
"name": "ods-xlsx",
|
||||||
"version": "0.5.0",
|
"version": "0.6.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./scripts/main.js",
|
"main": "./scripts/node.js",
|
||||||
|
"browser": "./scripts/browser.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "rollup -c",
|
"build": "rollup -c",
|
||||||
"dev": "npm-run-all --parallel dev:* start",
|
"dev": "npm-run-all --parallel dev:* start",
|
||||||
|
|||||||
@ -8,7 +8,7 @@ Small lib to parse/understand .ods and .xsls files in the browser and node.js
|
|||||||
### Install
|
### Install
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npm i github:DavidBruant/ods-xlsx#v0.5.0
|
npm i https://github.com/DavidBruant/ods-xlsx.git#v0.6.0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
//@ts-check
|
//@ts-check
|
||||||
|
|
||||||
import {tableRawContentToObjects, tableWithoutEmptyRows, getODSTableRawContent, getXLSXTableRawContent} from './main.js'
|
import {tableRawContentToObjects, tableWithoutEmptyRows, getODSTableRawContent, getXLSXTableRawContent} from './browser.js'
|
||||||
|
|
||||||
const ODS_TYPE = "application/vnd.oasis.opendocument.spreadsheet";
|
const ODS_TYPE = "application/vnd.oasis.opendocument.spreadsheet";
|
||||||
const XLSX_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
const XLSX_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||||
|
|||||||
48
scripts/browser.js
Normal file
48
scripts/browser.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
//@ts-check
|
||||||
|
|
||||||
|
function parseXML(str){
|
||||||
|
return (new DOMParser()).parseFromString(str, 'application/xml');
|
||||||
|
}
|
||||||
|
|
||||||
|
import {
|
||||||
|
_getODSTableRawContent,
|
||||||
|
_getXLSXTableRawContent
|
||||||
|
} from './shared.js'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ArrayBuffer} odsArrBuff
|
||||||
|
* @returns {ReturnType<_getODSTableRawContent>}
|
||||||
|
*/
|
||||||
|
export function getODSTableRawContent(odsArrBuff){
|
||||||
|
return _getODSTableRawContent(odsArrBuff, parseXML)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {ArrayBuffer} xlsxArrBuff
|
||||||
|
* @returns {ReturnType<_getXLSXTableRawContent>}
|
||||||
|
*/
|
||||||
|
export function getXLSXTableRawContent(xlsxArrBuff){
|
||||||
|
return _getXLSXTableRawContent(xlsxArrBuff, parseXML)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export {
|
||||||
|
// table-level exports
|
||||||
|
tableWithoutEmptyRows,
|
||||||
|
tableRawContentToValues,
|
||||||
|
tableRawContentToStrings,
|
||||||
|
tableRawContentToObjects,
|
||||||
|
|
||||||
|
// sheet-level exports
|
||||||
|
sheetRawContentToObjects,
|
||||||
|
sheetRawContentToStrings,
|
||||||
|
|
||||||
|
// row-level exports
|
||||||
|
rowRawContentToStrings,
|
||||||
|
isRowNotEmpty,
|
||||||
|
|
||||||
|
// cell-level exports
|
||||||
|
cellRawContentToStrings,
|
||||||
|
convertCellValue
|
||||||
|
} from './shared.js'
|
||||||
|
|
||||||
@ -1,21 +1,9 @@
|
|||||||
//@ts-check
|
//@ts-check
|
||||||
|
|
||||||
let _DOMParser
|
import {DOMParser} from '@xmldom/xmldom'
|
||||||
|
|
||||||
if(typeof DOMParser !== 'undefined' && Object(DOMParser) === DOMParser && DOMParser.prototype && typeof DOMParser.prototype.parseFromString === 'function'){
|
|
||||||
//console.info('[ods-xlsx] Already existing DOMParser. Certainly in the browser')
|
|
||||||
|
|
||||||
_DOMParser = DOMParser
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
//console.info('[ods-xlsx] No native DOMParser. Certainly in Node.js')
|
|
||||||
|
|
||||||
const xmldom = await import('@xmldom/xmldom')
|
|
||||||
_DOMParser = xmldom.DOMParser
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseXML(str){
|
function parseXML(str){
|
||||||
return (new _DOMParser()).parseFromString(str, 'application/xml');
|
return (new DOMParser()).parseFromString(str, 'application/xml');
|
||||||
}
|
}
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -32,11 +32,26 @@ export async function _getODSTableRawContent(arrayBuffer, parseXML) {
|
|||||||
|
|
||||||
for (let cell of Array.from(cells)) {
|
for (let cell of Array.from(cells)) {
|
||||||
const cellType = cell.getAttribute('office:value-type');
|
const cellType = cell.getAttribute('office:value-type');
|
||||||
const cellValue = cellType === 'string' ? cell.textContent : cell.getAttribute('office:value');
|
let cellValue;
|
||||||
rowData.push({
|
|
||||||
value: cellValue,
|
if (cellType === 'string') {
|
||||||
type: cellType
|
cellValue = cell.textContent;
|
||||||
});
|
} else if (cellType === 'date') {
|
||||||
|
cellValue = cell.getAttribute('office:date-value');
|
||||||
|
} else {
|
||||||
|
cellValue = cell.getAttribute('office:value');
|
||||||
|
}
|
||||||
|
|
||||||
|
const numberOfColumnsRepeated = cell.getAttribute('table:number-columns-repeated');
|
||||||
|
const repeatCount = numberOfColumnsRepeated ? parseInt(numberOfColumnsRepeated, 10) : 1;
|
||||||
|
if(repeatCount < 100){ // ignore excessive repetitions
|
||||||
|
for (let i = 0; i < repeatCount; i++) {
|
||||||
|
rowData.push({
|
||||||
|
value: cellValue,
|
||||||
|
type: cellType
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sheetData.push(rowData);
|
sheetData.push(rowData);
|
||||||
@ -48,6 +63,7 @@ export async function _getODSTableRawContent(arrayBuffer, parseXML) {
|
|||||||
return tableMap;
|
return tableMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts raw table content from an XLSX file.
|
* Extracts raw table content from an XLSX file.
|
||||||
* @param {ArrayBuffer} arrayBuffer - The XLSX file.
|
* @param {ArrayBuffer} arrayBuffer - The XLSX file.
|
||||||
@ -83,11 +99,11 @@ export async function _getXLSXTableRawContent(arrayBuffer, parseXML) {
|
|||||||
const rows = sheetDoc.getElementsByTagName('sheetData')[0].getElementsByTagName('row');
|
const rows = sheetDoc.getElementsByTagName('sheetData')[0].getElementsByTagName('row');
|
||||||
const sheetData = [];
|
const sheetData = [];
|
||||||
|
|
||||||
for (let row of rows) {
|
for (let row of Array.from(rows)) {
|
||||||
const cells = row.getElementsByTagName('c');
|
const cells = row.getElementsByTagName('c');
|
||||||
const rowData = [];
|
const rowData = [];
|
||||||
|
|
||||||
for (let cell of cells) {
|
for (let cell of Array.from(cells)) {
|
||||||
const cellType = cell.getAttribute('t') || 'n';
|
const cellType = cell.getAttribute('t') || 'n';
|
||||||
let cellValue = cell.getElementsByTagName('v')[0]?.textContent || '';
|
let cellValue = cell.getElementsByTagName('v')[0]?.textContent || '';
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import {readFile} from 'node:fs/promises'
|
|||||||
|
|
||||||
import test from 'ava';
|
import test from 'ava';
|
||||||
|
|
||||||
import {getODSTableRawContent} from '../scripts/main.js'
|
import {getODSTableRawContent} from '../scripts/node.js'
|
||||||
|
|
||||||
const nomAgeContent = (await readFile('./tests/data/nom-age.ods')).buffer
|
const nomAgeContent = (await readFile('./tests/data/nom-age.ods')).buffer
|
||||||
|
|
||||||
|
|||||||
BIN
tests/data/cellules avec dates.ods
Normal file
BIN
tests/data/cellules avec dates.ods
Normal file
Binary file not shown.
BIN
tests/data/cellules-répétées.ods
Normal file
BIN
tests/data/cellules-répétées.ods
Normal file
Binary file not shown.
38
tests/ods-files.js
Normal file
38
tests/ods-files.js
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import {readFile} from 'node:fs/promises'
|
||||||
|
|
||||||
|
import test from 'ava';
|
||||||
|
|
||||||
|
import {getODSTableRawContent} from '../scripts/node.js'
|
||||||
|
|
||||||
|
test('.ods file with table:number-columns-repeated attribute in cell', async t => {
|
||||||
|
const repeatedCellFileContent = (await readFile('./tests/data/cellules-répétées.ods')).buffer
|
||||||
|
|
||||||
|
const table = await getODSTableRawContent(repeatedCellFileContent);
|
||||||
|
|
||||||
|
const feuille1 = table.get('Feuille 1')
|
||||||
|
|
||||||
|
t.deepEqual(feuille1[0].length, feuille1[1].length, `First and second row should have the same number of columns`)
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
test('.ods cells with dates should be recognized', async t => {
|
||||||
|
const odsFileWithDates = (await readFile('./tests/data/cellules avec dates.ods')).buffer
|
||||||
|
const table = await getODSTableRawContent(odsFileWithDates);
|
||||||
|
|
||||||
|
const feuille1 = table.get('Feuille1')
|
||||||
|
|
||||||
|
const row1 = feuille1[0]
|
||||||
|
t.deepEqual(row1[0].value, 'Nom')
|
||||||
|
t.deepEqual(row1[1].value, 'Date de naissance')
|
||||||
|
|
||||||
|
const row2 = feuille1[1]
|
||||||
|
t.deepEqual(row2[0].value, 'Dav')
|
||||||
|
t.deepEqual(row2[1].type, 'date')
|
||||||
|
t.deepEqual(row2[1].value, '1987-03-08')
|
||||||
|
|
||||||
|
const row3 = feuille1[2]
|
||||||
|
t.deepEqual(row3[0].value, 'Fanny')
|
||||||
|
t.deepEqual(row3[1].type, 'date')
|
||||||
|
t.deepEqual(row3[1].value, '1986-06-01')
|
||||||
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user