Open Tri-Vi opened 5 years ago
were you able to find the root cause?
@Tri-Vi Hi, I am getting similar issue with my excel file, attached. Bulk.xlsx
However, the code works well while parsing other newly created excel file. There is some problem with properties of TEST.xlsx and Bulk.xlsx. Please share in case you find the root cause.
Read Excel Code:
async writeData(filepath, values, prof_name){
workbook.xlsx.readFile(filepath)
.catch(function(error){
console.log(error)
})
.then(function(){
var worksheet = workbook.getWorksheet(1);
var row = worksheet.getRow(worksheet.actualRowCount+1);
var j=values.length;
for(var i=1; i<=j; i++){
row.getCell(i).value = values[i-1];
}
row.commit();
workbook.xlsx.writeFile(downloadsFolder()+'/' +prof_name+'.xlsx');
})
}
Not sure of the exact root cause, but opening the file in Excel and saving it again works.
@amit-coditas @Tri-Vi I have had similar issue with apache poi(java), it would not be able to write into this same excel when downloaded. If it is opened and saved manually, it worked. How do we automate in such case? Any thoughts?
@dirasangtani , @amit-coditas : I haven't found the root cause yet, but there is something wrong with the worksheet. It seems like the worksheet can't be created for those excel files. I switch over to this package https://www.npmjs.com/package/xlsx and the problem is solved.
I am referring the docs for xlsx module. https://docs.sheetjs.com/#sheetjs-js-xlsx However, I do not see how do I create cells and write.
I am getting error like this, TypeError: Cannot read property 'v' of undefined when I use - bulkSheet['A4'].v = 'My Value'; Any help?
I am referring the docs for xlsx module. https://docs.sheetjs.com/#sheetjs-js-xlsx However, I do not see how do I create cells and write.
I am getting error like this, TypeError: Cannot read property 'v' of undefined when I use - bulkSheet['A4'].v = 'My Value'; Any help?
Can you include your code here ?
I am referring the docs for xlsx module. https://docs.sheetjs.com/#sheetjs-js-xlsx However, I do not see how do I create cells and write. I am getting error like this, TypeError: Cannot read property 'v' of undefined when I use - bulkSheet['A4'].v = 'My Value'; Any help?
Can you include your code here ?
Hi,
Below is the code,
const xlsx = require('xlsx');
function writeDataBulkEmployee(filepath, values){
//read from xlsx file
let workbook = xlsx.readFile(filepath);
// get first sheet
var first_sheet = workbook.SheetNames[0];
console.log(first_sheet)
var bulkSheet = workbook.Sheets[first_sheet]
//This below loop writes just one row, expected 8
for(let i=1; i<=8; i++){
var str = 'A'+i;
workbook.Sheets[first_sheet][str] = {v:'232388270', t: 's'};
}
//This below did not work, array of arrays cannot be written
xlsx.utils.sheet_add_aoa(bulkSheet, [[4,5,6,7,8,9,0]], {origin: "-1"});
//Below is able to write only on first row
workbook.Sheets[first_sheet]['A1'] = {v:'232388270', t: 's'};
workbook.Sheets[first_sheet]['A2'] = {v:'232388270', t: 's'};
workbook.Sheets[first_sheet]['A3'] = {v:'232388270', t: 's'};
workbook.Sheets[first_sheet]['A4'] = {v:'232388270', t: 's'};
workbook.Sheets[first_sheet]['A5'] = {v:'232388270', t: 's'};
workbook.Sheets[first_sheet]['A6'] = {v:'232388270', t: 's'};
xlsx.writeFile(workbook, 'C:\\Users\\dira.sangtani\\Downloads\\SampleOutput.xls')
}
writeDataBulkEmployee('C:\\Users\\dira.sangtani\\Downloads\\Sample.xlsx')
@Tri-Vi did you get chance to look into this?
@Tri-Vi did you get chance to look into this?
Try this :
const XLSX = require('xlsx');
var book1 = __dirname + '/files/Book1.xlsx';
var data = [
{"name":"A"},
{"name":"B"},
{"name":"C"},
]
function testWriteFile(filePath, data){
/* make the worksheet */
var ws = XLSX.utils.json_to_sheet(data);
/* add to workbook */
var wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "Test");
console.log(wb);
/* generate an XLSX file */
XLSX.writeFile(wb, filePath);
}
testWriteFile(book1, data);
that situation is really often when some worksheets were been removed.
for example when workbook has sheets:
index | name | id |
---|---|---|
0 | Sheet 1 | 1 |
1 | Sheet 2 | 2 |
2 | Sheet 3 | 4 |
3 | SomeSheet | 3 |
then you remove Sheet 1
:
index | name | id |
---|---|---|
0 | Sheet 2 | 2 |
1 | Sheet 3 | 3 |
2 | SomeSheet | 4 |
then you remove Sheet 3
:
Index | name | id |
---|---|---|
0 | Sheet 2 | 2 |
1 | SomeSheet | 4 |
In this case, You can:
const first = wb.getWorksheet() // to get first worksheet (Sheet 2)
const withId2 = wb.getWorksheet(2) //to get worksheet with id === 2 (Sheet 2)
const byName = wb.getWorksheet("Sheet 2") //to get worksheet with specific name (Sheet 2)
const byIndex= wb.worksheets[0] //to get directly from worksheet array
and also you can't do that:
const byIndex = wb.getWorksheet(0) // becouse it try to get worksheet by ID not by Index in worksheet array
so, if you want to iterate through the worksheets, you should use wb.worksheets
array or wb.eachSheet
function
I encourage you to study sources- they are like a tutorial :)
https://github.com/exceljs/exceljs/blob/bbc4e43d60fa7e57b5296b1ea1225a0e3ec27eed/lib/doc/workbook.js#L102 https://github.com/exceljs/exceljs/blob/bbc4e43d60fa7e57b5296b1ea1225a0e3ec27eed/lib/doc/workbook.js#L115 https://github.com/exceljs/exceljs/blob/bbc4e43d60fa7e57b5296b1ea1225a0e3ec27eed/lib/doc/workbook.js#L123
@Siemienik thanks for your reply, but the error happens before we can get the worksheet. It's more related to workbook than worksheet.
// place where the error happens
// v
return this.workbook.xlsx.read(sheet).then(() => {
if (sheetNameOrIndex) this.worksheet = this.workbook.getWorksheet(sheetNameOrIndex);
Lib code that throws the error:
// exceljs/lib/xlsx/xlsx.js:269
case 'xl/workbook.xml': {
const workbook = await this.parseWorkbook(entry);
model.sheets = workbook.sheets;
working xl/workbook.xml
:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<workbook xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x15 xr xr6 xr10 xr2"
xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main"
xmlns:xr="http://schemas.microsoft.com/office/spreadsheetml/2014/revision"
xmlns:xr6="http://schemas.microsoft.com/office/spreadsheetml/2016/revision6"
xmlns:xr10="http://schemas.microsoft.com/office/spreadsheetml/2016/revision10"
xmlns:xr2="http://schemas.microsoft.com/office/spreadsheetml/2015/revision2">
<fileVersion appName="xl" lastEdited="7" lowestEdited="7" rupBuild="22730"/>
<workbookPr/>
<mc:AlternateContent xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
<mc:Choice Requires="x15">
<x15ac:absPath url="C:\Users\gabri\Desktop\"
xmlns:x15ac="http://schemas.microsoft.com/office/spreadsheetml/2010/11/ac"/>
</mc:Choice>
</mc:AlternateContent>
<xr:revisionPtr revIDLastSave="0" documentId="13_ncr:1_{E472DD84-332E-4E17-AA84-0D21183461C7}"
xr6:coauthVersionLast="45" xr6:coauthVersionMax="45"
xr10:uidLastSave="{00000000-0000-0000-0000-000000000000}"/>
<bookViews>
<workbookView xWindow="-120" yWindow="-120" windowWidth="29040" windowHeight="15840"
xr2:uid="{00000000-000D-0000-FFFF-FFFF00000000}"/>
</bookViews>
<sheets>
<sheet name="Sheet1" sheetId="1" r:id="rId1"/>
</sheets>
<calcPr calcId="0"/>
</workbook>
broken xl/workbook.xml
:
<?xml version="1.0" encoding="utf-8"?>
<x:workbook xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<x:fileVersion appName="SpreadsheetLight"/>
<x:bookViews>
<x:workbookView/>
</x:bookViews>
<x:sheets>
<x:sheet name="Sheet1" sheetId="1" r:id="R72a4c9e3da964db8"/>
</x:sheets>
</x:workbook>
how this file is generated?
I'm also getting this error on (new Excel.Workbook()).xlsx.readFile(fileName)
.
how this file is generated?
Users like me typically won't know how the file is generated (because it came from an external source), so that doesn't seem like a useful line of inquiry. I can corroborate that this situation occurs in the wild. It would be cool if this lib was capable of dealing with it.
Another reproduction case: file.xlsx
Seeing this on latest (4.2.0).
With some basic debugging, it seems like the order of files in the zip is the issue. The sheet parser is being called before the workbook has been parsed, so this.model
is still undefined. Opening the file in excel and resaving it makes it work, assuming that it reorders the files inside the xlsx zip.
Same file after it has been opened and resaved: file.xlsx
here is an attempted fix for this which seemed to be sufficient in my case
EDIT: I deleted my fork/fix in favor of @contra's PR #1570 which fixes this and a lot more
I've fixed this as a part of this PR: https://github.com/exceljs/exceljs/pull/1570
@contra & @Siemienik
I now have a very similar issue with worksheet names, which default to "SheetN" if workbook.xml.rels
is not parsed via _parseRels(entry)
before
const matchingRel = (this.workbookRels || []).find(
rel => rel.Target === `worksheets/sheet${sheetNo}.xml`
);
const matchingSheet =
matchingRel && (this.model.sheets || []).find(sheet => sheet.rId === matchingRel.Id);
if (matchingSheet) {
worksheetReader.id = matchingSheet.id;
worksheetReader.name = matchingSheet.name;
worksheetReader.state = matchingSheet.state;
}
is called.
maybe mandatory files such as workbook.xml.rels
and workbook.xml
should be searched for and parsed before everything else to avoid race conditions like this
@Privatecoder Does that issue exist on my fork or only in the regular version?
@contra both, latest stable + your fork.
Title is "Sheet1" but should be "my fancy title".
I added a console.log(entry.path)
to the for await (const entry of zip)
statement to find that some files are just not showing up.
@contra & @Siemienik
there seems to be an issue with unzipper using async iterators. any await (sample: 1000ms) results in any of the succeeding contents of the zip (here xlsx) to not be processed:
const fs = require('fs');
const unzipper = require('unzipper');
const test = async () => {
const stream = fs.createReadStream('test.xlsx');
const zip = stream.pipe(unzipper.Parse({forceStream: true}));
for await (const entry of zip) {
console.log(entry.path);
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
test();
output:
docProps/core.xml
vs.
const fs = require('fs');
const unzipper = require('unzipper');
const test = () => {
const stream = fs.createReadStream('test.xlsx');
const zip = stream.pipe(unzipper.Parse());
zip.on('entry', entry => {
console.log(entry.path);
})
}
test();
output:
docProps/core.xml
docProps/app.xml
xl/worksheets/sheet1.xml
xl/workbook.xml
xl/theme/theme1.xml
xl/styles.xml
[Content_Types].xml
_rels/.rels
xl/_rels/workbook.xml.rels
resolutions": {
"unzipper": "github:kinolaev/node-unzipper#patch-1"
}
Try this in your package.json and let me know if it helps
it doesn't – you can check the sample along with the attached test.xlsx
@Privatecoder What node version are you on?
@contra v12.18.0/macOS
EDIT: upgrading node to v14.16.0 fixes the issue.
@Privatecoder Thought that would be the case - I saw the same issue on 12 and 13, I make sure to just use 15 because streams had a few odd bugs in those versions. Even 14 had some weird issues.
Hi Everyone,
I reproduced this issue: Failed: Cannot read property 'sheets' of undefined
Configuration settings:
node - v: 14.16.0
"exceljs": "^4.2.1"
test File: testFile.xlsx
Code:
const ExcelJS = require('exceljs');
const pageComparisonXLSXFilePath = './testFile.xlsx';
const workbook = new ExcelJS.Workbook();
await workbook.xlsx.readFile(pageComparisonXLSXFilePath);
const worksheet = workbook.getWorksheet(1);
const rowC = worksheet.rowCount;
for (const row of worksheet.getRows(1, rowC)) {
console.log(row.values);
}
Error raises during next line execution: await workbook.xlsx.readFile(pageComparisonXLSXFilePath);
Steps to reproduce:
Could you help me?
Regards, Sergei.
is there any work aroud for this?
I was having the same error "Failed: Cannot read property 'sheets' of undefined", looking at the code I realise the problem was that Exceljs is prepared to deal with tags that do not start with "<x:.....".
Working excel:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<workbook
xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="x15 xr xr6 xr10 xr2"
xmlns:x15="http://schemas.microsoft.com/office/spreadsheetml/2010/11/main"
xmlns:xr="http://schemas.microsoft.com/office/spreadsheetml/2014/revision"
xmlns:xr6="http://schemas.microsoft.com/office/spreadsheetml/2016/revision6"
xmlns:xr10="http://schemas.microsoft.com/office/spreadsheetml/2016/revision10"
xmlns:xr2="http://schemas.microsoft.com/office/spreadsheetml/2015/revision2">
.....
</workbook>
Not working excel:
<?xml version="1.0" encoding="utf-8"?>
<x:workbook
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<x:workbookPr codeName="ThisWorkbook" />
<x:bookViews>
<x:workbookView firstSheet="0" activeTab="0" />
</x:bookViews>
<x:sheets>
<x:sheet name="Data" sheetId="2" r:id="rId2" />
</x:sheets>
<x:definedNames />
<x:calcPr calcId="125725" />
</x:workbook>
The solution for my problem(it's probably not the best or correct solution but so far is working, so well...) was to replace all "<x:..." for "<..." and "</x:" for "</" before writing into the stream.
File: xlsx.js. Function: load Line: 301
// use object mode to avoid buffer-string convention
stream = new PassThrough({
writableObjectMode: true,
readableObjectMode: true
});
let content;
// https://www.npmjs.com/package/process
if (process.browser) {
// running in browser, use TextDecoder if possible
content = bufferToString(await entry.async('nodebuffer'));
}
else {
// running in node.js
content = await entry.async('string');
}
content = content.replace(/<\w:/g, '<') // <--- Here
content = content.replace(/<\/\w:/g, '</') // <--- Here
const chunkSize = 16 * 1024;
for (let i = 0; i < content.length; i += chunkSize) {
stream.write(content.substring(i, i + chunkSize));
}
PS: xlsx.js is also striping the "x:" from the tags
@yocontra
is there any work aroud for this?
I have got limited time for volunteering in OSS. (This is a common problem for OSS projects I guess). If any issue is urgent please get in touch with me via mail consulting@siemienik.com .
About this issue, As you did https://github.com/exceljs/exceljs/pull/1570/ I'm going to review it again if my time passes.
Hi @Siemienik any news on this?
Having similar issue with "exceljs": "4.3.0"
, this issue is very annoying looks like library can't initialize the sheets
Cannot read properties of undefined (reading 'sheets')
hi @Siemienik , any ETA on this?
It's 5 years since 2019, any update? face same issue as @resourge https://github.com/exceljs/exceljs/issues/962#issuecomment-957299936 mentioned.
I got this error when I tested the parsing process from an excel file. Hope someone can help me with this
Excel File: TEST.xlsx
exceljs version: 2.0.1