Can't parse some spreadsheets
Hey, thanks for developing this project - it is very useful to me. It works really well. Today I've encountered the edge case that prevents a successful read of the document (sorry, I can't disclose the actual file!).
After a bit of tinkering I've found the immediate cause. Here's the definition
of get-number-formats
:
(defun get-number-formats (zip)
(let ((format-codes (loop for fmt in (xmls:xmlrep-find-child-tags
:numFmt (xmls:xmlrep-find-child-tag
:numFmts (get-entry "xl/styles.xml" zip) nil))
collect (cons (parse-integer (xmls:xmlrep-attrib-value "numFmtId" fmt))
(xmls:xmlrep-attrib-value "formatCode" fmt)))))
(loop for style in (xmls:xmlrep-find-child-tags
:xf (xmls:xmlrep-find-child-tag
:cellXfs (get-entry "xl/styles.xml" zip)))
collect (let ((fmt-id (parse-integer (xmls:xmlrep-attrib-value "numFmtId" style))))
(cons fmt-id (if (< fmt-id 164)
:built-in
(cdr (assoc fmt-id format-codes))))))))
In my case the call
(xmls:xmlrep-find-child-tag :numFmts (get-entry "xl/styles.xml" zip) nil)
returns NIL which is preasumbly allowed because the third argument if-unfound
is specified as nil
instead of :error
. That leads to a call
(xmls:xmlrep-find-child-tags :numfmt nil)
That obviously fails because nil
can't return any children - the function
xmls:xmlrep-find-child-tags
calls xmlrep-children
on the treenode.
After reworking this function to ensure that the treenode is never nil the
files parses correctly. Here is how the function looks like after refactor:
(defun get-number-formats (zip)
(let* ((styles (get-entry "xl/styles.xml" zip))
(numfmt (and styles (xmls:xmlrep-find-child-tag :numFmts styles nil)))
(fcodes (and numfmt (loop for fmt in (xmls:xmlrep-find-child-tags :numFmt numfmt)
collect (cons (parse-integer (xmls:xmlrep-attrib-value "numFmtId" fmt))
(xmls:xmlrep-attrib-value "formatCode" fmt))))))
(loop for style in (xmls:xmlrep-find-child-tags :xf (xmls:xmlrep-find-child-tag :cellXfs styles))
collect (let ((fmt-id (parse-integer (xmls:xmlrep-attrib-value "numFmtId" style))))
(cons fmt-id (if (< fmt-id 164)
:built-in
(cdr (assoc fmt-id fcodes))))))))
I've patched the system locally and it parses other files without an issue. It would be great if this fix could be incorporated upstream, or perhaps address the issue in a more appropriate way (I have not read xlsx standard at all).
This should probably address #1 as well.
Best regards, Daniel