openpyxl处理excel2007文档思路以及心得

2019-09-24 04:24 来源:未知

寻找工具

用python + openpyxl管理excel二〇〇五文书档案思路以及心得,

探求工具

分明义务之后第一步正是找个趁手的库来行事。 Python Excel上列出了xlrd、xlwt、xlutils这多少个包,但是

它们都相比较老,xlwt以致不扶助07版之后的excel
它们的文书档案不太融洽,都大概供给去读源代码,而老姐的天职比较紧,加上作者随即在晚期,未有那么些时间细读源代码
再一番查找后本身找到了openpyxl,协理07+的excel,平素有人在保卫安全,文书档案清晰易读,参照Tutorial和API文书档案十分的快就能够上手,正是它了~

安装

其一很轻巧,直接pip install openpyxl,呵呵呵~

因为自身没有须要管理图片,就不曾装pillow。

一些思索

源文件大致一个在1~2MB左右,不大,所以能够直接读入内部存款和储蓄器管理。
既然是处理excel,何况他们全体组确定都以win下办事(数据都用excel存了= =,商科的人啊……),那些剧本如故在win下做啊
以此任务完全无需自个儿对现成的公文做修改!囧……笔者假设读入、管理、再写出另三个文件就行了

学学生运动用

哦,正是展开cmd,然后用python的shell各类玩这一个模块来上手……(win下未有装ipython,囧)

做这些小本子基本上作者只供给import四个东西

from openpyxl import Workbook
from openpyxl import load_workbook

load_workbook一面之识是把文件导入到内部存款和储蓄器,Workbook是最基本的三个类,用来在内部存款和储蓄器里成立文件最后写进磁盘的。

干活

先是小编需求导入那几个文件

inwb = load_workbook(filename)

收获的正是八个workbook对象

接下来小编急需创立一个新的文件

outwb = Workbook()

接着在这几个新文件里,用create_sheet新建多少个工作表,举例

careerSheet = outwb.create_sheet(0, 'career')

就能从底部插入三个叫career的工作表(也正是说用法类似python list的insert)

接下去自身要求遍历输入文件的每一种工作表,並且依照表名做一些干活(e.g.假若表名不是数字,作者没有供给管理),openpyxl帮忙用字典同样的法子通过表名获取工作表,获取二个工作簿的表名的办法是get_sheet_names

for sheetName in inwb.get_sheet_names():
  if not sheetName.isdigit():
    continue
  sheet = inwb[sheetName]

获得专门的工作表之后,就是按列和行管理了。openpyxl会基于职业表里实际有数据的区域来分明行数和列数,获取行和列的格局是sheet.rows和sheet.columns,它们都得以像list同样用。比方,要是笔者想跳过多少少于2列的表,能够写

if len(sheet.columns) < 2:
  continue

比方笔者想博得这些职业表的前两列,能够写

colA, colB = sheet.columns[:2]

而外用columns和rows来收获那一个职业表的连串之外,还能用excel的单元格编码来猎取二个区域,举个例子

cells = sheet['A1':'B20']

有一些像excel本身的函数,能够拉出一块二维的区域~

为了便利管理,遭受二个不曾C列的工作表,小编要创建八个和A列等长的空的C列出来,那么本人得以用sheet.cell那个点子,通过传播单元格编号和增添空值来创立新列。

alen = len(colA)
for i in range(1, alen + 1):
  sheet.cell('C%s' % (i)).value = None

只顾:excel的单元格命名是从1起来的~

下面的代码也彰显出来了,获取单元格的值是用cell.value(能够是左值也足以是右值),它的品种能够是字符串、浮点数、整数、大概时间(datetime.datetime),excel文件里也会变动对应等级次序的数码。

收获每种单元格的值之后,就能够进行操作了~openpyxl会自 动将字符串用unicode编码,所以字符串都以unicode类型的。

而外逐条每种单元格用cell.value修改值以外,还足以一行行append到办事表里

sheet.append(strA, dateB, numC)

 最终,等新的文本写好,直接用workbook.save保存就行

outwb.save("test.xlsx")

其一会覆盖当前已有的文件,乃至你在此之前读取到内部存款和储蓄器的足够文件。

有的要留意的地方
一旦要在遍历一列的各样单元格的时候取安妥前单元格的在那几个column对象里的下标

for idx, cell in enumerate(colA):
  # do something...

为了堤防获取的数额两端有看不见的空格(excel文件里很广泛的坑),记得strip()

要是职业表里的单元格未有数量,openpyxl会让它的值为None,所以只要要依附单元格的值做拍卖,不能够事先假定它的档次,最佳用

if not cell.value
  continue

