summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/tex/lualatex/odsfile
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2012-08-13 22:42:32 +0000
committerKarl Berry <karl@freefriends.org>2012-08-13 22:42:32 +0000
commit06c486e19ae6f98bf02be91b7d502e940c596d20 (patch)
treecfe172c44e8b94c2c4511228c0eeef9c4ecde63c /Master/texmf-dist/tex/lualatex/odsfile
parent891d790aa1dafff5340c181e3dce3332526e4834 (diff)
new (semi-old) luatex package odsfile (13aug12)
git-svn-id: svn://tug.org/texlive/trunk@27395 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/lualatex/odsfile')
-rw-r--r--Master/texmf-dist/tex/lualatex/odsfile/odsfile.lua178
-rw-r--r--Master/texmf-dist/tex/lualatex/odsfile/odsfile.sty180
2 files changed, 358 insertions, 0 deletions
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