-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
remove empty worksheet[0] from _worksheets #231
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just ran into a similar issue:
TypeError: Cannot read property 'name' of undefined
at /home/ruben/repos/finturanode/node_modules/exceljs/lib/stream/xlsx/workbook-writer.js:197:25
The reason is that the function nextId
begins counting the sheets by one. But arrays start with zero and otherwise the sheets are saved in a sparsed array with the first entry never existing (this is also leading to bad performance due to v8 not being able to optimize this).
So a proper fix would not be to filter everything but to just fix that function. Just set i
to zero and remove the || 1
in the return value.
A simple regression test would be something like:
const Stream = require('stream')
const Excel = require('exceljs')
const stream = new Stream.Writable({ write: function noop () {} })
const workbook = new Excel.stream.xlsx.WorkbookWriter({
stream: stream
})
workbook.addWorksheet('first')
workbook.getWorksheet('w00t') // cannot read property 'name' of undefined
@BridgeAR thanks for suggestion! while it seems reasonable to index from 0, i fear such a change of interface would break a lot of dependent code since it is possible to access sheets using their generated id:
there seem to be however more places where the loose array poses a problem - i will look into it deeper next week ps: you are 100% right filtering everything is an overkill - simply slicing the first item would be enough |
@pookong yes, this is a minimal behavior change but at least right now I do not see a better way to do this. It would be nice if semver would be used but this is not the case, so breaking changes might be in any update but I might be wrong. And this is a very trivial bug fix that fixes lots of side effects opposed to quite a few difficulties to work around this and keep the current behavior. @guyonroche could you give us a brief update on your view to this issue? :-) |
@pookong, @BridgeAR I've added unit-tests to cover the cannot read property 'name' of undefined issue I'll investigate the effects of this PR this weekend |
I think filtering is fine - after all, the arrays of worksheets will typically be small. |
@guyonroche well in that case I recommend to change the There does not have to be a breaking change by just fixing the getter in the calling method. But using sparse arrays is not a good idea and will likely have more side effects than here visible. And I guess you do not want to special handle zero everytime. So I'd say a better solution would be something like: class Workbook {
// ...
getWorksheet (index) {
if (typeof index === 'number') {
if (index <= 0) {
throw new TypeError('The index has to be 1 or above')
}
index--
// Do original stuff
} else ...
}
} |
_worksheets are saved as a loose array with undefined item[0]
when counting number of worksheets in xform models the .length is used - includes item[0]
when inserting worksheets into xml then .forEach method is used - excludes item[0]
this results in docProps/app.xml with data for a workbook with a single worksheet
foo
like:error being in
vt:vector
of size 2 with only one item inside