等等的语句来先行判定

一经要拍卖的excel文件里有许多noise,比如当您预期一个单元格是时间的时候,某些表的多少或者是字符串,这时候能够用

if isinstance(cell.value, unicode):
  break

等等的言语管理。

win下的cmd仿佛不太好设定用utf-8的code page,借使是简体中文的话能够用936(GBK),print的时候会活动从unicode转产生GBK输出到巅峰。  

有的助手管理普通话难点的小函数
自身管理的表有点超越GBK范围的字符,当自己索要把一些新闻print出来监察和控制管理速度的时候特别麻烦,还好它们都是可以无视的,笔者一向用空格替换再print也行,所以加上有的本人本来就要替换掉的分隔符,作者得以:

# annoying seperators
dot = u'u00b7'
dash = u'u2014'
emph = u'u2022'
dot2 = u'u2027'

seps = (u'.', dot, dash, emph, dot2)

def get_clean_ch_string(chstring):
  """Remove annoying seperators from the Chinese string.

  Usage:
    cleanstring = get_clean_ch_string(chstring)
  """
  cleanstring = chstring
  for sep in seps:
    cleanstring = cleanstring.replace(sep, u' ')
  return cleanstring

其它作者还大概有八个急需,是把土耳其共和国(Türkiye Cumhuriyeti)语名[空格]华语名分成乌克兰语姓、加泰罗尼亚语名、中文姓、汉语名。

第一自身急需能把罗马尼亚语和国文分割开,作者的点子是用正则相配,依据布满中韩文字符在unicode的限制来套。相称韩文和华语的正则pattern如下:

# regex pattern matching all ascii characters
asciiPattern = ur'[%s]+' % ''.join(chr(i) for i in range(32, 127))
# regex pattern matching all common Chinese characters and seporators
chinesePattern = ur'[u4e00-u9fff. %s]+' % (''.join(seps))

葡萄牙语就用ASCII可打字与印刷字符的界定庖代,常见中文字符的限制是u4e00-u9fff,那些seps是前方提到过的超越GBK范围的有的字符。 除了简便易行的细分,作者还要求管理唯有中文名从未克罗地亚共和国语名、独有克罗地亚语名未有粤语名等状态,判定逻辑如下:

def split_name(name):
  """Split [English name, Chinese name].

    If one of them is missing, None will be returned instead.
  Usage:
    engName, chName = split_name(name)
  """
  matches = re.match('(%s) (%s)' % (asciiPattern, chinesePattern), name)
  if matches: # English name + Chinese name
    return matches.group(1).strip(), matches.group(2).strip()
  else:
    matches = re.findall('(%s)' % (chinesePattern), name)
    matches = ''.join(matches).strip()
    if matches: # Chinese name only
      return None, matches
    else: # English name only
      matches = re.findall('(%s)' % (asciiPattern), name)
      return ''.join(matches).strip(), None

收获了普通话名之后,小编急需分割成姓和名,因为任务要求无需把姓名分割得很显眼,作者就遵照广泛的华语名姓名分割格局来分——八个字or四个字的首先个字是姓,多少个字的前四个字是姓,名字带分隔符的(少数民族名字)分隔符前是姓(这里运用了前边的get_clean_ch_string函数来移除分隔符),名字再长一些又不带分割符的,假使任何字符串都以名字。(注意阿拉伯语的first name 指的是名,last name指的是姓,2333)

def split_ch_name(chName):
  """Split the Chinese name into first name and last name.

    * If the name is XY or XYZ, X will be returned as the last name.
    * If the name is WXYZ, WX will be returned as the last name.
    * If the name is ...WXYZ, the whole name will be returned
     as the last name.
    * If the name is ..ABC * XYZ..., the part before the seperator
     will be returned as the last name.
  Usage:
    chFirstName, chLastName = split_ch_name(chName)
  """
  if len(chName) < 4: # XY or XYZ
    chLastName = chName[0]
    chFirstName = chName[1:]
  elif len(chName) == 4: # WXYZ
    chLastName = chName[:2]
    chFirstName = chName[2:]
  else: # longer
    cleanName = get_clean_ch_string(chName)
    nameParts = cleanName.split()
    print u' '.join(nameParts)
    if len(nameParts) < 2: # ...WXYZ
      return None, nameParts[0]
    chLastName, chFirstName = nameParts[:2] # ..ABC * XYZ...
  return chFirstName, chLastName

细分英语名就很简短了,空格分开,第一有的是名,第二有的是姓,别的意况偶然不管就行。

分明任务之后第一步正是找个趁手的库来办事。 Python Excel上列出了xlrd、xlwt、xlutils那多少个包,可是

