Remove xlsx support
This commit is contained in:
parent
c345323524
commit
30cfe0921e
@ -5,7 +5,7 @@
|
||||
<meta name="referrer" content="no-referrer">
|
||||
<link rel="icon" href="data:,">
|
||||
|
||||
<title>Upload ods/xlsx</title>
|
||||
<title>Upload ods file</title>
|
||||
|
||||
<meta name="description" content=" ">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
10
readme.md
10
readme.md
@ -6,7 +6,7 @@ Small lib to parse/understand .odf files (.odt, .ods) in the browser and node.js
|
||||
## Rough roadmap
|
||||
|
||||
- [x] add odt templating
|
||||
- [ ] remove support for xlsx
|
||||
- [x] remove support for xlsx
|
||||
- [ ] add a .ods minifyer
|
||||
- [ ] add a generic .ods visualizer
|
||||
- [ ] move to a dedicated odf docs org
|
||||
@ -22,7 +22,7 @@ npm i https://github.com/odfjs/odfjs.git#v0.14.0
|
||||
```
|
||||
|
||||
|
||||
### Basic - reading an ods/xlsx file
|
||||
### Basic - reading an ods file
|
||||
|
||||
```js
|
||||
import {tableRawContentToObjects, tableWithoutEmptyRows, getODSTableRawContent} from '@odfjs/odfjs'
|
||||
@ -40,14 +40,14 @@ async function getFileData(odsFile){
|
||||
|
||||
The return value is an array of objects where
|
||||
the **keys** are the column names in the first row and
|
||||
the **values** are automatically converted from the .ods or .xlsx files (which type numbers, strings, booleans and dates)
|
||||
the **values** are automatically converted from the .ods files (which type numbers, strings, booleans and dates)
|
||||
to the appropriate JavaScript value
|
||||
|
||||
|
||||
### Basic - creating an ods file
|
||||
|
||||
```js
|
||||
import {createOdsFile} from 'ods-xlsx'
|
||||
import {createOdsFile} from '@odfjs/odfjs'
|
||||
|
||||
const content = new Map([
|
||||
[
|
||||
@ -128,7 +128,7 @@ They can be used to generate lists or tables in .odt files from data and a templ
|
||||
|
||||
### Demo
|
||||
|
||||
https://davidbruant.github.io/ods-xlsx/
|
||||
https://odfjs.github.io/odfjs/
|
||||
|
||||
|
||||
## Local dev
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
<script>
|
||||
//@ts-check
|
||||
import {tableRawContentToObjects, tableWithoutEmptyRows, getODSTableRawContent, createOdsFile} from './browser.js'
|
||||
|
||||
import {tableRawContentToObjects, tableWithoutEmptyRows, getODSTableRawContent, getXLSXTableRawContent, createOdsFile} from './browser.js'
|
||||
/** @import {SheetName, SheetRawContent} from './types.js' */
|
||||
|
||||
const ODS_TYPE = "application/vnd.oasis.opendocument.spreadsheet";
|
||||
const XLSX_TYPE = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
@ -15,9 +16,6 @@
|
||||
if(file.type === ODS_TYPE)
|
||||
return getODSTableRawContent(await file.arrayBuffer())
|
||||
|
||||
if(file.type === XLSX_TYPE)
|
||||
return getXLSXTableRawContent(await file.arrayBuffer())
|
||||
|
||||
throw new TypeError(`Unsupported file type: ${file.type} (${file.name})`)
|
||||
}
|
||||
|
||||
@ -42,7 +40,7 @@
|
||||
<h2>Import</h2>
|
||||
<label>
|
||||
Fichier à importer:
|
||||
<input bind:files type="file" id="file-input" accept="{ ['.ods', '.xlsx', ODS_TYPE, XLSX_TYPE].join(',') }" />
|
||||
<input bind:files type="file" id="file-input" accept="{ ['.ods', ODS_TYPE].join(',') }" />
|
||||
</label>
|
||||
</section>
|
||||
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
//@ts-check
|
||||
|
||||
import {
|
||||
_getODSTableRawContent,
|
||||
_getXLSXTableRawContent
|
||||
} from './shared.js'
|
||||
import { _getODSTableRawContent } from './shared.js'
|
||||
|
||||
import {_createOdsFile} from './createOdsFile.js'
|
||||
|
||||
@ -26,13 +23,6 @@ export function getODSTableRawContent(odsArrBuff){
|
||||
return _getODSTableRawContent(odsArrBuff, parseXML)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ArrayBuffer} xlsxArrBuff
|
||||
* @returns {ReturnType<_getXLSXTableRawContent>}
|
||||
*/
|
||||
export function getXLSXTableRawContent(xlsxArrBuff){
|
||||
return _getXLSXTableRawContent(xlsxArrBuff, parseXML)
|
||||
}
|
||||
|
||||
|
||||
/** @type { typeof DOMImplementation.prototype.createDocument } */
|
||||
|
||||
@ -2,10 +2,7 @@
|
||||
|
||||
import {DOMParser, DOMImplementation, XMLSerializer, Node} from '@xmldom/xmldom'
|
||||
|
||||
import {
|
||||
_getODSTableRawContent,
|
||||
_getXLSXTableRawContent
|
||||
} from './shared.js'
|
||||
import {_getODSTableRawContent} from './shared.js'
|
||||
import { _createOdsFile } from './createOdsFile.js'
|
||||
|
||||
import _fillOdtTemplate from './odf/fillOdtTemplate.js'
|
||||
@ -32,13 +29,6 @@ export function getODSTableRawContent(odsArrBuff){
|
||||
return _getODSTableRawContent(odsArrBuff, parseXML)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ArrayBuffer} xlsxArrBuff
|
||||
* @returns {ReturnType<_getXLSXTableRawContent>}
|
||||
*/
|
||||
export function getXLSXTableRawContent(xlsxArrBuff){
|
||||
return _getXLSXTableRawContent(xlsxArrBuff, parseXML)
|
||||
}
|
||||
|
||||
const implementation = new DOMImplementation()
|
||||
|
||||
|
||||
@ -123,101 +123,6 @@ export async function _getODSTableRawContent(arrayBuffer, parseXML) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Extracts raw table content from an XLSX file.
|
||||
* @param {ArrayBuffer} arrayBuffer - The XLSX file.
|
||||
* @param {(str: string) => Document} parseXML - Function to parse XML content.
|
||||
* @returns {Promise<Map<SheetName, SheetRawContent>>}
|
||||
*/
|
||||
export async function _getXLSXTableRawContent(arrayBuffer, parseXML) {
|
||||
const zipDataReader = new Uint8ArrayReader(new Uint8Array(arrayBuffer));
|
||||
const zipReader = new ZipReader(zipDataReader);
|
||||
const zipEntries = await zipReader.getEntries()
|
||||
await zipReader.close();
|
||||
|
||||
/** @type {Map<Entry['filename'], Entry>} */
|
||||
const entryByFilename = new Map()
|
||||
for(const entry of zipEntries){
|
||||
const filename = entry.filename
|
||||
entryByFilename.set(filename, entry)
|
||||
}
|
||||
|
||||
const sharedStringsEntry = entryByFilename.get('xl/sharedStrings.xml')
|
||||
|
||||
if(!sharedStringsEntry){
|
||||
throw new TypeError(`entry 'xl/sharedStrings.xml' manquante dans le zip`)
|
||||
}
|
||||
|
||||
//@ts-ignore
|
||||
const sharedStringsXml = await sharedStringsEntry.getData(new TextWriter());
|
||||
|
||||
const sharedStringsDoc = parseXML(sharedStringsXml);
|
||||
const sharedStrings = Array.from(sharedStringsDoc.getElementsByTagName('sst')[0].getElementsByTagName('si')).map(si => si.textContent);
|
||||
|
||||
// Get sheet names and their corresponding XML files
|
||||
const workbookEntry = entryByFilename.get('xl/workbook.xml')
|
||||
|
||||
if(!workbookEntry){
|
||||
throw new TypeError(`entry 'xl/workbook.xml' manquante dans le zip`)
|
||||
}
|
||||
|
||||
//@ts-ignore
|
||||
const workbookXml = await workbookEntry.getData(new TextWriter());
|
||||
const workbookDoc = parseXML(workbookXml);
|
||||
const sheets = Array.from(workbookDoc.getElementsByTagName('sheets')[0].getElementsByTagName('sheet'));
|
||||
const sheetNames = sheets.map(sheet => sheet.getAttribute('name'));
|
||||
const sheetIds = sheets.map(sheet => sheet.getAttribute('r:id'));
|
||||
|
||||
// Read the relations to get the actual filenames for each sheet
|
||||
const workbookRelsEntry = entryByFilename.get('xl/_rels/workbook.xml.rels')
|
||||
|
||||
if(!workbookRelsEntry){
|
||||
throw new TypeError(`entry 'xl/_rels/workbook.xml.rels' manquante dans le zip`)
|
||||
}
|
||||
|
||||
//@ts-ignore
|
||||
const workbookRelsXml = await workbookRelsEntry.getData(new TextWriter());
|
||||
const workbookRelsDoc = parseXML(workbookRelsXml);
|
||||
const sheetRels = Array.from(workbookRelsDoc.getElementsByTagName('Relationship'));
|
||||
const sheetFiles = sheetIds.map(id => sheetRels.find(rel => rel.getAttribute('Id') === id).getAttribute('Target').replace('worksheets/', ''));
|
||||
|
||||
// Read each sheet's XML and extract data in parallel
|
||||
const sheetDataPs = sheetFiles.map((sheetFile, index) => (
|
||||
// @ts-ignore
|
||||
entryByFilename.get(`xl/worksheets/${sheetFile}`).getData(new TextWriter()).then(sheetXml => {
|
||||
const sheetDoc = parseXML(sheetXml);
|
||||
|
||||
const rows = sheetDoc.getElementsByTagName('sheetData')[0].getElementsByTagName('row');
|
||||
const sheetData = [];
|
||||
|
||||
for (let row of Array.from(rows)) {
|
||||
const cells = row.getElementsByTagName('c');
|
||||
const rowData = [];
|
||||
|
||||
for (let cell of Array.from(cells)) {
|
||||
const cellType = cell.getAttribute('t') || 'n';
|
||||
let cellValue = cell.getElementsByTagName('v')[0]?.textContent || '';
|
||||
|
||||
if (cellType === 's') {
|
||||
cellValue = sharedStrings[parseInt(cellValue, 10)];
|
||||
}
|
||||
|
||||
rowData.push({
|
||||
value: cellValue,
|
||||
type: cellType
|
||||
});
|
||||
}
|
||||
|
||||
sheetData.push(rowData);
|
||||
}
|
||||
|
||||
return [sheetNames[index], sheetData];
|
||||
})
|
||||
));
|
||||
|
||||
return new Map(await Promise.all(sheetDataPs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a cell value to the appropriate JavaScript type based on its cell type.
|
||||
* @param {SheetCellRawContent} _
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user