Python操作Excel插入删除行的方法


Posted in Python onDecember 10, 2018

1. 前言

由于近期有任务需要,要写一个能够处理Excel的脚本,实现的功能是,在A表格上其中一列,对字符串进行分组和排序,然后根据排序好的A表格以固定格式自动填写到B表格上。

开始写脚本之前查了很多资料,最开始采用了openpyxl这个模块,用起来很顺手,使用这个对A表格其中一列进行了重新填写,但是后来发现,需要用到删除和插入空白行的操作,使用openpyxl比较困难,这个模块仅支持在表格的最后一行继续添加新行,不支持在中间插入和删除行。

在查找的过程中发现,网上流传了一些使用openpyxl进行插入删除行的操作,现整理一下。

2. 使用openpyxl

一种思路是将sheet数据转换成list,然后在list进行操作,这种方法可行,但是实际测试之后发现运行起来速度太慢了,数据1000多条,时间就已经等不起了。

# Creat insert row function group----------------------------------------------
def blankRowInsert(sheet, row_num, add_num):
  myList = Sheet2List(sheet)
  insertLine(myList, row_num, add_num, sheet.max_column)
  List2Sheet(sheet,myList)

def Sheet2List(sheet):
  # 把一个表格中的数据全部导出到一个列表
  listResult = []
  for i in range(1,sheet.max_row + 1):
    lineData = []
    for j in range(1,sheet.max_column +1):
      cell = sheet.cell(row = i, column = j)
      lineData.append(cell.value)
    listResult.append(lineData)
  return listResult

def insertLine(aList, row_num , add_num, maxColumn):
  # 对列表进行添加操作操作
  for _ in range(1,add_num + 1):
    # ['']*N是创建一个个数为N的空格列表,插入列表aList
    aList.insert(row_num, [''] * maxColumn)

def List2Sheet(sheet,list):
  # 把数据写回sheet
  for i in range(1, len(list) + 1):
    for j in range(1, len(list[0]) + 1):
      cell = sheet.cell(row=i, column=j)
      cell.value = list[i-1][j-1]
# End of insert row function group---------------------------------------------

另外一种思路是直接自己给openpyxl这个轮子补胎,添加一个新的方法,笔者没有试验,下面的代码是StackOverflow相关问题上面贴的,如果各位有兴趣可以自己尝试。

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
    )

# Use way:
# Worksheet.insert_rows = insert_rows

3. 使用xlwings

进行一些列尝试和折腾之后,笔者放弃了使用openpyxl操作Excel插入和删除行了,到网上寻觅,发现了xlwings这个轮子,说明里写有api能够调用VBA的函数,这就很炫酷了,然后翻了翻文档,决定使用这个轮子操作,现贴出来笔者写的几段代码作为使用方法示范。

3.1. 删除行: range.api.EntireRow.Delete()

