def _create_freeze_panes( self, sheet_name: str, freeze_panes: Tuple[int, int] ) -> None: """ Create freeze panes in the sheet. Parameters ---------- sheet_name : str Name of the spreadsheet freeze_panes : tuple of (int, int) Freeze pane location x and y """ from odf.config import ( ConfigItem, ConfigItemMapEntry, ConfigItemMapIndexed, ConfigItemMapNamed, ConfigItemSet, ) config_item_set = ConfigItemSet(name="ooo:view-settings") self.book.settings.addElement(config_item_set) config_item_map_indexed = ConfigItemMapIndexed(name="Views") config_item_set.addElement(config_item_map_indexed) config_item_map_entry = ConfigItemMapEntry() config_item_map_indexed.addElement(config_item_map_entry) config_item_map_named = ConfigItemMapNamed(name="Tables") config_item_map_entry.addElement(config_item_map_named) config_item_map_entry = ConfigItemMapEntry(name=sheet_name) config_item_map_named.addElement(config_item_map_entry) config_item_map_entry.addElement( ConfigItem(name="HorizontalSplitMode", type="short", text="2") ) config_item_map_entry.addElement( ConfigItem(name="VerticalSplitMode", type="short", text="2") ) config_item_map_entry.addElement( ConfigItem( name="HorizontalSplitPosition", type="int", text=str(freeze_panes[0]) ) ) config_item_map_entry.addElement( ConfigItem( name="VerticalSplitPosition", type="int", text=str(freeze_panes[1]) ) ) config_item_map_entry.addElement( ConfigItem(name="PositionRight", type="int", text=str(freeze_panes[0])) ) config_item_map_entry.addElement( ConfigItem(name="PositionBottom", type="int", text=str(freeze_panes[1])) )
def doit(args): logfile = args.logger if args.report: logfile.loglevel = args.report try: root = ET.parse(args.input).getroot() except: logfile.log("Error parsing FTML input", "S") if args.font: # font(s) specified on command line fontlist = getfonts(args.font, logfile) else: # get font spec from FTML fontsrc element fontlist = getfonts([root.find("./head/fontsrc").text], logfile, False) #fontlist = getfonts( [fs.text for fs in root.findall("./head/fontsrc")], False ) ### would allow multiple fontsrc elements numfonts = len(fontlist) if numfonts == 0: logfile.log("No font(s) specified", "S") if numfonts > 1: formattedfontnum = ["{0:02d}".format(n) for n in range(numfonts)] else: formattedfontnum = [""] logfile.log("Font(s) specified:", "V") for n, (fontname, bold, italic, embeddedfont) in enumerate(fontlist): logfile.log( " " + formattedfontnum[n] + " " + fontname + BoldItalic(bold, italic) + " " + str(embeddedfont), "V") # get optional fontscale; compute pointsize as int(12*fontscale/100). If result xx is not 12, then add "fo:font-size=xxpt" in Px styles pointsize = 12 fontscaleel = root.find("./head/fontscale") if fontscaleel != None: fontscale = fontscaleel.text try: pointsize = int(int(fontscale) * 12 / 100) except ValueError: # any problem leaves pointsize 12 logfile.log("Problem with fontscale value; defaulting to 12 point", "W") # Get FTML styles and generate LO writer styles # P2 is paragraph style for string element when no features specified # each Px (for P3...) corresponds to an FTML style, which specifies lang or feats or both # if numfonts > 1, two-digit font number is appended to make an LO writer style for each FTML style + font combo # When LO writer style is used with attribute rtl="True", "R" appended to style name LOstyles = {} ftmlstyles = {} Pstylenum = 2 LOstyles["P2"] = ("", None, None) ftmlstyles[0] = "P2" for s in root.findall("./head/styles/style"): Pstylenum += 1 Pnum = "P" + str(Pstylenum) featstring = "" if s.get('feats'): featstring = parsefeats(s.get('feats')) langname = None countryname = None lang = s.get('lang') if lang != None: x = re.match(langcode, lang) langname = x.group('langname') countryname = x.group('countryname') # FTML <test> element @stylename attribute references this <style> element @name attribute ftmlstyles[s.get('name')] = Pnum LOstyles[Pnum] = (featstring, langname, countryname) # create LOwriter file and construct styles for tables, column widths, etc. LOdoc = OpenDocumentText() init(LOdoc, numfonts) # Initialize sequence counters sds = SequenceDecls() sd = sds.addElement( SequenceDecl(displayoutlinelevel='0', name='Illustration')) sd = sds.addElement(SequenceDecl(displayoutlinelevel='0', name='Table')) sd = sds.addElement(SequenceDecl(displayoutlinelevel='0', name='Text')) sd = sds.addElement(SequenceDecl(displayoutlinelevel='0', name='Drawing')) LOdoc.text.addElement(sds) # Create Px style for each (featstring, langname, countryname) tuple in LOstyles # and for each font (if >1 font, append to Px style name a two-digit number corresponding to the font in fontlist) # and (if at least one rtl attribute) suffix of nothing or "R" # At the same time, collect info for creating FontFace elements (and any embedded fonts) suffixlist = ["", "R" ] if root.find(".//test/[@rtl='True']") != None else [""] fontfaces = {} for p in sorted(LOstyles, key=lambda x: int(x[1:]) ): # key = lambda x : int(x[1:]) corrects sort order featstring, langname, countryname = LOstyles[p] for n, (fontname, bold, italic, embeddedfont) in enumerate( fontlist): # embeddedfont = None if no embedding needed fontnum = formattedfontnum[n] # Collect fontface info: need one for each font family + feature combination # Put embedded font in list only under fontname with empty featstring if (fontname, featstring) not in fontfaces: fontfaces[(fontname, featstring)] = [] if embeddedfont: if (fontname, "") not in fontfaces: fontfaces[(fontname, "")] = [] if embeddedfont not in fontfaces[(fontname, "")]: fontfaces[(fontname, "")].append(embeddedfont) # Generate paragraph styles for s in suffixlist: pstyle = Style(name=p + fontnum + s, family="paragraph") if s == "R": pstyle.addElement( ParagraphProperties(textalign="end", justifysingleword="false", writingmode="rl-tb")) pstyledic = {} pstyledic['fontnamecomplex'] = \ pstyledic['fontnameasian'] =\ pstyledic['fontname'] = fontname + featstring pstyledic['fontsizecomplex'] = \ pstyledic['fontsizeasian'] = \ pstyledic['fontsize'] = str(pointsize) + "pt" if bold: pstyledic['fontweightcomplex'] = \ pstyledic['fontweightasian'] = \ pstyledic['fontweight'] = 'bold' if italic: pstyledic['fontstylecomplex'] = \ pstyledic['fontstyleasian'] = \ pstyledic['fontstyle'] = 'italic' if langname != None: pstyledic['languagecomplex'] = \ pstyledic['languageasian'] = \ pstyledic['language'] = langname if countryname != None: pstyledic['countrycomplex'] = \ pstyledic['countryasian'] = \ pstyledic['country'] = countryname pstyle.addElement(TextProperties(attributes=pstyledic)) # LOdoc.styles.addElement(pstyle) ### tried this, but when saving the generated odt, LO changed them to automatic styles LOdoc.automaticstyles.addElement(pstyle) fontstoembed = [] for fontname, featstring in sorted( fontfaces ): ### Or find a way to keep order of <style> elements from original FTML? ff = FontFace(name=fontname + featstring, fontfamily=fontname + featstring, fontpitch="variable") LOdoc.fontfacedecls.addElement(ff) if fontfaces[(fontname, featstring)]: # embedding needed for this combination for fontfile in fontfaces[(fontname, featstring)]: fontstoembed.append(fontfile) # make list for embedding ffsrc = FontFaceSrc() ffuri = FontFaceUri( **{ 'href': "Fonts/" + os.path.basename(fontfile), 'type': "simple" }) ffformat = FontFaceFormat(**{'string': 'truetype'}) ff.addElement(ffsrc) ffsrc.addElement(ffuri) ffuri.addElement(ffformat) basename = "Table1.B" colorcount = 0 colordic = { } # record color #rrggbb as key and "Table1.Bx" as stylename (where x is current color count) tablenum = 0 # get title and comment and use as title and subtitle titleel = root.find("./head/title") if titleel != None: LOdoc.text.addElement( H(outlinelevel=1, stylename="Title", text=titleel.text)) commentel = root.find("./head/comment") if commentel != None: LOdoc.text.addElement(P(stylename="Subtitle", text=commentel.text)) # Each testgroup element begins a new table for tg in root.findall("./testgroup"): # insert label attribute of testgroup element as subtitle tglabel = tg.get('label') if tglabel != None: LOdoc.text.addElement( H(outlinelevel=1, stylename="Subtitle", text=tglabel)) # insert text from comment subelement of testgroup element tgcommentel = tg.find("./comment") if tgcommentel != None: #print("commentel found") LOdoc.text.addElement(P(text=tgcommentel.text)) tgbg = tg.get( 'background') # background attribute of testgroup element tablenum += 1 table = Table(name="Table" + str(tablenum), stylename="Table1") table.addElement(TableColumn(stylename="Table1.A")) for n in range(numfonts): table.addElement(TableColumn(stylename="Table1.B")) table.addElement(TableColumn(stylename="Table1.A")) table.addElement(TableColumn(stylename="Table1.D")) for t in tg.findall("./test"): # Each test element begins a new row # stuff to start the row labeltext = t.get('label') stylename = t.get('stylename') stringel = t.find('./string') commentel = t.find('./comment') rtlsuffix = "R" if t.get('rtl') == 'True' else "" comment = commentel.text if commentel != None else None colBstyle = "Table1.A1" tbg = t.get( 'background' ) # get background attribute of test group (if one exists) if tbg == None: tbg = tgbg if tbg != None: # if background attribute for test element (or background attribute for testgroup element) if tbg not in colordic: # if color not found in color dic, create new style colorcount += 1 newname = basename + str(colorcount) colordic[tbg] = newname tb1style = Style(name=newname, family="table-cell") tb1style.addElement( TableCellProperties( attributes={ 'padding': "0.0382in", 'border': "0.05pt solid #000000", 'backgroundcolor': tbg })) LOdoc.automaticstyles.addElement(tb1style) colBstyle = colordic[tbg] row = TableRow() table.addElement(row) # fill cells # column A (label) cell = TableCell(stylename="Table1.A1", valuetype="string") if labeltext: cell.addElement( P(stylename="Table_20_Contents", text=labeltext)) row.addElement(cell) # column B (string) for n in range(numfonts): Pnum = ftmlstyles[stylename] if stylename != None else "P2" Pnum = Pnum + formattedfontnum[n] + rtlsuffix ### not clear if any of the following can be moved outside loop and reused cell = TableCell(stylename=colBstyle, valuetype="string") par = P(stylename=Pnum) if len(stringel) == 0: # no <em> subelements par.addText(re.sub(backu, hextounichr, stringel.text)) else: # handle <em> subelement(s) if stringel.text != None: par.addElement( Span(stylename="T1", text=re.sub(backu, hextounichr, stringel.text))) for e in stringel.findall("em"): if e.text != None: par.addText(re.sub(backu, hextounichr, e.text)) if e.tail != None: par.addElement( Span(stylename="T1", text=re.sub(backu, hextounichr, e.tail))) cell.addElement(par) row.addElement(cell) # column C (comment) cell = TableCell(stylename="Table1.A1", valuetype="string") if comment: cell.addElement(P(stylename="Table_20_Contents", text=comment)) row.addElement(cell) # column D (stylename) cell = TableCell(stylename="Table1.A1", valuetype="string") if comment: cell.addElement( P(stylename="Table_20_Contents", text=stylename)) row.addElement(cell) LOdoc.text.addElement(table) LOdoc.text.addElement(P(stylename="Subtitle", text="")) # Empty paragraph to end ### necessary? try: if fontstoembed: logfile.log("Embedding fonts in document", "V") for f in fontstoembed: LOdoc._extra.append( OpaqueObject( filename="Fonts/" + os.path.basename(f), mediatype= "application/x-font-ttf", ### should be "application/font-woff" or "/font-woff2" for WOFF fonts, "/font-opentype" for ttf content=io.open(f, "rb").read())) ci = ConfigItem(**{ 'name': 'EmbedFonts', 'type': 'boolean' }) ### (name = 'EmbedFonts', type = 'boolean') ci.addText('true') cis = ConfigItemSet(**{'name': 'ooo:configuration-settings' }) ### (name = 'ooo:configuration-settings') cis.addElement(ci) LOdoc.settings.addElement(cis) except: logfile.log("Error embedding fonts in document", "E") logfile.log("Writing output file: " + args.output, "P") LOdoc.save(unicode(args.output)) return
def doit(args) : logfile = args.logger if args.report: logfile.loglevel = args.report try: root = ET.parse(args.input).getroot() except: logfile.log("Error parsing FTML input", "S") if args.font: # font(s) specified on command line fontlist = getfonts( args.font, logfile ) else: # get font spec from FTML fontsrc element fontlist = getfonts( [root.find("./head/fontsrc").text], logfile, False ) #fontlist = getfonts( [fs.text for fs in root.findall("./head/fontsrc")], False ) ### would allow multiple fontsrc elements numfonts = len(fontlist) if numfonts == 0: logfile.log("No font(s) specified", "S") if numfonts > 1: formattedfontnum = ["{0:02d}".format(n) for n in range(numfonts)] else: formattedfontnum = [""] logfile.log("Font(s) specified:", "V") for n, (fontname, bold, italic, embeddedfont) in enumerate(fontlist): logfile.log(" " + formattedfontnum[n] + " " + fontname + BoldItalic(bold, italic) + " " + str(embeddedfont), "V") # get optional fontscale; compute pointsize as int(12*fontscale/100). If result xx is not 12, then add "fo:font-size=xxpt" in Px styles pointsize = 12 fontscaleel = root.find("./head/fontscale") if fontscaleel != None: fontscale = fontscaleel.text try: pointsize = int(int(fontscale)*12/100) except ValueError: # any problem leaves pointsize 12 logfile.log("Problem with fontscale value; defaulting to 12 point", "W") # Get FTML styles and generate LO writer styles # P2 is paragraph style for string element when no features specified # each Px (for P3...) corresponds to an FTML style, which specifies lang or feats or both # if numfonts > 1, two-digit font number is appended to make an LO writer style for each FTML style + font combo # When LO writer style is used with attribute rtl="True", "R" appended to style name LOstyles = {} ftmlstyles = {} Pstylenum = 2 LOstyles["P2"] = ("", None, None) ftmlstyles[0] = "P2" for s in root.findall("./head/styles/style"): Pstylenum += 1 Pnum = "P" + str(Pstylenum) featstring = "" if s.get('feats'): featstring = parsefeats(s.get('feats')) langname = None countryname = None lang = s.get('lang') if lang != None: x = re.match(langcode, lang) langname = x.group('langname') countryname = x.group('countryname') # FTML <test> element @stylename attribute references this <style> element @name attribute ftmlstyles[s.get('name')] = Pnum LOstyles[Pnum] = (featstring, langname, countryname) # create LOwriter file and construct styles for tables, column widths, etc. LOdoc = OpenDocumentText() init(LOdoc, numfonts) # Initialize sequence counters sds = SequenceDecls() sd = sds.addElement(SequenceDecl(displayoutlinelevel = '0', name = 'Illustration')) sd = sds.addElement(SequenceDecl(displayoutlinelevel = '0', name = 'Table')) sd = sds.addElement(SequenceDecl(displayoutlinelevel = '0', name = 'Text')) sd = sds.addElement(SequenceDecl(displayoutlinelevel = '0', name = 'Drawing')) LOdoc.text.addElement(sds) # Create Px style for each (featstring, langname, countryname) tuple in LOstyles # and for each font (if >1 font, append to Px style name a two-digit number corresponding to the font in fontlist) # and (if at least one rtl attribute) suffix of nothing or "R" # At the same time, collect info for creating FontFace elements (and any embedded fonts) suffixlist = ["", "R"] if root.find(".//test/[@rtl='True']") != None else [""] fontfaces = {} for p in sorted(LOstyles, key = lambda x : int(x[1:])): # key = lambda x : int(x[1:]) corrects sort order featstring, langname, countryname = LOstyles[p] for n, (fontname, bold, italic, embeddedfont) in enumerate(fontlist): # embeddedfont = None if no embedding needed fontnum = formattedfontnum[n] # Collect fontface info: need one for each font family + feature combination # Put embedded font in list only under fontname with empty featstring if (fontname, featstring) not in fontfaces: fontfaces[ (fontname, featstring) ] = [] if embeddedfont: if (fontname, "") not in fontfaces: fontfaces[ (fontname, "") ] = [] if embeddedfont not in fontfaces[ (fontname, "") ]: fontfaces[ (fontname, "") ].append(embeddedfont) # Generate paragraph styles for s in suffixlist: pstyle = Style(name=p+fontnum+s, family="paragraph") if s == "R": pstyle.addElement(ParagraphProperties(textalign="end", justifysingleword="false", writingmode="rl-tb")) pstyledic = {} pstyledic['fontnamecomplex'] = \ pstyledic['fontnameasian'] =\ pstyledic['fontname'] = fontname + featstring pstyledic['fontsizecomplex'] = \ pstyledic['fontsizeasian'] = \ pstyledic['fontsize'] = str(pointsize) + "pt" if bold: pstyledic['fontweightcomplex'] = \ pstyledic['fontweightasian'] = \ pstyledic['fontweight'] = 'bold' if italic: pstyledic['fontstylecomplex'] = \ pstyledic['fontstyleasian'] = \ pstyledic['fontstyle'] = 'italic' if langname != None: pstyledic['languagecomplex'] = \ pstyledic['languageasian'] = \ pstyledic['language'] = langname if countryname != None: pstyledic['countrycomplex'] = \ pstyledic['countryasian'] = \ pstyledic['country'] = countryname pstyle.addElement(TextProperties(attributes=pstyledic)) # LOdoc.styles.addElement(pstyle) ### tried this, but when saving the generated odt, LO changed them to automatic styles LOdoc.automaticstyles.addElement(pstyle) fontstoembed = [] for fontname, featstring in sorted(fontfaces): ### Or find a way to keep order of <style> elements from original FTML? ff = FontFace(name=fontname + featstring, fontfamily=fontname + featstring, fontpitch="variable") LOdoc.fontfacedecls.addElement(ff) if fontfaces[ (fontname, featstring) ]: # embedding needed for this combination for fontfile in fontfaces[ (fontname, featstring) ]: fontstoembed.append(fontfile) # make list for embedding ffsrc = FontFaceSrc() ffuri = FontFaceUri( **{'href': "Fonts/" + os.path.basename(fontfile), 'type': "simple"} ) ffformat = FontFaceFormat( **{'string': 'truetype'} ) ff.addElement(ffsrc) ffsrc.addElement(ffuri) ffuri.addElement(ffformat) basename = "Table1.B" colorcount = 0 colordic = {} # record color #rrggbb as key and "Table1.Bx" as stylename (where x is current color count) tablenum = 0 # get title and comment and use as title and subtitle titleel = root.find("./head/title") if titleel != None: LOdoc.text.addElement(H(outlinelevel=1, stylename="Title", text=titleel.text)) commentel = root.find("./head/comment") if commentel != None: LOdoc.text.addElement(P(stylename="Subtitle", text=commentel.text)) # Each testgroup element begins a new table for tg in root.findall("./testgroup"): # insert label attribute of testgroup element as subtitle tglabel = tg.get('label') if tglabel != None: LOdoc.text.addElement(H(outlinelevel=1, stylename="Subtitle", text=tglabel)) # insert text from comment subelement of testgroup element tgcommentel = tg.find("./comment") if tgcommentel != None: #print("commentel found") LOdoc.text.addElement(P(text=tgcommentel.text)) tgbg = tg.get('background') # background attribute of testgroup element tablenum += 1 table = Table(name="Table" + str(tablenum), stylename="Table1") table.addElement(TableColumn(stylename="Table1.A")) for n in range(numfonts): table.addElement(TableColumn(stylename="Table1.B")) table.addElement(TableColumn(stylename="Table1.A")) table.addElement(TableColumn(stylename="Table1.D")) for t in tg.findall("./test"): # Each test element begins a new row # stuff to start the row labeltext = t.get('label') stylename = t.get('stylename') stringel = t.find('./string') commentel = t.find('./comment') rtlsuffix = "R" if t.get('rtl') == 'True' else "" comment = commentel.text if commentel != None else None colBstyle = "Table1.A1" tbg = t.get('background') # get background attribute of test group (if one exists) if tbg == None: tbg = tgbg if tbg != None: # if background attribute for test element (or background attribute for testgroup element) if tbg not in colordic: # if color not found in color dic, create new style colorcount += 1 newname = basename + str(colorcount) colordic[tbg] = newname tb1style = Style(name=newname, family="table-cell") tb1style.addElement(TableCellProperties(attributes={'padding':"0.0382in", 'border':"0.05pt solid #000000", 'backgroundcolor':tbg})) LOdoc.automaticstyles.addElement(tb1style) colBstyle = colordic[tbg] row = TableRow() table.addElement(row) # fill cells # column A (label) cell = TableCell(stylename="Table1.A1", valuetype="string") if labeltext: cell.addElement(P(stylename="Table_20_Contents", text = labeltext)) row.addElement(cell) # column B (string) for n in range(numfonts): Pnum = ftmlstyles[stylename] if stylename != None else "P2" Pnum = Pnum + formattedfontnum[n] + rtlsuffix ### not clear if any of the following can be moved outside loop and reused cell = TableCell(stylename=colBstyle, valuetype="string") par = P(stylename=Pnum) if len(stringel) == 0: # no <em> subelements par.addText(re.sub(backu, hextounichr, stringel.text)) else: # handle <em> subelement(s) if stringel.text != None: par.addElement(Span(stylename="T1", text = re.sub(backu, hextounichr, stringel.text))) for e in stringel.findall("em"): if e.text != None: par.addText(re.sub(backu, hextounichr, e.text)) if e.tail != None: par.addElement(Span(stylename="T1", text = re.sub(backu, hextounichr, e.tail))) cell.addElement(par) row.addElement(cell) # column C (comment) cell = TableCell(stylename="Table1.A1", valuetype="string") if comment: cell.addElement(P(stylename="Table_20_Contents", text = comment)) row.addElement(cell) # column D (stylename) cell = TableCell(stylename="Table1.A1", valuetype="string") if comment: cell.addElement(P(stylename="Table_20_Contents", text = stylename)) row.addElement(cell) LOdoc.text.addElement(table) LOdoc.text.addElement(P(stylename="Subtitle", text="")) # Empty paragraph to end ### necessary? try: if fontstoembed: logfile.log("Embedding fonts in document", "V") for f in fontstoembed: LOdoc._extra.append( OpaqueObject(filename = "Fonts/" + os.path.basename(f), mediatype = "application/x-font-ttf", ### should be "application/font-woff" or "/font-woff2" for WOFF fonts, "/font-opentype" for ttf content = io.open(f, "rb").read() )) ci = ConfigItem(**{'name':'EmbedFonts', 'type': 'boolean'}) ### (name = 'EmbedFonts', type = 'boolean') ci.addText('true') cis=ConfigItemSet(**{'name':'ooo:configuration-settings'}) ### (name = 'ooo:configuration-settings') cis.addElement(ci) LOdoc.settings.addElement(cis) except: logfile.log("Error embedding fonts in document", "E") logfile.log("Writing output file: " + args.output, "P") LOdoc.save(unicode(args.output)) return