【问题标题】:Insert row into Excel spreadsheet using openpyxl in Python在 Python 中使用 openpyxl 将行插入 Excel 电子表格
【发布时间】:2022-02-20 23:23:42
【问题描述】:

我正在寻找使用 openpyxl 将行插入电子表格的最佳方法。

实际上,我有一个电子表格 (Excel 2007),它有一个标题行,后面跟着(最多)几千行数据。我希望将该行作为实际数据的第一行插入,所以在标题之后。我的理解是append函数适合将内容添加到文件的末尾。

阅读 openpyxl 和 xlrd(和 xlwt)的文档后,除了手动循环内容并插入新工作表(在插入所需的行之后)之外,我找不到任何明确的方法来做到这一点。

鉴于我迄今为止对 Python 的有限经验,我试图了解这是否确实是最好的选择(最 Python 的!),如果是这样,有人可以提供一个明确的例子。具体来说,我可以使用 openpyxl 读写行还是必须访问单元格?另外我可以(覆盖)写入相同的文件(名称)吗?

【问题讨论】:

  • 您可以选择导出为 CSV 吗?这是一次性的过程吗?还是您需要重复执行此操作?
  • @Srini 不,我们被这种格式卡住了,这是一个可重复的过程:文件实际上通过 FTP 传输到另一台服务器并由 SSIS 包处理。

标签: python excel xlrd xlwt openpyxl


【解决方案1】:

== 根据此处的反馈更新到功能齐全的版本:groups.google.com/forum/#!topic/openpyxl-users/wHGecdQg3Iw。 ==

正如其他人所指出的,openpyxl 不提供此功能,但我已将Worksheet 类扩展如下以实现插入行。希望这对其他人有用。

def insert_rows(self, row_idx, cnt, above=False, copy_style=True, fill_formulae=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 fill_formulae: Set True if new rows should take on formula from immediately above row, filled with references new to rows.

    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 self._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 self.formula_attributes and 'ref' in self.formula_attributes[old_coor]:
                self.formula_attributes[old_coor]['ref'] = CELL_RE.sub(
                    replace,
                    self.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 self.formula_attributes:
                old_fas.add(old_coor)
                fa = self.formula_attributes[old_coor].copy()
                new_fas[c.coordinate] = fa

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

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

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

    # Now, create our new rows, with all the pretty cells
    row_idx += 1
    for row in range(row_idx,row_idx+cnt):
        # Create a Row Dimension for our new row
        new_rd = copy.copy(self.row_dimensions[row-1])
        new_rd.index = row
        self.row_dimensions[row] = new_rd
        for col in range(1,self.max_column):
            col = get_column_letter(col)
            cell = self.cell('%s%d'%(col,row))
            cell.value = None
            source = self.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 fill_formulae and source.data_type == Cell.TYPE_FORMULA:
                s_coor = source.coordinate
                if s_coor in self.formula_attributes and 'ref' not in self.formula_attributes[s_coor]:
                    fa = self.formula_attributes[s_coor].copy()
                    self.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
                )   
                cell.data_type = Cell.TYPE_FORMULA

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

Worksheet.insert_rows = insert_rows

【讨论】:

  • 复制听起来有点矫枉过正。您可能想尝试类似我在邮件列表中提出的插入列 groups.google.com/forum/#!topic/openpyxl-users/wHGecdQg3Iw 的建议。它未经测试且特定于 2.2,因为它依赖于内部结构,但它提供了一般的推动力。
  • 我同意修改坐标数据是理想的,但这是在没有研究内部情况的情况下完成的。不知道为什么团队不会只添加此功能,因为它是 Excel 中经常使用的功能。
  • 没有人提交相关代码。 openpyxl 是开源的,没有团队。
  • Dallas:使用频率不会影响实现的难易程度。作为@CharlieClark,没有“团队”(他应该知道!)。这是一个基于 phpexcel 的开源项目。随着该项目的不断成熟,已对单元格/坐标系进行了重大更改。请求的功能需要这些更改,否则解决方案(如我上面的)充其量是不可靠的,并且不适合主要版本。给它时间(或者更好,贡献!)来实现功能。
  • 请在存储库中查看我的 Snippit。我已经进一步实施了......我会说非常接近完全。 ;^)
