Example #1
0
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
Example #2
0
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)