def write_cell(sheet, nodecell, engine): """Write data to a cell. * *sheet* Worksheet object. See `xlpy.xlwt.worksheet.Worksheet` * *nodecell* Cell data. * *engine* Data source engine. See `xlreport.engine` Returns a tuple of (ref_rowno, value). """ row = int(engine.get_child(nodecell, 'row')) col = int(engine.get_child(nodecell, 'col')) ori_row = int(engine.get_child(nodecell, 'ori_row')) ori_col = int(engine.get_child(nodecell, 'ori_col')) value = uni(engine.get_child(nodecell, 'value')) or '' ref_row = int(engine.get_child(nodecell, 'ref_row') or -1) filters = [] extras = engine.find(nodecell, 'Extras') if extras is not None: for extra in engine.findall(extras, 'Extra'): func = engine.get_child(extra, 'func') argn = engine.get_child(extra, 'argn') or 0 args = [engine.get_child(extra, 'arg%s' % i) or '' for i in range(int(argn))] or [] args = [x.strip() for x in args] filters.append(create_filter(func, args)) for filter in filters: value = filter.apply(sheet, row, col, value, ref_row, ori_row, ori_col) if ref_row == -1: sheet.set_value(row, col, value) value = '' return ref_row, value
def generate_report(src_doc, template_path, dest_path, split=False, engine=XmlEngine): """Generate excel file. * *src_doc*: Data source path * *template_path*: Template file path * *dest_path*: Destination file path * *split*: When set to True, sheets will be splitted into seperate workbooks and compressed into a single zip file. * *engine* Data source engine. See `xlreport.engine` Yields the worksheet's name each time a new worksheet generated. """ w = xlpy.create_copy(template_path) info = BookInfo() template = Template.parse(template_path) if split: tmpdir = tempfile.mkdtemp() # TODO: total count is available later #total_cnt = w.get_sheet_count() #digits = int(math.log10(total_cnt)) + 1 digits = 4 fmt = "%%0%sd" % digits try: for idx, node_sheet in enumerate(template.apply(src_doc, engine=engine)): nodesheet = node_sheet['Sheet'] sheet_name = engine.get_child(nodesheet, 'name') sheet_name = info.register_name(idx, sheet_name) sheet = generate_sheet(w, nodesheet, sheet_name, engine=engine) del nodesheet page_setup_default(idx, sheet) if split and sheet.is_visible(): wb = xlpy.Workbook() wb.copy_sheet_from_book(w, sheet.index, sheet.name) path = os.path.join(tmpdir, u'%s_%s.xls' % (fmt % idx, uni(sheet.name))) wb.save(path.encode('utf8')) wb = None sheet.flush_row_data() sheet = None yield sheet_name except: logger.error('error occured during excel generation') raise finally: del info del template for idx, sheet in enumerate(w.get_original_sheets()): page_setup_default(idx, sheet) w.save(dest_path) w = None if split: # split the sheets and zip all fd, tmppath = tempfile.mkstemp(suffix='.zip') rslt = zipfile.ZipFile(os.fdopen(fd, 'wb'), 'w', zipfile.ZIP_DEFLATED) for r, dirs, files in os.walk(tmpdir): for fpath in files: if isinstance(fpath, str): fpath = unicode(fpath, 'utf8') rslt.write(os.path.join(r, fpath.encode('utf8')), arcname=fpath.encode('cp932')) rslt.close() shutil.copy2(tmppath, dest_path)