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采用socket模拟TCP通讯的实现方法
Nov 19 Python
Python中的True,False条件判断实例分析
Jan 12 Python
python使用datetime模块计算各种时间间隔的方法
Mar 24 Python
Python常用随机数与随机字符串方法实例
Apr 09 Python
Python六大开源框架对比
Oct 19 Python
Python实现图片转字符画的示例
Aug 22 Python
Python中文件的读取和写入操作
Apr 27 Python
Python二叉树的遍历操作示例【前序遍历,中序遍历,后序遍历,层序遍历】
Dec 24 Python
详解python破解zip文件密码的方法
Jan 13 Python
jupyter notebook插入本地图片的实现
Apr 13 Python
python中如何进行连乘计算
May 28 Python
python制作图形界面的2048游戏, 基于tkinter
Apr 06 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 array_slice函数的使用以及参数详解
2008/08/30 PHP
php版本的cron定时任务执行器使用实例
2014/08/19 PHP
php创建和删除目录函数介绍和递归删除目录函数分享
2014/11/18 PHP
PHP函数实现从一个文本字符串中提取关键字的方法
2015/07/01 PHP
thinkphp3.x自定义Action、Model及View的简单实现方法
2016/05/19 PHP
thinkphp 字母函数详解T/I/N/D/M/A/R/U
2017/04/03 PHP
Jquery实现遮罩层的方法
2015/06/08 Javascript
jQuery 中的 DOM 操作
2016/04/26 Javascript
基于jQuery实现仿微博发布框字数提示
2016/07/27 Javascript
vue实现单选和多选功能
2017/08/11 Javascript
详谈DOM简介及节点、属性、查找节点的方法
2017/11/16 Javascript
小程序图片剪裁加旋转的示例代码
2018/07/10 Javascript
js实现视图和数据双向绑定的方法分析
2020/02/05 Javascript
利用JavaScript模拟京东按键输入功能
2020/12/01 Javascript
使用Node.js和Socket.IO扩展Django的实时处理功能
2015/04/20 Python
python中关于for循环的碎碎念
2017/06/30 Python
python3学习笔记之多进程分布式小例子
2018/02/13 Python
Python 数据处理库 pandas进阶教程
2018/04/21 Python
python XlsxWriter模块创建aexcel表格的实例讲解
2018/05/03 Python
Python3获取电脑IP、主机名、Mac地址的方法示例
2019/04/11 Python
基于numpy中的expand_dims函数用法
2019/12/18 Python
python异常处理try except过程解析
2020/02/03 Python
Python matplotlib绘制图形实例(包括点,曲线,注释和箭头)
2020/04/17 Python
css3实现椭圆轨迹旋转的示例代码
2018/10/29 HTML / CSS
详解CSS3中常用的样式【基本文本和字体样式】
2020/10/20 HTML / CSS
毕业生自荐书
2014/02/02 职场文书
2014年五四青年节演讲稿范文
2014/04/22 职场文书
体育活动总结范文
2014/05/04 职场文书
个人担保书范文
2014/05/20 职场文书
反腐倡廉演讲稿
2014/05/22 职场文书
2015年小学语文工作总结
2015/05/25 职场文书
医学生自荐信范文(2016精选篇)
2016/01/28 职场文书
《蚂蚁和蝈蝈》教学反思
2016/02/22 职场文书
go 原生http web 服务跨域restful api的写法介绍
2021/04/27 Golang
Go语言编译原理之源码调试
2022/08/05 Golang
CSS中理解层叠性及权重如何分配
2022/12/24 HTML / CSS