From 06c486e19ae6f98bf02be91b7d502e940c596d20 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Mon, 13 Aug 2012 22:42:32 +0000 Subject: new (semi-old) luatex package odsfile (13aug12) git-svn-id: svn://tug.org/texlive/trunk@27395 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/tex/lualatex/odsfile/odsfile.lua | 178 ++++++++++++++++++++ Master/texmf-dist/tex/lualatex/odsfile/odsfile.sty | 180 +++++++++++++++++++++ 2 files changed, 358 insertions(+) create mode 100644 Master/texmf-dist/tex/lualatex/odsfile/odsfile.lua create mode 100644 Master/texmf-dist/tex/lualatex/odsfile/odsfile.sty (limited to 'Master/texmf-dist/tex/lualatex/odsfile') diff --git a/Master/texmf-dist/tex/lualatex/odsfile/odsfile.lua b/Master/texmf-dist/tex/lualatex/odsfile/odsfile.lua new file mode 100644 index 00000000000..d305fb48a5f --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/odsfile/odsfile.lua @@ -0,0 +1,178 @@ +module(...,package.seeall) +require "zip" +xmlparser = require ("luaxml-mod-xml") +handler = require("luaxml-mod-handler") + + +function load(filename) + local p = { + file = zip.open(filename), + content_file_name = "content.xml", + loadContent = function(self,filename) + local treehandler = handler.simpleTreeHandler() + local filename = filename or self.content_file_name + local xmlfile = self.file:open(filename) + local text = xmlfile:read("*a") + local xml = xmlparser.xmlParser(treehandler) + xml:parse(text) + return treehandler + end + } + return p +end + +function getTable(x,table_name) + local tables = x.root["office:document-content"]["office:body"]["office:spreadsheet"]["table:table"] + if #tables > 1 then + if type(tables) == "table" and table_name ~= nil then + for k,v in pairs(tables) do + if(v["_attr"]["table:name"]==table_name) then + return v, k + end + end + elseif type(tables) == "table" and table_name == nil then + return tables[1], 1 + else + return tables + end + else + return tables + end +end + +function tableValues(tbl,x1,y1,x2,y2) + local t= {} + if type(tbl["table:table-row"])=="table" then + local rows = table_slice(tbl["table:table-row"],y1,y2) + for k,v in pairs(rows) do + -- In every sheet, there are two rows with no data at the bottom, we need to strip them + if(v["_attr"] and v["_attr"]["table:number-rows-repeated"] and tonumber(v["_attr"]["table:number-rows-repeated"])>10000) then break end + local j = {} + if #v["table:table-cell"] > 1 then + local r = table_slice(v["table:table-cell"],x1,x2) + for p,n in pairs(r) do + table.insert(j,{value=n["text:p"] or "",attr=n["_attr"]}) + end + else + local p = {value=v["table:table-cell"]["text:p"],attr=v["table:table-cell"]["_attr"]} + table.insert(j,p) + end + table.insert(t,j) + end + end + return t +end + +function getRange(range) + local r = range:lower() + local function getNumber(s) + if s == "" or s == nil then return nil end + local f,ex = 0,0 + for i in string.gmatch(s:reverse(),"(.)") do + f = f + (i:byte()-96) * 26 ^ ex + ex = ex + 1 + end + return f + end + for x1,y1,x2,y2 in r:gmatch("(%a*)(%d*):*(%a*)(%d*)") do + return getNumber(x1),tonumber(y1),getNumber(x2),tonumber(y2) + --print(string.format("%s, %s, %s, %s",getNumber(x1),y1,getNumber(x2),y2)) + end +end + +function table_slice (values,i1,i2) + -- Function from http://snippets.luacode.org/snippets/Table_Slice_116 + local res = {} + local n = #values + -- default values for range + i1 = i1 or 1 + i2 = i2 or n + if i2 < 0 then + i2 = n + i2 + 1 + elseif i2 > n then + i2 = n + end + if i1 < 1 or i1 > n then + return {} + end + local k = 1 + for i = i1,i2 do + res[k] = values[i] + k = k + 1 + end + return res +end + +function interp(s, tab) + return (s:gsub('(-%b{})', + function(w) + s = w:sub(3, -2) + s = tonumber(s) or s + return tab[s] or w + end) + ) +end + + +-- Interface for adding new rows to the spreadsheet + +function newRow() + local p = { + pos = 0, + cells = {}, + -- Generic function for inserting cell + addCell = function(self,val, attr,pos) + if pos then + table.insert(self.cells,pos,{["text:p"] = val, ["_attr"] = attr}) + self.pos = pos + else + self.pos = self.pos + 1 + table.insert(self.cells,self.pos,{["text:p"] = val, ["_attr"] = attr}) + end + end, + addString = function(self,s,attr,pos) + local attr = attr or {} + attr["office:value-type"] = "string" + self:addCell(s,attr,pos) + end, + addFloat = function(self,i,attr,pos) + local attr = attr or {} + local s = tonumber(i) or 0 + s = tostring(s) + attr["office:value-type"] = "float" + attr["office:value"] = s + self:addCell(s,attr,pos) + end, + findLastRow = function(self,sheet) + for i= #sheet["table:table-row"],1,-1 do + if sheet["table:table-row"][i]["_attr"]["table:number-rows-repeated"] then + return i + end + end + return #sheet["table:table-row"]+1 + end, + insert = function(self, sheet, pos) + local t = {} + local pos = pos or self:findLastRow(sheet) + print("pos je: ",pos) + if sheet["table:table-column"]["_attr"] and sheet["table:table-column"]["_attr"]["table:number-columns-repeated"] then + table_columns = sheet["table:table-column"]["_attr"]["table:number-columns-repeated"] + else + table_columns = #sheet["table:table-column"] + end + for i=1, table_columns do + table.insert(t,self.cells[i] or {}) + end + t = {["table:table-cell"]=t} + table.insert(sheet["table:table-row"],pos,t) + end + } + return p +end + + +-- function for updateing the archive. Depends on external zip utility +function updateZip(zipfile, updatefile) + local command = string.format("zip %s %s",zipfile, updatefile) + print ("Updating an ods file.\n" ..command .."\n Return code: ", os.execute(command)) +end diff --git a/Master/texmf-dist/tex/lualatex/odsfile/odsfile.sty b/Master/texmf-dist/tex/lualatex/odsfile/odsfile.sty new file mode 100644 index 00000000000..b4c7f617e18 --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/odsfile/odsfile.sty @@ -0,0 +1,180 @@ +\ProvidesPackage{odsfile.sty} +\RequirePackage{luacode,xkeyval} + +%keyval keys + +\define@key{includespread}{file}{\loadodsfile{#1}} +\define@key{includespread}{sheet}{\luaexec{sheetname = "\luatexluaescapestring{#1}"}} +\define@key{includespread}{range}{\luaexec{% +local x1,y1,x2,y2 = odsreader.getRange("\luatexluaescapestring{#1}")% +range = {x1,y1,x2,y2}% +}} +\define@key{includespread}{template}{\luaexec{currenttemplate="\luatexluaescapestring{#1}"}} +\define@key{includespread}{rowtemplate}{\luaexec{rowtemplate="\luatexluaescapestring{\unexpanded{#1}}"}} + +\define@choicekey*+{includespread}{rowseparator}[\val\nr]{tableline,hline,newline}[tableline]% +{% +\ifcase\nr\relax% + \luaexec{rowseparator=""}% +\or% + \luaexec{rowseparator="\\hline "}% +\or +\luaexec{% +rowseparator=[[\\n]] +} +\fi% +}{% + \luaexec{rowseparator="\luatexluaescapestring{#1}"} +} + +\define@choicekey*+{includespread}{columns}[\val\nr]{head,top,none}{% +\ifcase\nr\relax% + \luaexec{columns=1}% +\or% + \luaexec{columns=2}% +\fi% +}{% +\luaexec{% +local function split(s,sep) + local sep, fields = sep or ":", {} + local pattern = string.format("([^\%s]+)", sep) + s:gsub(pattern, function(c) fields[\#fields+1] = c end) + return fields +end +local s="\luatexluaescapestring{#1}" +columns = split(s,",") +}% +}{}% + + +% Variable initialization and helper functions +\begin{luacode*} +odsreader = require("odsfile") +odsfile = nil +sheetname = nil +range = {nil,nil,nil,nil} +columns = nil +templates = {} +row = {} +body = nil +odsfilename = "" +currenttemplate = nil +rowtemplate=nil +\end{luacode*} + +\newcommand\loadodsfile[2][]{% + \setkeys{includespread}{#1}% + \luaexec{% + odsfilename = "\luatexluaescapestring{#2}"% + local ods = odsreader.load(odsfilename)% + odsfile, e = ods:loadContent()% + }% +} + +\newcommand\tabletemplate[2]{% + \luaexec{% + templates["#1"]="\luatexluaescapestring{\unexpanded{#2}}" + } +} + +\newcommand\includespread[1][]{% + \luaexec{% + range = {nil,nil,nil,nil} + rowseparator = "" + columns=nil + currenttemplate = nil + rowtemplate = nil + }% + \setkeys{includespread}{#1}% + \luaexec{% + body = odsreader.getTable(odsfile,sheetname) + local values = odsreader.tableValues(body,range[1],range[2],range[3],range[4]) + %-- Conversion of odsfile table values to LaTeX tabular + local rowValues = function(row) + local t={} + for _,column in pairs(row) do table.insert(t,column.value) end + return t + end + if rowtemplate == nil then + currenttemplate = currenttemplate or "default" + content = {} + for i,row in pairs(values) do + table.insert(content,table.concat(rowValues(row)," & ")) + end + %-- Column headings handling + local colheading="" + if type(columns) == "number" and columns == 1 then + columns = rowValues(values[1]) + content = odsreader.table_slice(content,2,nil) + elseif type(columns) == "number" and columns == 2 then + local t = odsreader.tableValues(body,range[1],1,range[3],2) + columns = rowValues(t[1]) + end + if type(columns) == "table" then colheading = table.concat(columns," & ") .. "\\\\" end + coltypes = "" + if type(content)== "table" then coltypes= string.rep("l",\#content[1]) end + tex.print(odsreader.interp(templates[currenttemplate],{content=table.concat(content, "\\\\ "..rowseparator),coltypes=coltypes,colheading=colheading,rowsep=rowseparator})) + else + local content = {} + currenttemplate = currenttemplate or "empty" + for _,row in pairs(values) do + table.insert(content,odsreader.interp(rowtemplate,rowValues(row))) + end + content = table.concat(content,rowseparator) + tex.sprint(odsreader.interp(templates[currenttemplate],{content=content})) + end + } +} + +\tabletemplate{empty}{-{content}} + +\tabletemplate{default}{-{colheading}-{rowsep}-{content}} + +\tabletemplate{booktabs}{% +\begin{tabular}{-{coltypes}} +\toprule +-{colheading} +\midrule +-{content} +\\ \bottomrule +\end{tabular} +} + +% Interface for adding of new rows + +\newenvironment{AddRow}[1][]{% +\def\AddString##1##2{% +\luaexec{% +local pos = "\luatexluaescapestring{##2}"% +if pos == "" then pos = nil end; row:addString("\luatexluaescapestring{\unexpanded{##1}}",nil,pos)% +}% +}% +\def\AddNumber##1##2{% +\luaexec{% +local pos = "\luatexluaescapestring{##2}"% +if pos == "" then pos = nil end; row:addFloat("\luatexluaescapestring{##1}",nil,pos)% +}% +}% +\luaexec{% +pos = "\luatexluaescapestring{#1}"% +if pos == "" then pos = nil end; row = odsreader.newRow()% +}% +}{% +\luaexec{% +body = body or odsreader.getTable(odsfile) +row:insert(body,pos)% +}% +} + +% Interface for saving the spreadsheet + +\newcommand\savespreadsheet{% +\luaexec{% + local xml = require("luaxml-mod-xml") + f = io.open("content.xml","w")% + f:write(xml.serialize(odsfile.root))% + f:close()% + odsreader.updateZip(odsfilename,"content.xml")% +}% +} +\endinput -- cgit v1.2.3