Index: trunk/setup.py =================================================================== --- trunk/setup.py (revision 395) +++ trunk/setup.py (revision 398) @@ -3,7 +3,7 @@ __rev_id__ = """$Id: setup.py 3475 2008-09-18 12:39:27Z sjmachin $""" import sys, glob -from distutils.core import setup +from setuptools import setup DESCRIPTION = ( 'Library to create spreadsheet files compatible with ' Index: trunk/xlwt/BIFFRecords.py =================================================================== --- trunk/xlwt/BIFFRecords.py (revision 395) +++ trunk/xlwt/BIFFRecords.py (revision 398) @@ -2158,4 +2158,120 @@ hres, vres, header_margin, footer_margin, num_copies) + +class NameRecord(BiffRecord): + """ + This record is part of a Link Table. It contains the name and the token + array of an internal defined name. Token arrays of defined names + contain tokens with aberrant token classes. + Record NAME, BIFF5/BIFF7: + Offset Size Contents + 0 2 Option flags, see below + 2 1 Keyboard shortcut (only for command macro names, see below) + 3 1 Length of the name (character count, ln) + 4 2 Size of the formula data (sz) + 6 2 0 = Global name, otherwise index to EXTERNSHEET record (one-based) + 8 2 0 = Global name, otherwise index to sheet (one-based) + 10 1 Length of menu text (character count, lm) + 11 1 Length of description text (character count, ld) + 12 1 Length of help topic text (character count, lh) + 13 1 Length of status bar text (character count, ls) + 14 ln Character array of the name + 14+ln sz Formula data (RPN token array without size field, 4) + 14+ln+sz lm Character array of menu text + var. ld Character array of description text + var. lh Character array of help topic text + var. ls Character array of status bar text + + Record NAME, BIFF8: + Offset Size Contents + 0 2 Option flags, see below + 2 1 Keyboard shortcut (only for command macro names, see below) + 3 1 Length of the name (character count, ln) + 4 2 Size of the formula data (sz) + 6 2 Not used + 8 2 0 = Global name, otherwise index to sheet (one-based) + 10 1 Length of menu text (character count, lm) + 11 1 Length of description text (character count, ld) + 12 1 Length of help topic text (character count, lh) + 13 1 Length of status bar text (character count, ls) + 14 var. Name (Unicode string without length field, 3.4) + var. sz Formula data (RPN token array without size field, 4) + [var.] var. (optional, only if lm > 0) Menu text (Unicode string without length field, 3.4) + [var.] var. (optional, only if ld > 0) Description text (Unicode string without length field, 3.4) + [var.] var. (optional, only if lh > 0) Help topic text (Unicode string without length field, 3.4) + [var.] var. (optional, only if ls > 0) Status bar text (Unicode string without length field, 3.4) + """ + _REC_ID = 0x0018 + + def __init__(self, options, keyboard_shortcut, name, scope1, rpn, menu_text='', desc_text='', help_text='', status_text=''): + assert isinstance(name, basestring) + uname_len = len(name) + uname = upack1(name)[1:] + texts = [menu_text, desc_text, help_text, status_text] + body = pack('", see 3.9.1) + + """ + + def __init__(self, num_sheets): + SupBookRecord.__init__(self) + + self._rec_data = pack('= 0: + self.__worksheets.insert(index, ws) + else: + self.__worksheets.append(ws) + return ws def get_sheet(self, sheetnum): return self.__worksheets[sheetnum] + + + ################################################################## ## BIFF records generation ################################################################## @@ -405,6 +414,12 @@ def __useselfs_rec(self): return BIFFRecords.UseSelfsRecord().get() + def __names_rec(self): + name_records = '' + for i, sheet in enumerate(self.__worksheets): + name_records += sheet.get_name_records(i) + return name_records + def __boundsheets_rec(self, data_len_before, data_len_after, sheet_biff_lens): # ................................. # BOUNDSEHEET0 @@ -430,9 +445,17 @@ start += sheet_biff_len return result - def __all_links_rec(self): - result = '' - return result + def __all_links_rec(self): + supbook_records = '' + nsheets = len(self.__worksheets) + #~ supbook_records += BIFFRecords.AddInFunctionSupBookRecord(nsheets).get() + supbook_records += BIFFRecords.InternalReferenceSupBookRecord(nsheets).get() + #~ supbook_records += BIFFRecords.ExternalReferenceSupBookRecord(nsheets).get() + ######## Following will need replacing when 3D formula references patch is factored in + self.__refs = [(0, i, i) for i in xrange(nsheets)] + externsheet_record = BIFFRecords.ExternSheetRecord(self.__refs).get() + return supbook_records + externsheet_record + def __sst_rec(self): return self.__sst.get_biff_record() @@ -472,9 +495,10 @@ country = self.__country_rec() all_links = self.__all_links_rec() + names = self.__names_rec() shared_str_table = self.__sst_rec() - after = country + all_links + shared_str_table + after = country + all_links + names + shared_str_table ext_sst = self.__ext_sst_rec(0) # need fake cause we need calc stream pos eof = self.__eof_rec() @@ -489,7 +513,7 @@ bundlesheets = self.__boundsheets_rec(len(before), len(after)+len(ext_sst)+len(eof), sheet_biff_lens) - sst_stream_pos = len(before) + len(bundlesheets) + len(country) + len(all_links) + sst_stream_pos = len(before) + len(bundlesheets) + len(country) + len(all_links) + len(names) ext_sst = self.__ext_sst_rec(sst_stream_pos) return before + bundlesheets + after + ext_sst + eof + sheets Index: trunk/xlwt/Worksheet.py =================================================================== --- trunk/xlwt/Worksheet.py (revision 395) +++ trunk/xlwt/Worksheet.py (revision 398) @@ -38,6 +38,7 @@ import Bitmap import Formatting import Style +import tempfile class Worksheet(object): @@ -159,6 +160,21 @@ self.__protect = 0 self.__scen_protect = 0 self.__password = '' + + self.last_used_row = 0 + self.first_used_row = 65535 + self.last_used_col = 0 + self.first_used_col = 255 + self.row_tempfile = None + + self.__repeat = False + self.__repeat_rstart = 0 + self.__repeat_rend = 0 + self.__repeat_cstart = 0 + self.__repeat_cend = 0 + + self.__print_areas = [] + ################################################################# ## Properties, "getters", "setters" @@ -989,6 +1005,11 @@ return self.__parent def write(self, r, c, label="", style=Style.default_style): + if c < self.first_used_col: + self.first_used_col = c + if c > self.last_used_col: + self.last_used_col = c + self.row(r).write(c, label, style) if 0: # old @@ -1046,6 +1067,10 @@ return self.__cols[indx] def row(self, indx): + if (indx > self.last_used_row): + self.last_used_row = indx + if (indx < self.first_used_row): + self.first_used_row = indx if indx not in self.__rows: self.__rows[indx] = self.Row(indx, self) return self.__rows[indx] @@ -1069,6 +1094,62 @@ return result ################################################################## + ## Area hacks for print area and rows/cols to repeat + ################################################################## + + # needs sheetnum since index can change if sheets are inserted + def get_name_records(self, sheetnum): + name_records = '' + for area in self.__print_areas: + name_records += self.name_2D_area(u'\x06', sheetnum, + area[0], + area[1], + area[2], + area[3], + options=0x0020, scope=sheetnum).get() + if self.__repeat: + name_records += self.name_2D_area(u'\x07', sheetnum, + self.__repeat_rstart, + self.__repeat_rend, + self.__repeat_cstart, + self.__repeat_cend, + options=0x0020, scope=sheetnum).get() + return name_records + + # @accepts(object, basestring, int, int, int, int, int, int, int) + def name_2D_area(self, name, sheetnum, rstart, rend, cstart, cend, options=0x0000, scope=-1): + from struct import pack + assert 0 <= rstart <= rend <= 65535 + assert 0 <= cstart <= cend <= 255 + rpn = pack(' last_used_col: last_used_col = _max + ''' + return BIFFRecords.DimensionsRecord(self.first_used_row, self.last_used_row, self.first_used_col, self.last_used_col).get() - return BIFFRecords.DimensionsRecord(first_used_row, last_used_row, first_used_col, last_used_col).get() - def __window2_rec(self): options = 0 options |= (self.__show_formulas & 0x01) << 0 @@ -1209,13 +1291,31 @@ while i < len(used_rows): j = 0 while i < len(used_rows) and (j < 32): - result.append(self.__rows[used_rows[i]].get_row_biff_data()) - result.append(self.__rows[used_rows[i]].get_cells_biff_data()) + value = self.__rows.pop(used_rows[i]) + result.append(value.get_row_biff_data()) + result.append(value.get_cells_biff_data()) + j += 1 i += 1 return ''.join(result) + def __row_blocks_rec_dump(self): + # this function takes almost 99% of overall execution time + # when file is saved + # return '' + result = [] + i = 0 + used_rows = self.__rows.keys() + while i < len(used_rows): + value = self.__rows.get(used_rows[i]) + result.append(value.get_row_biff_data()) + result.append(value.get_cells_biff_data()) + i += 1 + self.__rows = {} + return ''.join(result) + + def __merged_rec(self): return BIFFRecords.MergedCellsRecord(self.__merged_ranges).get() @@ -1281,6 +1381,7 @@ result += BIFFRecords.PasswordRecord(self.__password).get() return result + def get_biff_data(self): result = '' result += self.__bof_rec() @@ -1292,6 +1393,10 @@ result += self.__dimensions_rec() result += self.__print_settings_rec() result += self.__protection_rec() + if self.row_tempfile: + self.row_tempfile.flush() + self.row_tempfile.seek(0) + result += self.row_tempfile.read() result += self.__row_blocks_rec() result += self.__merged_rec() result += self.__bitmaps_rec() @@ -1300,6 +1405,10 @@ result += self.__eof_rec() return result + + def flush_row_data(self): + if self.row_tempfile == None: + self.row_tempfile = tempfile.TemporaryFile() + self.row_tempfile.write(self.__row_blocks_rec_dump()) -