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:
David Bruant 2024-07-08 15:32:03 +02:00 committed by GitHub
commit fbf5f8abc9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 122 additions and 29 deletions

4
.gitignore vendored
View File

@ -1,3 +1,5 @@
node_modules/ node_modules/
build/* build/*
.~lock*

4
package-lock.json generated
View File

@ -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"

View File

@ -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",

View File

@ -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
``` ```

View File

@ -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
View 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'

View File

@ -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 {

View File

@ -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 || '';

View File

@ -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

Binary file not shown.

Binary file not shown.

38
tests/ods-files.js Normal file
View 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')
});