它们都相比老,xlwt乃至不援救07版之后的excel
它们的文书档案不太对劲儿,都恐怕需求去读源代码,而老姐的职责相比较紧,加上小编立刻在最后阶段,未有那个时刻细读源代码
再一番物色后自个儿找到了openpyxl,辅助07+的excel,一直有人在维护,文书档案清晰易读,参照Tutorial和API文书档案非常的慢就能够上手,就是它了~

+ openpyxl管理excel二〇〇五文书档案思路以及心得, 搜索工具 分明任务之后第一步正是找个趁手的库来办事。 Python Excel上列出了xlrd、xlwt、xl...

安装

其一很轻便,直接pip install openpyxl,呵呵呵~

因为本人无需处理图片,就平昔不装pillow。

局部思量

源文件差十分少一个在1~2MB左右,极小,所以能够直接读入内部存款和储蓄器处理。
既然是管理excel,并且他们任何组明确都以win下办事(数据都用excel存了= =,商科的人呀……),这么些剧本依然在win下做吧
其一任务完全无需自身对现存的公文做修改!囧……作者只要读入、管理、再写出另二个文件就行了

上学生运动用

哦,正是展开cmd,然后用python的shell种种玩那一个模块来上手……(win下并未有装ipython,囧)

做那些小本子基本上自个儿只供给import四个东西

from openpyxl import Workbook
from openpyxl import load_workbook

load_workbook看名就能够猜到其意义是把公文导入到内部存款和储蓄器,Workbook是最基本的二个类,用来在内部存款和储蓄器里创设文件最终写进磁盘的。

干活

率先小编需求导入这个文件

inwb = load_workbook(filename)

获得的便是二个workbook对象

接下来自个儿索要创制三个新的公文

outwb = Workbook()

进而在那些新文件里,用create_sheet新建多少个职业表,比方

careerSheet = outwb.create_sheet(0, 'career')

就能够从头顶插入二个叫career的事业表(也正是说用法类似python list的insert)

接下去本人急需遍历输入文件的各样职业表,並且依据表名做一些办事(e.g.假设表名不是数字,小编不要求管理),openpyxl支持用字典同样的办法通过表名获取工作表,获取三个工作簿的表名的点子是get_sheet_names

for sheetName in inwb.get_sheet_names():
  if not sheetName.isdigit():
    continue
  sheet = inwb[sheetName]

获得专业表之后,便是按列和行管理了。openpyxl会依照专业表里实际有多少的区域来规定行数和列数,获取行和列的方法是sheet.rows和sheet.columns,它们都能够像list一样用。比方,即使本人想跳过数额少于2列的表,能够写

if len(sheet.columns) < 2:
  continue

借使自个儿想猎取那些工作表的前两列,可以写

colA, colB = sheet.columns[:2]

除此之外用columns和rows来获得那些职业表的行列之外,仍是能够用excel的单元格编码来获得贰个区域,举例

cells = sheet['A1':'B20']

有一点像excel本人的函数,能够拉出一块二维的区域~

为了便于管理,蒙受一个从未C列的工作表,作者要创立一个和A列等长的空的C列出来,那么本身能够用sheet.cell这么些法子,通过传播单元格编号和拉长空值来成立新列。

alen = len(colA)
for i in range(1, alen + 1):
  sheet.cell('C%s' % (i)).value = None

留心:excel的单元格命名是从1起来的~

地点的代码也显得出来了,获取单元格的值是用cell.value(可以是左值也得以是右值),它的花色能够是字符串、浮点数、整数、大概时间(datetime.datetime),excel文件里也会扭转对应项目标数额。

取得各个单元格的值之后,就足以开展操作了~openpyxl会自 动将字符串用unicode编码,所以字符串都以unicode类型的。

除外逐条各种单元格用cell.value修改值以外,还是能一行行append到工作表里

sheet.append(strA, dateB, numC)

最后,等新的公文写好,直接用workbook.save保存就行

outwb.save("test.xlsx")

以此会覆盖当前已部分文件,以致你前边读取到内部存款和储蓄器的老大文件。

局地要专心的地点
比方要在遍历一列的每一种单元格的时候获得当前单元格的在那个column对象里的下标

for idx, cell in enumerate(colA):
  # do something...

为了堤防获取的多少两端有看不见的空格(excel文件里很广泛的坑),记得strip()

假诺事业表里的单元格未有数据,openpyxl会让它的值为None,所以假如要依照单元格的值做管理,不能够事先假定它的种类,最佳用

if not cell.value
  continue

等等的语句来先行决断