# Delete origin row
temp_del = 0
if len(delete_list) > 0:
  for delete_row in delete_list:
    # Report schedule
    print("Have alerady done: " + \
        str((temp_del*100)//delete_num) + "%")
    # Delete one row
    wb_sheet.range('A'+str(delete_row-temp_del)).api.EntireRow.Delete()
    temp_del = temp_del + 1
wb.save()

上面这段代码使用了一些小技巧,delete_list储存的是原表格中,需要删除的行号,在删除过程中由于总行数也在跟着减少,所以需要把绝对行号转成相对行号进行标记删除,这个转换就是temp_del变量的使用目的。

3.2. 插入行: sheet.api.Rows(row_number).Insert()

if key_word == sheet.range('A'+str(i_row+1)).value:
  # Insert new line
  sheet.api.Rows(i_row+2).Insert()

需要注意的是,这个VBA函数是向上插入空行,并且xlwings这个轮子只能在windows和macos的系统下使用,暂时不支持Linux。不过xlwings运行速度要远超过openpyxl,而且还能直接调用VBA的函数,对于WPS和Excel都能兼容,综合来看,还是选择xlwings比较好一些。

以上这篇Python操作Excel插入删除行的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python的id()函数解密过程
Dec 25 Python
使用apidocJs快速生成在线文档的实例讲解
Feb 07 Python
python pandas 对时间序列文件处理的实例
Jun 22 Python
virtualenv 指定 python 解释器的版本方法
Oct 25 Python
python覆盖写入,追加写入的实例
Jun 26 Python
python实现关闭第三方窗口的方法
Jun 28 Python
详解pandas DataFrame的查询方法(loc,iloc,at,iat,ix的用法和区别)
Aug 02 Python
python3.7 openpyxl 删除指定一列或者一行的代码
Oct 08 Python
Python 实现顺序高斯消元法示例
Dec 09 Python
python十进制转二进制的详解
Feb 07 Python
Selenium常见异常解析及解决方案示范
Apr 10 Python
如何用python免费看美剧
Aug 11 Python
Python openpyxl 遍历所有sheet 查找特定字符串的方法
Dec 10 #Python
使用pandas实现csv/excel sheet互相转换的方法
Dec 10 #Python
python得到一个excel的全部sheet标签值方法
Dec 10 #Python
解决pandas .to_excel不覆盖已有sheet的问题
Dec 10 #Python
python模块导入的细节详解
Dec 10 #Python
pandas每次多Sheet写入文件的方法
Dec 10 #Python
Python用61行代码实现图片像素化的示例代码
Dec 10 #Python
You might like
php开发过程中关于继承的使用方法分享
2011/06/17 PHP
php中将html中的br换行符转换为文本输入中的换行符
2013/03/26 PHP
php修改上传图片尺寸的方法
2015/04/14 PHP
php使用环形链表解决约瑟夫问题完整示例
2018/08/07 PHP
js png图片(有含有透明)在IE6中为什么不透明了
2010/02/07 Javascript
javascript加号&quot;+&quot;的二义性说明
2013/03/04 Javascript
javascript获取函数名称、函数参数、对象属性名称的代码实例
2014/04/12 Javascript
使用typeof判断function是否存在于上下文
2014/08/14 Javascript
node.js中的fs.exists方法使用说明
2014/12/17 Javascript
JSONP之我见
2015/03/24 Javascript
js实现每日自动换一张图片的方法
2015/05/04 Javascript
js实现的页面加载完毕之前loading提示效果完整示例【附demo源码下载】
2016/08/02 Javascript
原生js实现网易轮播图效果
2020/04/10 Javascript
详解angularJs中自定义directive的数据交互
2017/01/13 Javascript
Vue数据监听方法watch的使用
2018/03/28 Javascript
浅谈webpack 构建性能优化策略小结
2018/06/13 Javascript
[03:02]2014DOTA2西雅图邀请赛 让队员自己告诉你DK NAVI备战情况
2014/07/08 DOTA
python操作MySQL数据库的方法分享
2012/05/29 Python
简单介绍Python中的几种数据类型
2016/01/02 Python
使用Python写一个量化股票提醒系统
2018/08/22 Python
Python3+Requests+Excel完整接口自动化测试框架的实现
2019/10/11 Python
python数据化运营的重要意义
2019/11/25 Python
Python二次规划和线性规划使用实例
2019/12/09 Python
Python实现汇率转换操作
2020/05/03 Python
[原创]赚疯了!转手立赚800+?大佬的python「抢茅台脚本」使用教程
2021/01/12 Python
Python Spyder 调出缩进对齐线的操作
2021/02/26 Python
数组越界问题
2015/10/21 面试题
什么是符号链接,什么是硬链接?符号链接与硬链接的区别是什么?
2014/01/19 面试题
新学期红领巾广播稿
2014/01/14 职场文书
留学自荐信写作方法
2014/01/27 职场文书
委托书样本
2014/04/02 职场文书
乔丹名人堂演讲稿
2014/05/24 职场文书
博士生专家推荐信
2015/03/25 职场文书
2015年科协工作总结
2015/05/19 职场文书
2016教师年度考核评语大全
2015/12/01 职场文书
Python获取江苏疫情实时数据及爬虫分析
2021/08/02 Python