Source code for odml_xls_table

# -*- coding: utf-8 -*-
"""

"""

from odml_table import OdmlTable
import xlwt
from xls_style import XlsStyle
import datetime


[docs]class OdmlXlsTable(OdmlTable): """ Class to create a csv-file from an odml-file :param sheetname: name of the excel sheet; default is 'sheet1' :param header_style: style used for the header of the table :param first_style: default style used for the rows :param second_style: used to switch styles of the rows if changing_point is not None :param first_marked_style: default style used in marked columns :param second_marked_style: used to switch styles of the rows in marked columns if changing_point is not None :param pattern: can be 'alternating' or 'checkerboard' :param changing_point: select the point for changing styles. this can be when a new section, property or value starts ('sections', 'properties', 'values' or None) :type sheetname: string :type header_style: XlsStyle :type first_style: XlsStyle :type second_style: XlsStyle :type first_marked_style: XlsStyle :type second_marked_style: XlsStyle :type pattern: string :type changing_point: string """ def __init__(self, load_from = None): super(OdmlXlsTable, self).__init__(load_from=load_from) self.sheetname = "sheet1" self._marked_cols = ["Value"] self.document_info_style = XlsStyle(backcolor='white', fontcolor='gray80', fontstyle='bold 1') self.header_style = XlsStyle(backcolor='gray80', fontcolor='white', fontstyle='bold 1') self.first_style = XlsStyle(backcolor='dark_blue', fontcolor='white', fontstyle='') self.second_style = XlsStyle(backcolor='green', fontcolor='white', fontstyle='') self.first_marked_style = XlsStyle(backcolor='light_blue', fontcolor='black', fontstyle='') self.second_marked_style = XlsStyle(backcolor='lime', fontcolor='black', fontstyle='') self.highlight_style = XlsStyle(backcolor='red', fontcolor='black', fontstyle='') self._highlight_defaults = False self._pattern = 'alternating' self._changing_point = 'sections' # TODO: python properties?? @property def changing_point(self): return self._changing_point @changing_point.setter def changing_point(self, point): if point in ["sections", "properties", "values", None]: self._changing_point = point else: raise Exception("Your changing point must be 'sections', " + "'properties', 'values' or None") # TODO: exceptions @property def pattern(self): return self._pattern @pattern.setter def pattern(self, pat): if pat in ['alternating', 'checkerboard']: self._pattern = pat else: raise Exception("This pattern does not exist") @property def highlight_defaults(self): return self._highlight_defaults @highlight_defaults.setter def highlight_defaults(self, mode): if mode in [True, False]: self._highlight_defaults = mode else: try: self._highlight_defaults = bool(mode) except: raise TypeError('Mode "{}" can not be' 'converted to boolean.' ''.format(str(mode)))
[docs] def mark_columns(self, *args): """ choose the columns of the table you want to highlight by giving them another style (for example a different color). Possible Arguments are: - 'Path' - 'SectionName' - 'SectionType' - 'SectionDefinition' - 'PropertyName' - 'PropertyDefinition' - 'Value' - 'ValueDefinition' - 'DataUnit' - 'DataUncertainty' - 'odmlDatatype'. """ cols = [] for arg in args: if arg in self._header_titles.keys(): cols.append(arg) else: raise Exception("wrong argument") # TODO: exception... self._marked_cols = cols
[docs] def write2file(self, save_to): """ writes the data from the odml-file to a xls-file :param save_to: name of the xls-file :type save_to: string """ self.consistency_check() styles = {"document_info": xlwt.easyxf( self.document_info_style.get_style_string()), "header": xlwt.easyxf(self.header_style.get_style_string()), "row0col0": xlwt.easyxf(self.first_style.get_style_string()), "row1col0": xlwt.easyxf(self.second_style.get_style_string()), "row0col1": xlwt.easyxf(self.first_marked_style.get_style_string()), "row1col1": xlwt.easyxf(self.second_marked_style.get_style_string()), "highlight": xlwt.easyxf(self.highlight_style.get_style_string())} workbook = xlwt.Workbook() sheet = workbook.add_sheet(self.sheetname) oldpath = "" oldprop = "" oldrow = [] row = 0 doclen = len(self._docdict) if self._docdict else 0 max_col_len = [1] * max(len(self._header), 2 * doclen + 1) for i, h in enumerate(self._header): if h != None: max_col_len[i] = len(self._header_titles[h]) col_style = 0 row_style = 0 if self._docdict: # add document information in first row sheet.write(row, 0, 'Document Information', styles["document_info"]) for a, attribute in enumerate(sorted(self._docdict)): sheet.write(row, 2 * a + 1, attribute, styles["document_info"]) sheet.write(row, 2 * a + 2, self._docdict[attribute], styles["document_info"]) # adjusting cell widths if len(attribute) > max_col_len[2 * a + 1]: max_col_len[2 * a + 1] = len(attribute) if self._docdict[attribute] != None and ( len(self._docdict[attribute]) > max_col_len[2 * a + 2]): max_col_len[2 * a + 2] = len(self._docdict[attribute]) row += 1 # write the header for col, h in enumerate(self._header): sheet.write(row, col, self._header_titles[h] if h in self._header_titles else "", styles['header']) row += 1 if self._odmldict != None: # write the rest of the rows for dic in self._odmldict: # make a copy of the actual dic row_dic = dic.copy() # removing unneccessary entries if dic["Path"] == oldpath: if not self.show_all_sections: for h in self._SECTION_INF: row_dic[h] = "" else: # start of a new section if self._changing_point is 'sections': row_style = (row_style + 1) % 2 # switch row-color oldpath = dic["Path"] oldprop = "" if dic["PropertyName"] == oldprop: if not self.show_all_properties: for h in self._PROPERTY_INF: row_dic[h] = "" else: # start of a new property if self._changing_point is 'properties': row_style = (row_style + 1) % 2 # switch row-color oldprop = dic["PropertyName"] # check the changing point if self._changing_point is 'values': row_style = (row_style + 1) % 2 elif self._changing_point is None: pass elif not self._changing_point in ['sections', 'properties']: raise Exception( "Invalid argument for changing_point: Your " + "changing_point must be 'sections', " + "'properties', 'values' or None") # TODO: change exception # row_content: only those elements of row_dic, that will be # visible in the table row_content = [row_dic[h] if h != None else '' for h in self._header] # check, if row would be empty or same as the row before; # if so, skip the row if ((row_content == oldrow) or (row_content == ['' for h in self._header])): continue else: oldrow = list(row_content) for col, h in enumerate(self._header): if self._pattern is "checkerboard": row_style = (row_style + 1) % 2 elif self._pattern is "alternating": row_style = row_style else: raise Exception("this is not a valid argument") # TODO: better exception # adjust column style if h in self._marked_cols: col_style = 1 else: col_style = 0 stylestring = "row" + str(row_style) + "col" + str( col_style) # special style for highlighting default values if (h == 'Value' and self._highlight_defaults and row_dic['Value'] == self.odtypes.default_value( row_dic['odmlDatatype'])): stylestring = 'highlight' style = styles[stylestring] if h != None: cell_content = row_dic[h] else: cell_content = '' # special style for datetime-objects if isinstance(cell_content, datetime.datetime): style.num_format_str = "DD-MM-YYYY HH:MM:SS" elif isinstance(cell_content, datetime.date): style.num_format_str = "DD-MM-YYYY" elif isinstance(cell_content, datetime.time): style.num_format_str = "HH:MM:SS" else: style.num_format_str = "" # finding longest string in the column if len(unicode(cell_content)) > max_col_len[col]: max_col_len[col] = len(str(cell_content)) sheet.write(row, col, cell_content, style) row += 1 # adjust the size of the columns due to the max length of the content for i, l in enumerate(max_col_len): sheet.col(i).width = 256 * (l + 1) workbook.save(save_to)