【解决方案2】:

添加适用于openpyxl 的最新版本 v2.5+ 的答案:

现在有insert_rows() 和insert_cols()。

insert_rows(idx, amount=1)

在 row==idx 之前插入一行或多行

【讨论】:

  • 遗憾的是它不支持合并单元格(它们保持固定在行位置)
【解决方案3】:

用我现在用来达到预期结果的代码来回答这个问题。请注意,我在位置 1 处手动插入行,但这应该很容易根据特定需求进行调整。您还可以轻松地对其进行调整以插入多行,然后简单地从相关位置开始填充其余数据。

另外,请注意,由于下游依赖关系,我们手动指定“Sheet1”中的数据,数据被复制到插入工作簿开头的新工作表,同时将原始工作表重命名为“Sheet1” .5'。

编辑:我还(稍后)添加了对 format_code 的更改,以解决此处默认复制操作删除所有格式的问题:new_cell.style.number_format.format_code = 'mm/dd/yyyy'。我找不到任何可以设置的文档,这更像是一个反复试验的案例!

最后,不要忘记这个例子是在原来的基础上保存。您可以更改适用的保存路径以避免这种情况。

    import openpyxl

    wb = openpyxl.load_workbook(file)
    old_sheet = wb.get_sheet_by_name('Sheet1')
    old_sheet.title = 'Sheet1.5'
    max_row = old_sheet.get_highest_row()
    max_col = old_sheet.get_highest_column()
    wb.create_sheet(0, 'Sheet1')

    new_sheet = wb.get_sheet_by_name('Sheet1')

    # Do the header.
    for col_num in range(0, max_col):
        new_sheet.cell(row=0, column=col_num).value = old_sheet.cell(row=0, column=col_num).value

    # The row to be inserted. We're manually populating each cell.
    new_sheet.cell(row=1, column=0).value = 'DUMMY'
    new_sheet.cell(row=1, column=1).value = 'DUMMY'

    # Now do the rest of it. Note the row offset.
    for row_num in range(1, max_row):
        for col_num in range (0, max_col):
            new_sheet.cell(row = (row_num + 1), column = col_num).value = old_sheet.cell(row = row_num, column = col_num).value

    wb.save(file)

【讨论】:

  • 这会按预期操作文件,尽管我觉得我应该补充一点,我们现在决定改为实现 CSV 导出。这是因为 openpyxl 库的编码问题与此问题无关,但我觉得我应该提一下!
【解决方案4】:

Openpyxl 工作表在执行行或列级别操作时功能有限。工作表与行/列相关的唯一属性是属性row_dimensions 和column_dimensions,它们分别为每一行和每一列存储“RowDimensions”和“ColumnDimensions”对象。这些字典也用于get_highest_row()和get_highest_column()等函数中。

其他一切都在单元格级别上运行,在字典_cells 中跟踪 Cell 对象(以及在字典 _styles 中跟踪它们的样式)。大多数看起来像是在行或列级别上执行任何操作的函数实际上是在一系列单元格上运行的(例如前面提到的append())。

最简单的做法就是按照您的建议:创建一个新工作表,附加标题行,附加新数据行,附加旧数据行,删除旧工作表,然后将新工作表重命名为旧工作表.这种方法可能会出现的问题是行/列维度属性和单元格样式的丢失,除非您也专门复制它们。

或者,您可以创建自己的插入行或列的函数。

我有大量非常简单的工作表,我需要从中删除列。由于您要求提供明确的示例,因此我将提供我快速拼凑的功能:

from openpyxl.cell import get_column_letter

def ws_delete_column(sheet, del_column):

    for row_num in range(1, sheet.get_highest_row()+1):
        for col_num in range(del_column, sheet.get_highest_column()+1):

            coordinate = '%s%s' % (get_column_letter(col_num),
                                   row_num)
            adj_coordinate = '%s%s' % (get_column_letter(col_num + 1),
                                       row_num)

            # Handle Styles.
            # This is important to do if you have any differing
            # 'types' of data being stored, as you may otherwise get
            # an output Worksheet that's got improperly formatted cells.
            # Or worse, an error gets thrown because you tried to copy
            # a string value into a cell that's styled as a date.

            if adj_coordinate in sheet._styles:
                sheet._styles[coordinate] = sheet._styles[adj_coordinate]
                sheet._styles.pop(adj_coordinate, None)
            else:
                sheet._styles.pop(coordinate, None)

            if adj_coordinate in sheet._cells:
                sheet._cells[coordinate] = sheet._cells[adj_coordinate]
                sheet._cells[coordinate].column = get_column_letter(col_num)
                sheet._cells[coordinate].row = row_num
                sheet._cells[coordinate].coordinate = coordinate

                sheet._cells.pop(adj_coordinate, None)
            else:
                sheet._cells.pop(coordinate, None)

        # sheet.garbage_collect()

