我需要在xlwt

时间:2017-02-16 13:49:15

标签: python excel xlrd xlwt

默认表:

enter image description here

在我的脚本操作之后,我想得到这个 enter image description here

rb = xlrd.open_workbook('example.xls', formatting_info=True)
wb = copy(rb)
sheet = wb.get_sheet(0)
...?
wb.save('example.xls')

由于

1 个答案:

答案 0 :(得分:1)

使用openpyxl的解决方案:

def insert_rows(ws, row_idx, cnt, above=False, copy_style=True, copy_merged_columns=True, copy_data=True):
    """Inserts new (empty) rows into worksheet at specified row index.

    :param row_idx: Row index specifying where to insert new rows.
    :param cnt: Number of rows to insert.
    :param above: Set True to insert rows above specified row index.
    :param copy_style: Set True if new rows should copy style of immediately above row.
    :param copy_data: Set True if new rows should take on data or formula from immediately above row, filled with references new to rows. (changed from formulae only by Hillel)

    Usage:

    * insert_rows(2, 10, above=True, copy_style=False)

    """
    CELL_RE  = re.compile("(?P<col>\$?[A-Z]+)(?P<row>\$?\d+)")

    row_idx = row_idx - 1  if above else row_idx
    def replace(m):
        row = m.group('row')
        prefix = "$" if row.find("$") != -1 else ""
        row = int(row.replace("$", ""))
        row += cnt if row > row_idx else 0
        return m.group('col') + prefix + str(row)

    # First, we shift all cells down cnt rows...
    old_cells = set()
    old_fas = set()
    new_cells = dict()
    new_fas = dict()
    for c in ws._cells.values():

        old_coor = c.coordinate

        # Shift all references to anything below row_idx
        if c.data_type == Cell.TYPE_FORMULA:
            c.value = CELL_RE.sub(
                replace,
                c.value
            )
            # Here, we need to properly update the formula references to reflect new row indices
            if old_coor in ws.formula_attributes and 'ref' in ws.formula_attributes[old_coor]:
                ws.formula_attributes[old_coor]['ref'] = CELL_RE.sub(
                    replace,
                    ws.formula_attributes[old_coor]['ref']
                )

        # Do the magic to set up our actual shift
        if c.row > row_idx:
            old_coor = c.coordinate
            old_cells.add((c.row, c.col_idx))
            c.row += cnt
            new_cells[(c.row, c.col_idx)] = c
            if old_coor in ws.formula_attributes:
                old_fas.add(old_coor)
                fa = ws.formula_attributes[old_coor].copy()
                new_fas[c.coordinate] = fa

    for coor in old_cells:
        del ws._cells[coor]
    ws._cells.update(new_cells)

    for fa in old_fas:
        del ws.formula_attributes[fa]
    ws.formula_attributes.update(new_fas)

    # Next, we need to shift all the Row Dimensions below our new rows down by cnt...
    # CHANGED: for row in range(len(ws.row_dimensions) - 1 + cnt, row_idx + cnt, -1):
    for row in range(list(ws.row_dimensions)[-1] + cnt, row_idx + cnt, -1):
        new_rd = copy(ws.row_dimensions[row - cnt])
        new_rd.index = row
        ws.row_dimensions[row] = new_rd
        del ws.row_dimensions[row - cnt]

    # Now, create our new rows, with all the pretty cells
    # CHANGED: row_idx += 1
    new_row_idx = row_idx + 1
    for row in range(new_row_idx, new_row_idx + cnt):
        # Create a Row Dimension for our new row
        new_rd = copy(ws.row_dimensions[row-1])
        new_rd.index = row
        ws.row_dimensions[row] = new_rd

        # CHANGED: for col in range(1,ws.max_column):
        for col in range(ws.max_column):
            # CHANGED: col = get_column_letter(col)
            col = get_column_letter(col+1)
            cell = ws.cell('%s%d' % (col, row))
            cell.value = None
            source = ws.cell('%s%d' % (col, row-1))
            if copy_style:
                cell.number_format = source.number_format
                cell.font = source.font.copy()
                cell.alignment = source.alignment.copy()
                cell.border = source.border.copy()
                cell.fill = source.fill.copy()
            if copy_data:
                s_coor = source.coordinate
                cell.data_type = source.data_type
                if source.data_type == Cell.TYPE_FORMULA:
                    if s_coor in ws.formula_attributes and 'ref' not in ws.formula_attributes[s_coor]:
                        fa = ws.formula_attributes[s_coor].copy()
                        ws.formula_attributes[cell.coordinate] = fa
                    #print("Copying formula from cell %s%d to %s%d"%(col,row-1,col,row))
                    cell.value = re.sub(
                        "(\$?[A-Z]{1,3}\$?)%d" % (row-1),
                        lambda m: m.group(1) + str(row),
                        source.value
                    )
                else:
                    cell.value = source.value

    # Check for Merged Cell Ranges that need to be expanded to contain new cells
    for cr_idx, cr in enumerate(ws.merged_cell_ranges):
        ws.merged_cell_ranges[cr_idx] = CELL_RE.sub(
            replace,
            cr
        )

    # Merge columns of the new rows in the same way row above does
    if copy_merged_columns:
        for cr in ws.merged_cell_ranges:
            min_col, min_row, max_col, max_row = range_boundaries(cr)
            if max_row == min_row == row_idx:
                for row in range(new_row_idx, new_row_idx + cnt):
                    newCellRange = get_column_letter(min_col) + str(row) + ":" + get_column_letter(max_col) + str(row)
                    ws.merge_cells(newCellRange)