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 'chessfield' :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): OdmlTable.__init__(self) 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', 'chessfield']: 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))) 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 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._odmldict) 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 # 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 "chessfield": 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(str(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)
class CompareSectionXlsTable(CompareSectionTable): """ class to write a CompareSectionTable to a xls-file :param sheet_name: name of the excel-sheet, default is 'sheet1' :type sheet_name: string :param header_style: style used for the header :param first_style: style used for the values inside the table :param second_style: second style used for the values inside the table :param missing_value_style: if include_all is True, this style will be used if a property doesnt exist in the section, so they distinguish from properties with empty values :type header_style: XlsStyle :type first_style: XlsStyle :type second_style: XlsStyle :type missing_value_style: XlsStyle """ def __init__(self): CompareSectionTable.__init__(self) self.sheet_name = "sheet1" 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.missing_value_style = XlsStyle(backcolor="red", fontcolor="black", fontstyle="") def write2file(self, save_to): """ writes the table to an xls-file """ headerstyle = xlwt.easyxf(self.header_style.get_style_string()) missing_val_style = xlwt.easyxf(self.missing_value_style.get_style_string()) row_styles = [ xlwt.easyxf(self.first_style.get_style_string()), xlwt.easyxf(self.second_style.get_style_string()), ] properties, sections, table = self._build_table() workbook = xlwt.Workbook() sheet = workbook.add_sheet(self.sheet_name) max_col_len = [] if self.switch: for i, prop in enumerate([""] + properties): sheet.write(0, i, prop, headerstyle) max_col_len.append(len(str(prop))) for row_num, sec in enumerate(sections): sheet.write(row_num + 1, 0, sec, headerstyle) for row_num, row in enumerate(table): for col_num, elem in enumerate(row): if elem is None: style = missing_val_style cell_content = "" else: style = row_styles[row_num % 2] cell_content = elem 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 = "" sheet.write(row_num + 1, col_num + 1, cell_content, style) if len(str(cell_content)) > max_col_len[col_num]: max_col_len[col_num] = len(str(cell_content)) else: for i, sec in enumerate([""] + sections): sheet.write(0, i, sec, headerstyle) max_col_len.append(len(str(sec))) for row_num, prop in enumerate(properties): sheet.write(row_num + 1, 0, prop, headerstyle) for col_num, col in enumerate(table): for row_num, elem in enumerate(col): if elem is None: style = missing_val_style cell_content = "" else: style = row_styles[row_num % 2] cell_content = elem 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 = "" sheet.write(row_num + 1, col_num + 1, cell_content, style) if len(str(cell_content)) > max_col_len[col_num]: max_col_len[col_num] = len(str(cell_content)) # if self.switch: # csvwriter.writerow([''] + properties) # # for i, line in enumerate(table): # csvwriter.writerow([sections[i]] + line) # # else: # csvwriter.writerow([''] + sections) # # for i in range(len(table[0])): # csvwriter.writerow([properties[i]] + [table[j][i] # for j in range(len(table))]) # # for col, h in enumerate(header): # sheet.write(0, col, h, headerstyle) # max_col_len.append(len(h)) # # for row, dic in enumerate(table): # for col, h in enumerate(header): # if h in table[dic]: # cell_content = table[dic][h] # style = row_styles[row % 2] if col > 0 else headerstyle # 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 = "" # else: # cell_content = "" # style = missing_val_style # # sheet.write(row+1, col, cell_content, style) # if len(str(cell_content)) > max_col_len[col]: # max_col_len[col] = len(str(cell_content)) # # # adjust width of he columns # for col in range(len(header)): # sheet.col(col).width = (256 * (max_col_len[col]+1)) workbook.save(save_to)