我将我正在使用的工作表以及我想要删除的列号传递给它,然后它就消失了。我知道这不是您想要的,但我希望这些信息对您有所帮助!

编辑:注意到有人给了另一个投票,并认为我应该更新它。 Openpyxl 中的坐标系统在过去几年的某个时间经历了一些变化,为_cell 中的项目引入了coordinate 属性。这也需要编辑,否则行将留空(而不是删除),Excel 将抛出有关文件问题的错误。这适用于 Openpyxl 2.2.3(未经更高版本测试)

【讨论】:

    【解决方案5】:

    从 openpyxl 1.5 开始,您现在可以使用 .insert_rows(idx, row_qty)

    from openpyxl import load_workbook
    wb = load_workbook('excel_template.xlsx')
    ws = wb.active
    ws.insert_rows(14, 10)
    

    它不会像您在 Excel 中手动执行此操作那样获取 idx 行的格式。之后您将应用正确的格式,即单元格颜色。

    【讨论】:

      【解决方案6】:

      在 Python 中使用 openpyxl 将行插入 Excel 电子表格

      下面的代码可以帮助你:-

      import openpyxl
      
      file = "xyz.xlsx"
      #loading XL sheet bassed on file name provided by user
      book = openpyxl.load_workbook(file)
      #opening sheet whose index no is 0
      sheet = book.worksheets[0]
      
      #insert_rows(idx, amount=1) Insert row or rows before row==idx, amount will be no of 
      #rows you want to add and it's optional
      sheet.insert_rows(13)
      

      对于插入列,openpyxl 也有类似的功能,即insert_cols(idx, amount=1)

      【讨论】:

        【解决方案7】:

        我已经编写了一个函数,它可以使用 openpyxl 在电子表格或整个 2D 表格中的任意位置插入整行。

        函数的每一行都有注释说明,但如果您只想插入一行,只需使您的行等于 [row]。即如果 row = [1,2,3,4,5] 然后将输入设置为 [[1,2,3,4,5]]。如果您希望将此行插入电子表格的第一行 (A1),则 Start = [1,1]。

        您确实可以覆盖文件名,如底部的示例所示。

        def InputList(Start, List): #This function is to input an array/list from a input start point; len(Start) must equal 2, where Start = [1,1] is cell 1A. List must be a two dimensional array; if you wish to input a single row then this can be done where len(List) == 1, e.g. List = [[1,2,3,4]]
            x = 0 #Sets up a veriable to go through List columns
            y = 0 #Sets up a veriable to go through List rows
            l = 0 #Sets up a veriable to count addional columns against Start[1] to allow for column reset on each new row
            for row in List: #For every row in List
                l = 0 #Set additonal columns to zero
                for cell in row: #For every cell in row
                    ws.cell(row=Start[0], column=Start[1]).value = List[y][x] #Set value for current cell
                    x = x + 1 #Move to next data input (List) column
                    Start[1] = Start[1] + 1 #Move to next Excel column
                    l = l + 1 #Count addional row length
                y = y + 1 #Move to next Excel row
                Start[0] = Start[0] + 1 #Move to next Excel row
                x = 0 #Move back to first column of input data (ready for next row)
                Start[1] = Start[1] - l #Reset Excel column back to orignal start column, ready to write next row
        

        在第 7 行开头插入单行的示例:

        from openpyxl import load_workbook
        wb = load_workbook('New3.xlsx')
        ws = wb.active
        
        def InputList(Start, List): #This function is to input an array/list from a input start point; len(Start) must equal 2, where Start = [1,1] is cell 1A. List must be a two dimensional array; if you wish to input a single row then this can be done where len(List) == 1, e.g. List = [[1,2,3,4]]
            x = 0 #Sets up a veriable to go through List columns
            y = 0 #Sets up a veriable to go through List rows
            l = 0 #Sets up a veriable to count addional columns against Start[1] to allow for column reset on each new row
            for row in List: #For every row in List
                l = 0 #Set additonal columns to zero
                for cell in row: #For every cell in row
                    ws.cell(row=Start[0], column=Start[1]).value = List[y][x] #Set value for current cell
                    x = x + 1 #Move to next data input (List) column
                    Start[1] = Start[1] + 1 #Move to next Excel column
                    l = l + 1 #Count addional row length
                y = y + 1 #Move to next Excel row
                Start[0] = Start[0] + 1 #Move to next Excel row
                x = 0 #Move back to first column of input data (ready for next row)
                Start[1] = Start[1] - l #Reset Excel column back to orignal start column, ready to write next row
        
        test = [[1,2,3,4]]
        InputList([7,1], test)
        
        wb.save('New3.xlsx')
        

        【讨论】:

          【解决方案8】:

          我采用了达拉斯解决方案并添加了对合并单元格的支持:

              def insert_rows(self, row_idx, cnt, above=False, copy_style=True, fill_formulae=True):
                  skip_list = []
                  try:
                      idx = row_idx - 1 if above else row_idx
                      for (new, old) in zip(range(self.max_row+cnt,idx+cnt,-1),range(self.max_row,idx,-1)):
                          for c_idx in range(1,self.max_column):
                            col = self.cell(row=1, column=c_idx).column #get_column_letter(c_idx)
                            print("Copying %s%d to %s%d."%(col,old,col,new))
                            source = self["%s%d"%(col,old)]
                            target = self["%s%d"%(col,new)]
                            if source.coordinate in skip_list:
                                continue
          
                            if source.coordinate in self.merged_cells:
                                # This is a merged cell
                                for _range in self.merged_cell_ranges:
                                    merged_cells_list = [x for x in cells_from_range(_range)][0]
                                    if source.coordinate in merged_cells_list:
                                        skip_list = merged_cells_list
                                        self.unmerge_cells(_range)
                                        new_range = re.sub(str(old),str(new),_range)
                                        self.merge_cells(new_range)
                                        break
          
                            if source.data_type == Cell.TYPE_FORMULA:
                              target.value = re.sub(
                                "(\$?[A-Z]{1,3})%d"%(old),
                                lambda m: m.group(1) + str(new),
                                source.value
                              )
                            else:
                              target.value = source.value
                            target.number_format = source.number_format
                            target.font   = source.font.copy()
                            target.alignment = source.alignment.copy()
                            target.border = source.border.copy()
                            target.fill   = source.fill.copy()
                      idx = idx + 1
                      for row in range(idx,idx+cnt):
                          for c_idx in range(1,self.max_column):
                            col = self.cell(row=1, column=c_idx).column #get_column_letter(c_idx)
                            #print("Clearing value in cell %s%d"%(col,row))
                            cell = self["%s%d"%(col,row)]
                            cell.value = None
                            source = self["%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 fill_formulae and source.data_type == Cell.TYPE_FORMULA:
                              #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
                              )
          

          【讨论】:

          【解决方案9】:

          编辑了 Nick 的解决方案,此版本采用起始行、要插入的行数和文件名,并插入必要数量的空白行。

          #! python 3
          
          import openpyxl, sys
          
          my_start = int(sys.argv[1])
          my_rows = int(sys.argv[2])
          str_wb = str(sys.argv[3])
          
          wb = openpyxl.load_workbook(str_wb)
          old_sheet = wb.get_sheet_by_name('Sheet')
          mcol = old_sheet.max_column
          mrow = old_sheet.max_row
          old_sheet.title = 'Sheet1.5'
          wb.create_sheet(index=0, title='Sheet')
          
          new_sheet = wb.get_sheet_by_name('Sheet')
          
          for row_num in range(1, my_start):
              for col_num in range(1, mcol + 1):
                  new_sheet.cell(row = row_num, column = col_num).value = old_sheet.cell(row = row_num, column = col_num).value
          
          for row_num in range(my_start + my_rows, mrow + my_rows):
              for col_num in range(1, mcol + 1):
                  new_sheet.cell(row = (row_num + my_rows), column = col_num).value = old_sheet.cell(row = row_num, column = col_num).value
          
          wb.save(str_wb)
          

          【讨论】:

            【解决方案10】:

            这对我有用:

                openpyxl.worksheet.worksheet.Worksheet.insert_rows(wbs,idx=row,amount=2)
            

            在 row==idx 之前插入 2 行

            见:http://openpyxl.readthedocs.io/en/stable/api/openpyxl.worksheet.worksheet.html

            【讨论】:

              【解决方案11】:

              我已经成功地使用了Dalas's 答案,尽管对 openpyxl 3.0.9 做了一些修改。我在这里为其他想知道如何在 2022 年做到这一点的人发布代码。

              区别在于:

              • 添加导入
              • 将Cell.TYPE_FORMULA 更改为TYPE_FORMULA
              • 在需要的地方使用str() 或int() 添加类型转换

              我是 Python 新手,因此请随意提出任何更改建议,但这就是我让它发挥作用的方式。

              import copy
              import re
              from openpyxl.utils import get_column_letter
              from openpyxl.cell.cell import TYPE_FORMULA
              
              def insert_rows(self, row_idx, cnt, above=False, copy_style=True, 
                  fill_formulae=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 fill_formulae: Set True if new rows should take on formula from immediately above row, filled with references new to rows.
              
              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 self._cells.values():
              
                  old_coor = c.coordinate
              
                  # Shift all references to anything below row_idx
                  if c.data_type == 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 self.formula_attributes and 'ref' in self.formula_attributes[old_coor]:
                          self.formula_attributes[old_coor]['ref'] = CELL_RE.sub(
                              replace,
                              self.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.column))
                      c.row += cnt
                      new_cells[(c.row,c.column)] = c
                      if old_coor in self.formula_attributes:
                          old_fas.add(old_coor)
                          fa = self.formula_attributes[old_coor].copy()
                          new_fas[c.coordinate] = fa
              
              for coor in old_cells:
                  del self._cells[coor]
              self._cells.update(new_cells)
              
              for fa in old_fas:
                  del self.formula_attributes[fa]
              self.formula_attributes.update(new_fas)
              
              # Next, we need to shift all the Row Dimensions below our new rows down by cnt...
              for row in range(len(self.row_dimensions)-1+cnt,row_idx+cnt,-1):
                  new_rd = copy.copy(self.row_dimensions[row-cnt])
                  new_rd.index = row
                  self.row_dimensions[row] = new_rd
                  del self.row_dimensions[row-cnt]
              
              # Now, create our new rows, with all the pretty cells
              row_idx += 1
              for row in range(row_idx,row_idx+cnt):
                  # Create a Row Dimension for our new row
                  new_rd = copy.copy(self.row_dimensions[row-1])
                  new_rd.index = row
                  self.row_dimensions[row] = new_rd
                  for col in range(1,self.max_column):
                      col = get_column_letter(col)
                      cell = self[str(col)+str(row)]
                      cell.value = None
                      source = self[str(col)+str(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 fill_formulae and source.data_type == TYPE_FORMULA:
                          s_coor = source.coordinate
                          if s_coor in self.formula_attributes and 'ref' not in self.formula_attributes[s_coor]:
                              fa = self.formula_attributes[s_coor].copy()
                              self.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
                          )   
                          cell.data_type = TYPE_FORMULA
              
              # Check for Merged Cell Ranges that need to be expanded to contain new cells
              for cr_idx, cr in enumerate(self.merged_cells.ranges):
                  self.merged_cells.ranges[cr_idx] = CELL_RE.sub(
                      replace,
                      str(cr)
                  )
              

              【讨论】:

                【解决方案12】:

                不幸的是,没有更好的方法来读取文件,并使用像 xlwt 这样的库来写出一个新的 excel 文件(在顶部插入新行)。 Excel 不像您可以读取和追加的数据库那样工作。不幸的是,您只需要读入信息并在内存中进行操作,然后写出本质上是一个新文件。

                【讨论】:

                  猜你喜欢
                  • 2018-12-03
                  • 1970-01-01
                  • 1970-01-01
                  • 2017-11-15
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多