""" MoinMoin - sctable a Processor for spread sheet calculations by sc @license: GNU GPL, see COPYING for details. PURPOSE: This processor is used to do some spread sheet calculation based on sc in a regular wiki table. The first column/first line coordinate is A0. CALLING SEQUENCE: {{{ #!sctable [-column_header, -row_header, -show_formular ] }}} INPUTS: -column_header: additional in the result the column header is shown -row_header: additional in the result the line number header is shown -show_formular: if set the formular instead of the result is shown, data is arranged in textmode. Blanks in formulars are removed EXAMPLE: {{{ #!sctable ||1||2||=A0+B0|| ||10||20||=@sum(A1:B1)|| }}} RESULT: ||<)>1.00||<)>2.00||<)>3.00|| ||<)>10.00||<)>20.00||<)>30.00|| ----- {{{ #!sctable ||1||||2||=A0+C0|| }}} RESULT: ||<)>1.00||<)>||<)>2.00||<)>3.00|| ----- {{{ #!sctable ||1||2||=A0+B0|| ||10||20||=@sum(A1:B1)|| ||=@sum(A0:A1)||=@sum(B0:B1)||=@sum(C0:C1)|| }}} RESULT: ||<)>1.00||<)>2.00||<)>3.00|| ||<)>10.00||<)>20.00||<)>30.00|| ||<)>11.00||<)>22.00||<)>33.00|| ----- {{{ #!sctable ||A||B||C|| ||1||2||=A1+B1|| ||10||20||=@sum(A2:B2)|| ||=@sum(A1:A2)||=@sum(B1:B2)||=@sum(C1:C2)|| }}} RESULT: ||<(>A||<(>B||<(>C|| ||<)>1.00||<)>2.00||<)>3.00|| ||<)>10.00||<)>20.00||<)>30.00|| ||<)>11.00||<)>22.00||<)>33.00|| ----- {{{ #!sctable -column_header ||1||2|| ||3||4|| ||5||6|| }}} RESULT: ||<:#CCCCCC>'''A'''||<:#CCCCCC>'''B'''|| ||<)>1.00||<)>2.00|| ||<)>3.00||<)>4.00|| ||<)>5.00||<)>6.00|| ----- {{{ #!sctable -row_header ||1||2|| ||3||4|| ||5||6|| }}} RESULT: ||<)#CCCCCC>'''0'''||<)>1.00||<)>2.00|| ||<)#CCCCCC>'''1'''||<)>3.00||<)>4.00|| ||<)#CCCCCC>'''2'''||<)>5.00||<)>6.00|| ----- {{{ #!sctable -column_header -row_header ||1||2|| ||3||4|| ||5||6|| }}} RESULT: ||<:#CCCCCC> ||<:#CCCCCC>'''A'''||<:#CCCCCC>'''B'''|| ||<)#CCCCCC>'''0'''||<)>1.00||<)>2.00|| ||<)#CCCCCC>'''1'''||<)>3.00||<)>4.00|| ||<)#CCCCCC>'''2'''||<)>5.00||<)>6.00|| ----- {{{ #!sctable -show_formular -column_header -row_header ||m||p|| ||1||=A1 * 5|| ||2||=A2-3|| ||3||4|| }}} RESULT: ||<:#CCCCCC> ||<:#CCCCCC>'''A'''||<:#CCCCCC>'''B'''|| ||<)#CCCCCC>'''0'''||<(>m||<(>p|| ||<)#CCCCCC>'''1'''||<(>1||<(>=A1*5|| ||<)#CCCCCC>'''2'''||<(>2||<(>=A2-3|| ||<)#CCCCCC>'''3'''||<(>3||<(>4|| ----- {{{ #!sctable -column_header ||Name Vorname|| || || 3 || || 5|| ||Name Vorname|| 1 || 2 || || 4 || 5|| ||Name Vorname|| 1 || 2 || || || 5|| }}} RESULT: ||<:#CCCCCC>'''A'''||<:#CCCCCC>'''B'''||<:#CCCCCC>'''C'''||<:#CCCCCC>'''D'''||<:#CCCCCC>'''E'''||<:#CCCCCC>'''F'''|| ||<)>Name Vorname|| || ||<(>3 || ||<(>5 || ||<)>Name Vorname|| 1 ||<(>2 || ||<(>4 ||<(>5|| ||<)>Name Vorname|| 1 ||<(>2 || || ||<(>5|| PROCEDURE: This processor needs the external sc (http://freshmeat.net/projects/sc/) routine. It is necessary to have a tmp directory in the wiki data dir. All formulars have to start by a "=" sign. Please remove the version number from the routine name! RESTRICTIONS: MODIFICATION: @copyright: 2004-09-19 by Reimar Bauer (R.Bauer@fz-juelich.de) sctable-1.2.3-1 1.2.3-2 : (RB) bug fixed line #!sctable was not found by giving input parameters 1.2.3-3 : (RB) input parameter -show_formular added, column width is set to 200 chars : if this parameter is used : (RB) bug removed (already) #!sctable position could be different from 0 : but always greater -1 1.2.3-4 : 2004-10-05 RB format always extended for sc call to 200 signs. bug with blanks in names removed, more as one blank in a cell handled as one blank. DISCUSSION: * we need a better routine to destinguish between strings and numbers """ Dependencies = [] import sys, os, re, sha from MoinMoin.parser import wiki from MoinMoin.action import AttachFile from MoinMoin.Page import Page import string,os config_sc_vartmp_dir = "./data/tmp" config_external_sc="/usr/bin/sc" def table2sc(lines,show_formular): result=[] r=0 name="=" # searchstring col_names=' ABCDEFGHIJKLMNOPQRSTUVWXYZ' #if (show_formular == 1): first_line=lines[0] col_list=first_line.split('||') c=0 form=[] for value in col_list: if (len(value.lstrip()) > 0): f="%(command)s %(column)s %(arg)s" %{ "command":"format", "column":col_names[c], "arg":"200 2 0" } form.append(f) c=c+1 result.append(form) for txt in lines: n_name=txt.count(name) txt=txt.lstrip() sargs=txt.split('||') n=len(sargs) sargs=sargs[0:n-1] c=0 # linecounter digits="=-.0123456789" for arg in sargs: if (len(arg) > 0): if arg[0] in digits: if (arg.find(name) == 0): if (show_formular == 0): sargs[c]="%(command)s %(column)s %(arg)s" %{ "command":'let ', "column":col_names[c]+str(r), "arg":string.strip(str(arg)) } else: arg=string.replace(arg,"="," =") sargs[c]="%(command)s %(column)s=%(arg)s" %{ "command":'leftstring', "column":col_names[c]+str(r), "arg":'"'+string.replace(str(arg),' ','')+'"' } else: if (show_formular == 0): sargs[c]="%(command)s %(column)s=%(arg)s" %{ "command":'let ', "column":col_names[c]+str(r), "arg":string.strip(str(arg)) } else: sargs[c]="%(command)s %(column)s=%(arg)s" %{ "command":'leftstring', "column":col_names[c]+str(r), "arg":'"'+string.replace(str(arg),' ','')+'"' } else: if (c > 0): if (string.strip(arg) == ""): arg="Blank!@" else: arg=string.strip(arg) arg=string.replace(arg," ","Blank!@") sargs[c]="%(command)s %(column)s=%(arg)s" %{ "command":'rightstring ', "column":col_names[c]+str(r), "arg":'"'+str(arg)+'"' } c=c+1 result.append(sargs) r=r+1 return(result) def process(request, formatter, lines): kw=string.split(lines[0]) column_header=0 row_header=0 show_formular=0 for test in kw: if (test == '-column_header') : column_header=1 if (test == '-row_header') : row_header=1 if (test == '-show_formular') : show_formular=1 if (lines[0].find("#!sctable") > -1): del lines[0] matrix = [] textstr = '\n'.join(lines).strip() tmpname = re.sub('\s+', ' ', textstr) tmpname = sha.new(tmpname).hexdigest() tmpname = tmpname + "_sc" tmpfile = "%s/%s.sc" % (config_sc_vartmp_dir, tmpname) textstr=table2sc(lines,show_formular) data = open(tmpfile, "w") i=0 for txt in textstr: if (len(textstr[i]) > 0): tmpstr=string.join(textstr[i],'\n') data.write('%s\n' % (tmpstr)) i=i+1 data.close() cmd = "%(external_sc)s %(argument)s %(file)s " % { "external_sc": config_external_sc, "argument": " -W% ", "file":tmpfile } f=os.popen(cmd,'r')# popen to get the result of the calculation result=f.readlines() f.flush() os.unlink(tmpfile) # remove the tmpfile right_format='<)>' left_format='<(>' for txt in result: txt=string.join(txt,'') numbers=string.split(txt,' ') zres='||' c=1 for value in numbers: value=string.join(value,'') value=string.strip(value) strlen=len(value) if (strlen > 0) : if value in " AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz": format=left_format else: if (show_formular == 0) : format=right_format else: format=left_format if (value == "Blank!@"): value=" " zres = zres + "%(format)s %(value)s %(tab)s" % { "format": format, "value": value, "tab":'||' } if string.find(zres,"Blank!@"): zres=string.replace(zres,"Blank!@", " ") c=c+1 matrix.append(zres) if (len(matrix[0]) == 2): # das ist noch nicht die beste Loesung (workaround) matrix=matrix[1:] if (row_header == 1): y=[] r=len(matrix) lines=range(r) i=0 for no in lines: matrix[i]="||<)#CCCCCC>'''"+str(no)+"'''"+matrix[i] i=i+1 if (column_header == 1): col_names=' ABCDEFGHIJKLMNOPQRSTUVWXYZ' x='||' if(row_header == 1): start=0 else: start=1 for name in col_names[start:c]: x = x + "%(format)s %(value)s %(tab)s" % { "format": '<:#CCCCCC>', "value": "'''"+name+"'''", "tab":'||'} matrix.insert(0,x) wikiizer = wiki.Parser(string.join(matrix,"\n"),request) # parser for wiki tabular wikiizer.format(formatter)