一旦要拍卖的excel文件里有多数noise,比方当您预期四个单元格是光阴的时候,某些表的数据也许是字符串,那时候能够用

if isinstance(cell.value, unicode):
  break

等等的说话管理。

win下的cmd就像是不太好设定用utf-8的code page,假诺是简体普通话的话能够用936(GBK),print的时候会自动从unicode调换来GBK输出到极限。

一部分声援处理普通话难题的小函数
自己管理的表有点高于GBK范围的字符,当自个儿索要把有个别新闻print出来监察和控制管理速度的时候非常麻烦,辛亏它们都是能够无视的,作者一向用空格替换再print也行,所以加上部分本身自然就要替换掉的分隔符,笔者得以:

# annoying seperators
dot = u'u00b7'
dash = u'u2014'
emph = u'u2022'
dot2 = u'u2027'

seps = (u'.', dot, dash, emph, dot2)

def get_clean_ch_string(chstring):
  """Remove annoying seperators from the Chinese string.

  Usage:
    cleanstring = get_clean_ch_string(chstring)
  """
  cleanstring = chstring
  for sep in seps:
    cleanstring = cleanstring.replace(sep, u' ')
  return cleanstring

除此以外笔者还也可以有三个必要,是把葡萄牙语名[空格]粤语名分成拉脱维亚语姓、塞尔维亚(Serbia)语名、中文姓、中文名。

首先本身索要能把意大利共和国语和中文分割开,笔者的主意是用正则相称,依据布满中印度语印尼语字符在unicode的界定来套。相配马耳他语和中文的正则pattern如下:

# regex pattern matching all ascii characters
asciiPattern = ur'[%s]+' % ''.join(chr(i) for i in range(32, 127))
# regex pattern matching all common Chinese characters and seporators
chinesePattern = ur'[u4e00-u9fff. %s]+' % (''.join(seps))

意国语就用ASCII可打字与印刷字符的界定替代,常见普通话字符的限制是u4e00-u9fff,那一个seps是前方提到过的压倒GBK范围的某些字符。 除了简短的撤销合并,作者还必要管理唯有汉语名未有匈牙利(Magyarország)语名、独有俄语名未有中文名等情况,剖断逻辑如下:

def split_name(name):
  """Split [English name, Chinese name].

    If one of them is missing, None will be returned instead.
  Usage:
    engName, chName = split_name(name)
  """
  matches = re.match('(%s) (%s)' % (asciiPattern, chinesePattern), name)
  if matches: # English name + Chinese name
    return matches.group(1).strip(), matches.group(2).strip()
  else:
    matches = re.findall('(%s)' % (chinesePattern), name)
    matches = ''.join(matches).strip()
    if matches: # Chinese name only
      return None, matches
    else: # English name only
      matches = re.findall('(%s)' % (asciiPattern), name)
      return ''.join(matches).strip(), None

得到了中文名之后,小编急需分割成姓和名,因为任务供给不要求把姓名分割得很分明,笔者就根据分布的华语名姓名分割格局来分——多少个字or多少个字的首先个字是姓,多少个字的前多个字是姓,名字带分隔符的(少数民族名字)分隔符前是姓(这里运用了后面包车型大巴get_clean_ch_string函数来移除分隔符),名字再长一些又不带分割符的,若是任何字符串都以名字。(注意土耳其共和国(Türkiye Cumhuriyeti)语的first name 指的是名,last name指的是姓,2333)

def split_ch_name(chName):
  """Split the Chinese name into first name and last name.

    * If the name is XY or XYZ, X will be returned as the last name.
    * If the name is WXYZ, WX will be returned as the last name.
    * If the name is ...WXYZ, the whole name will be returned
     as the last name.
    * If the name is ..ABC * XYZ..., the part before the seperator
     will be returned as the last name.
  Usage:
    chFirstName, chLastName = split_ch_name(chName)
  """
  if len(chName) < 4: # XY or XYZ
    chLastName = chName[0]
    chFirstName = chName[1:]
  elif len(chName) == 4: # WXYZ
    chLastName = chName[:2]
    chFirstName = chName[2:]
  else: # longer
    cleanName = get_clean_ch_string(chName)
    nameParts = cleanName.split()
    print u' '.join(nameParts)
    if len(nameParts) < 2: # ...WXYZ
      return None, nameParts[0]
    chLastName, chFirstName = nameParts[:2] # ..ABC * XYZ...
  return chFirstName, chLastName

细分日文名就非常的粗略了,空格分开,第一有的是名,首盘部是姓,其余情状有的时候不管就行。

TAG标签:
版权声明:本文由990888藏宝阁发布于网络应用,转载请注明出处:openpyxl处理excel2007文档思路以及心得