-
-
Save zauguin/a1c73bf596a08e51d8a9d94f485c8a27 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Requires slaxdom and slaxml from https://github.com/Phrogz/SLAXML | |
local slaxdom = require'slaxdom' | |
local xlsxNs = 'http://schemas.openxmlformats.org/spreadsheetml/2006/main' | |
local relNs = 'http://schemas.openxmlformats.org/officeDocument/2006/relationships' | |
local function filteredNext(ns, element) | |
local function iter(table, i) | |
i = i + 1 | |
local elem = table[i] | |
if not elem then | |
return nil | |
end | |
if elem.nsURI == ns and elem.name == element then | |
return i, elem | |
end | |
return iter(table, i) | |
end | |
return iter | |
end | |
local function elementIter(parent, ns, element) | |
return filteredNext(ns, element), parent.el, 0 | |
end | |
local function findAttr(element, ns, attr) | |
if not attr and ns then ns, attr = attr, ns end | |
for _,attribute in ipairs(element.attr) do | |
if attribute.nsURI == ns and attribute.name == attr then | |
return attribute.value | |
end | |
end | |
end | |
local function readDom(f, msg) | |
if not f then return f, msg end | |
local data = f:read'*a' | |
f:close() | |
return slaxdom:dom(data) | |
end | |
local f = assert(zip.open'how_should_i_know_how_you_call_your_files.xlsx') | |
local sheets = {} | |
local relationships do | |
local ns = 'http://schemas.openxmlformats.org/package/2006/relationships' | |
local dom = assert(readDom(f:open'xl/_rels/workbook.xml.rels')).root | |
relationships = {} | |
for _, rel in elementIter(dom, ns, 'Relationship') do | |
relationships[rel.attr.Id] = rel.attr.Target | |
end | |
end | |
local workbook = assert(readDom(f:open'xl/workbook.xml')).root | |
local worksheets = {} | |
for _, sheets in elementIter(workbook, xlsxNs, 'sheets') do | |
for _, sheet in elementIter(sheets, xlsxNs, 'sheet') do | |
local worksheet = assert(readDom(f:open('xl/' .. relationships[findAttr(sheet, relNs, 'id')]))).root | |
assert(worksheet.nsURI == xlsxNs and worksheet.name == 'worksheet') | |
local sheetData | |
for _, element in elementIter(worksheet, xlsxNs, 'sheetData') do | |
assert(not sheetData) | |
sheetData = element | |
end | |
assert(sheetData) | |
local rows = {} | |
for i, rowElement in elementIter(sheetData, xlsxNs, 'row') do | |
local row = {} | |
for j, colElem in elementIter(rowElement, xlsxNs, 'c') do | |
for _, entry in elementIter(colElem, xlsxNs, 'v') do | |
local value = entry.kids | |
if not value or #value == 0 then | |
value = nil | |
elseif #value == 1 and value[1].type == 'text' then | |
value = value[1].value | |
value = tonumber(value) or value | |
else | |
error'???' | |
end | |
row[j] = value | |
break | |
end | |
end | |
rows[i] = row | |
end | |
worksheets[sheet.attr.name] = rows | |
end | |
break | |
end | |
print(worksheets.Sheet1[5][2]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment