#!/usr/bin/env python # -*- coding: windows-1251 -*- # Copyright (C) 2005 Roman V. Kiseliov # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # 3. All advertising materials mentioning features or use of this # software must display the following acknowledgment: # "This product includes software developed by # Roman V. Kiseliov ." # # 4. Redistributions of any form whatsoever must retain the following # acknowledgment: # "This product includes software developed by # Roman V. Kiseliov ." # # THIS SOFTWARE IS PROVIDED BY Roman V. Kiseliov ``AS IS'' AND ANY # EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Roman V. Kiseliov OR # ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED # OF THE POSSIBILITY OF SUCH DAMAGE. __rev_id__ = """$Id: Row.py,v 1.6 2005/08/11 08:53:48 rvk Exp $""" import BIFFRecords from Deco import * from Worksheet import Worksheet import Style import Cell import ExcelFormula import datetime as dt class Row(object): __slots__ = ["__init__", "__adjust_height", "__adjust_bound_col_idx", "__excel_date_dt", "get_height_in_pixels", "set_style", "get_xf_index", "get_cells_count", "get_min_col", "get_max_col", "get_str_count", "get_row_biff_data", "get_cells_biff_data", "get_index", "write", "write_blanks", # private variables "__idx", "__parent", "__parent_wb", "__cells", "__min_col_idx", "__max_col_idx", "__total_str", "__xf_index", "__has_default_format", "__height_in_pixels", # public variables "height", "has_default_height", "level", "collapse", "hidden", "space_above", "space_below"] ################################################################# ## Constructor ################################################################# def __init__(self, index, parent_sheet): self.__idx = index self.__parent = parent_sheet self.__parent_wb = parent_sheet.get_parent() self.__cells = [] self.__min_col_idx = 0 self.__max_col_idx = 0 self.__total_str = 0 self.__xf_index = 0x0F self.__has_default_format = 0 self.__height_in_pixels = 0x11 self.height = 0x00FF self.has_default_height = 0x00 self.level = 0 self.collapse = 0 self.hidden = 0 self.space_above = 0 self.space_below = 0 def __adjust_height(self, style): twips = style.font.height points = float(twips)/20.0 # Cell height in pixels can be calcuted by following approx. formula: # cell height in pixels = font height in points * 83/50 + 2/5 # It works when screen resolution is 96 dpi pix = int(round(points*83.0/50.0 + 2.0/5.0)) if pix > self.__height_in_pixels: self.__height_in_pixels = pix def __adjust_bound_col_idx(self, *args): for arg in args: if arg < self.__min_col_idx: self.__min_col_idx = arg elif arg > self.__max_col_idx: self.__max_col_idx = arg def __excel_date_dt(self, date): if isinstance(date, dt.date) and (not isinstance(date, dt.datetime)): epoch = dt.date(1899, 12, 31) elif isinstance(date, dt.time): date = dt.datetime.combine(dt.datetime(1900, 1, 1), date) epoch = dt.datetime(1900, 1, 1, 0, 0, 0) else: epoch = dt.datetime(1899, 12, 31, 0, 0, 0) delta = date - epoch xldate = delta.days + float(delta.seconds) / (24*60*60) # Add a day for Excel's missing leap day in 1900 if xldate > 59: xldate += 1 return xldate def get_height_in_pixels(self): return self.__height_in_pixels #accepts(object, Style.XFStyle) def set_style(self, style): self.__adjust_height(style) self.__xf_index = self.__parent_wb.add_style(style) def get_xf_index(self): return self.__xf_index def get_cells_count(self): return len(self.__cells) def get_min_col(self): return self.__min_col_idx def get_max_col(self): return self.__min_col_idx def get_str_count(self): return self.__total_str def get_row_biff_data(self): height_options = (self.height & 0x07FFF) height_options |= (self.has_default_height & 0x01) << 15 options = (self.level & 0x07) << 0 options |= (self.collapse & 0x01) << 4 options |= (self.hidden & 0x01) << 5 options |= (0x00 & 0x01) << 6 options |= (0x01 & 0x01) << 8 if self.__xf_index != 0x0F: options |= (0x01 & 0x01) << 7 else: options |= (0x00 & 0x01) << 7 options |= (self.__xf_index & 0x0FFF) << 16 options |= (0x00 & self.space_above) << 28 options |= (0x00 & self.space_below) << 29 return BIFFRecords.RowRecord(self.__idx, self.__min_col_idx, self.__max_col_idx, height_options, options).get() def get_cells_biff_data(self): return ''.join([ cell.get_biff_data() for cell in self.__cells ]) def get_index(self): return self.__idx #accepts(object, int, (str, unicode, int, float, dt.datetime, dt.time, dt.date, ExcelFormula.Formula), Style.XFStyle) def write(self, col, label, style): self.__adjust_height(style) self.__adjust_bound_col_idx(col) if isinstance(label, (str, unicode)): if len(label) > 0: self.__cells.extend([ Cell.StrCell(self, col, self.__parent_wb.add_style(style), self.__parent_wb.add_str(label)) ]) self.__total_str += 1 else: self.__cells.extend([ Cell.BlankCell(self, col, self.__parent_wb.add_style(style)) ]) elif isinstance(label, (int, float)): self.__cells.extend([ Cell.NumberCell(self, col, self.__parent_wb.add_style(style), label) ]) elif isinstance(label, (dt.datetime, dt.time)): self.__cells.extend([ Cell.NumberCell(self, col, self.__parent_wb.add_style(style), self.__excel_date_dt(label)) ]) else: self.__cells.extend([ Cell.FormulaCell(self, col, self.__parent_wb.add_style(style), label) ]) #accepts(object, int, int, Style.XFStyle) def write_blanks(self, c1, c2, style): self.__adjust_height(style) self.__adjust_bound_col_idx(c1, c2) self.__cells.extend([ Cell.MulBlankCell(self, c1, c2, self.__parent_wb.add_style(style)) ])