侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

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

Python  /  管理员 发布于 7年前   237

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 listResultdef 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 rowtemp_del = 0if 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 + 1wb.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 openpyxl 遍历所有sheet 查找特定字符串的方法
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客