鱼C论坛

 找回密码
 立即注册
查看: 1617|回复: 4

[作品展示] 用openpyxl和docx写一个简单的数据比对程序,提高工作准确率

[复制链接]
发表于 2020-4-2 10:33:20 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 allearn_Python 于 2020-4-2 10:30 编辑

工作原因需要经常核对word中一些数据是否准确。有时候工作量一大很容易出现遗漏。学习完 python操作excel后,发现可以利用openpyxl 和 docx 来帮助自己核对word中的内容,于是就写了一个很简单的小程序,基本实现了自动提取数据,自动分类比对,错误提示的功能。

思路是:
1. 从excle中读取需要的数据,编写了独立程序去实现。
2. 从word中读取需要对比的数据,编写独立程序。
3. 按类别分类对比。

希望得到大家指点

另外我想对比的数据每一个都有 “型号”,“公司”,“证书号”等若干信息,我就把源数据和待对比数据分别封装成一个独立的类对象,再把这些类对象储存到一个列表中,然后去依次对比。但感觉这样不是很方便,请问有什么更好的办法吗?

效果GIF如下图:
xiaopiqiu1.gif

代码如下,请指教: 程序代码.zip (91.66 KB, 下载次数: 2)
  1. '''
  2. 名称:安全部件信息比对程序 V1.0
  3. 功能:提取Word中安全部件信息与Excel中的正确信息进行对比。
  4. 最后更新:2020/3/28

  5. '''
  6. import openpyxl
  7. from docx import Document
  8. from ComparisonData import *
  9. from OriginalData import *

  10. #打开目标文件
  11. wb = openpyxl.load_workbook('Excel file.xlsx')
  12. ws = wb.active
  13. document = Document('Word file.docx')

  14. class DateError():
  15.     '定义错误类,用于存放错误型号'
  16.     def __init__(self):
  17.         self.type = 'None'
  18.         self.model = 'None'
  19.         

  20. def check(original_data_list, comparison_data_list, name):
  21.     '检查两个数据类的每个属性值是否相同'
  22.     error_list = []
  23.     print('正在对比', name)
  24.     for B in comparison_data_list:
  25.         date_error = DateError()
  26.         model_ok = False
  27.         company_ok = False
  28.         cert_ok = False
  29.         nb_ok = False
  30.         
  31.         #依次比较
  32.         for A in original_data_list:
  33.             if B.model == A.model:
  34.                 model_ok = True
  35.                 #有同一型号,不同制造商的情况,单独判断
  36.                 if B.model  in ['AQ1', 'XS1']:
  37.                         for A in original_data_list:
  38.                                 if B.model == A.model and B.company == A.company:
  39.                                         model_ok = True
  40.                                         company_ok = True
  41.                                         if B.cert == A.cert:
  42.                                                 cert_ok = True
  43.                                                 if B.nb == A.nb:
  44.                                                         nb_ok = True
  45.                                                         print('%s | %s   -->  OK' % (B.model, B.company))                                
  46.                                                         break
  47.                                                 else:
  48.                                                         print('%s该型号公告机构错误!' % B.model)
  49.                                                         date_error.type = '公告机构错误'
  50.                                                         date_error.model = B.model
  51.                                                         error_list.append(date_error)
  52.                                                         break
  53.                                         else:
  54.                                                 print('%s该型号证书号错误!' % B.model)
  55.                                                 date_error.type = '证书号错误'
  56.                                                 date_error.model = B.model
  57.                                                 error_list.append(date_error)
  58.                                                 break
  59.                         if not company_ok:
  60.                             print('%s该型号制造商错误!' % B.model)
  61.                             print(B.company)
  62.                             date_error.type = '制造商错误'
  63.                             date_error.model = B.model
  64.                             error_list.append(date_error)
  65.                             break
  66.                 if B.company == A.company:
  67.                     company_ok = True
  68.                     if B.cert == A.cert:
  69.                         cert_ok = True
  70.                         if B.nb == A.nb:
  71.                             nb_ok = True
  72.                             print('%s   -->  OK' % B.model)
  73.                             break
  74.                         else:
  75.                             print('%s该型号公告机构错误!' % B.model)
  76.                             print(A.nb, B.nb)
  77.                             date_error.type = '公告机构错误'
  78.                             date_error.model = B.model
  79.                             error_list.append(date_error)
  80.                             break
  81.                     else:
  82.                         print('%s该型号证书号错误!' % B.model)
  83.                         date_error.type = '证书号错误'
  84.                         date_error.model = B.model
  85.                         error_list.append(date_error)
  86.                         break
  87.                 else:
  88.                     print('%s该型号制造商错误!' % B.model)
  89.                     print(A.company, B.company, sep='\n')
  90.                     date_error.type = '制造商错误'
  91.                     date_error.model = B.model
  92.                     error_list.append(date_error)
  93.                     break
  94.         if not model_ok:
  95.             #遍历完列表找不到该型号
  96.             print('%s没有对应型号!' % B.model)
  97.             date_error.type = '没有此型号'
  98.             date_error.model = B.model
  99.             error_list.append(date_error)
  100.     return error_list
  101.                            
  102.             
  103.         


  104. def sort(original_data, comparison_data):
  105.     '按照安全部件的名称分类'
  106.     for name in comparison_data.__dict__:
  107.         if name == 'SG':
  108.             original_data_list = original_data.SG
  109.             comparison_data_list = comparison_data.SG
  110.         if name == 'OG':
  111.             original_data_list = original_data.OG
  112.             comparison_data_list = comparison_data.OG
  113.         if name == 'BRAKE':
  114.             original_data_list = original_data.BRAKE
  115.             comparison_data_list = comparison_data.BRAKE
  116.         if name == 'BF':
  117.             original_data_list = original_data.BF
  118.             comparison_data_list = comparison_data.BF
  119.         if name == 'DL':
  120.             original_data_list = original_data.DL
  121.             comparison_data_list = comparison_data.DL
  122.         if name == 'UCMP':
  123.             original_data_list = original_data.UCMP
  124.             comparison_data_list = comparison_data.UCMP

  125.         #检查
  126.         error = check(original_data_list, comparison_data_list, name)

  127.         #集中打印错误
  128.         if error:
  129.             print('\n%s的错误有:' % name)
  130.             for each in error:
  131.                 print(each.model, each.type)
  132.         else:
  133.             print('\n%s无错误^_^' % name)

  134.         input('\n按任意键继续:')


  135. def main():
  136.     comparison_data = Comparison()     
  137.     original_data = Original()
  138.    
  139.     #从Word获取数据
  140.     get_data_from_word(document, comparison_data)
  141.     #从Excel获取数据        
  142.     get_data_from_excel(original_data, ws)

  143.     #开始对比
  144.     sort(original_data, comparison_data)
  145.            
  146.         
  147.             
  148.    
  149. if __name__ == '__main__':
  150.     main()
  151.    
  152.         


  153.    







复制代码

  1. '从word获得待对比数据'
  2. from docx import Document

  3. #定义安全部件的类
  4. class Component:
  5.     def __init__(self):
  6.         self.infos = []
  7.         self.model = 'None'
  8.         self.cert = 'None'
  9.         self.company = 'None'
  10.         self.nb = 'None'
  11.         self.nb_name = 'None'
  12.         self.type_ = 'None'

  13.     def info(self):
  14.         self.infos.append(self.model)
  15.         self.infos.append(self.company)
  16.         self.infos.append(self.cert)
  17.         self.infos.append(self.nb)
  18.         self.infos.append(self.nb_name)
  19.         return self.infos

  20.     def print(self):
  21.         self.info(self)
  22.         for each in self.infos:
  23.             print(each, sep='   |   ')

  24. #定义Comparison类
  25. class Comparison:
  26.     def __init__(self):
  27.         self.SG = []
  28.         self.BF = []
  29.         self.OG = []
  30.         self.BRAKE = []
  31.         self.UCMP = []
  32.         self.DL = []

  33. #定义添加到列表的函数
  34. def add2comparison_list(table, component, comparison_data):
  35.     'table是哪一个安全部件的表格,component是相应的类对象'
  36.     if table == sg_table:
  37.         comparison_data.SG.append(component)
  38.     if table == og_table:
  39.         comparison_data.OG.append(component)
  40.     if table == brake_table:
  41.         comparison_data.BRAKE.append(component)
  42.     if table == bf_table:
  43.         comparison_data.BF.append(component)
  44.     if table == dl_table:
  45.         comparison_data.DL.append(component)
  46.     if table == ucmp_table:
  47.         comparison_data.UCMP.append(component)

  48. #定义从表格获取数据的函数
  49. def get_data_from_table(table, comparison_data):
  50.     '从表格中获取数据,每一行的数据储存在实例化的component对象中,每个component对象再分类储存在comparison_data类中'
  51.     for each in range(1, len(table.rows)): #第0行和第1行非正文,默认从第1行开始读取数据
  52.         if 'Type' not in table.row_cells(each)[0].text:
  53.             #每个部件实例化一个对象
  54.             component = Component()
  55.             #model
  56.             component.model = table.row_cells(each)[0].text
  57.             #Manufacturer Name
  58.             component.company = table.row_cells(each)[1].text
  59.             #Cert. No
  60.             component.cert = table.row_cells(each)[2].text
  61.             #Notified body
  62.             component.nb = table.row_cells(each)[3].text

  63.             #component.print()
  64.             #component 以列表形式添加进comparison类中
  65.             add2comparison_list(table, component, comparison_data)

  66. def get_data_from_word(document, comparison_data):
  67.     '定位各个安全部件所在表格位置\
  68.     document: Word文件对象; comparison_data: 要对比的数据类'
  69.     table_list = []
  70.     global sg_table, og_table, brake_table, bf_table, dl_table, ucmp_table

  71.     #判断word中每一个表格
  72.     for each_table in document.tables:
  73.         #以每个表格左上角内容是否匹配关键字的方式来确定是否属于目标表格,是的话命名并存入列表
  74.         if 'gear' in each_table.cell(0, 0).text:
  75.             sg_table = each_table
  76.             table_list.append(each_table)
  77.         if 'governor' in each_table.cell(0, 0).text:
  78.             og_table = each_table
  79.             table_list.append(each_table)
  80.         if 'overspeed' in each_table.cell(0, 0).text:
  81.             brake_table = each_table
  82.             table_list.append(each_table)
  83.         if 'Buffer' in each_table.cell(0, 0).text:
  84.             bf_table = each_table
  85.             table_list.append(each_table)
  86.         if 'Locking' in each_table.cell(0, 0).text:
  87.             dl_table = each_table
  88.             table_list.append(each_table)
  89.         if 'UCMP' in each_table.cell(0, 0).text:
  90.             ucmp_table = each_table
  91.             table_list.append(each_table)
  92.         
  93.     #从各个表格获取数据
  94.     for each_table in table_list:
  95.         get_data_from_table(each_table, comparison_data)


  96. def main():
  97.     '测试函数'
  98.     document = Document('LF_A_C_18897_19-FINAL.docx')
  99.     comparison_data = Comparison()
  100.     get_data_from_word(document, comparison_data)

  101.     print('共统计得到:')
  102.     print('安全钳:%d个' % len(comparison_data.SG))
  103.     print('限速器:%d个' % len(comparison_data.OG))
  104.     print('制动器:%d个' % len(comparison_data.BRAKE))
  105.     print('缓冲器:%d个' % len(comparison_data.BF))
  106.     print('门锁:%d个' % len(comparison_data.DL))
  107.     print('UCMP:%d个' % len(comparison_data.UCMP))

  108. if __name__ == '__main__':
  109.     main()

  110.    



复制代码

  1. ''' 从Excel中获取原始的数据信息,存储在Original类中以便于对比 '''
  2. import openpyxl
  3. from ComparisonData import Component

  4. #定义Original类
  5. class Original:
  6.     def __init__(self):
  7.         self.SG = []
  8.         self.BF = []
  9.         self.OG = []
  10.         self.BRAKE = []
  11.         self.UCMP = []
  12.         self.DL = []

  13. def get_data_from_excel(original_data, worksheet):
  14.     #识别安全部件类型, 默认从39行开始
  15.     #detect_component('B39', 'D200')

  16.     #安全钳
  17.     for each in worksheet['B42':'E69']:
  18.         component = Component()
  19.         
  20.         component.model = each[0].value
  21.         component.cert = each[1].value
  22.         component.nb = each[2].value
  23.         component.company = each[3].value

  24.         original_data.SG.append(component)

  25.     #限速器
  26.     for each in worksheet['B73':'E84']:
  27.         component = Component()
  28.         
  29.         component.model = each[0].value
  30.         component.cert = each[1].value
  31.         component.nb = each[2].value
  32.         component.company = each[3].value

  33.         original_data.OG.append(component)

  34.     #制动器
  35.     for each in worksheet['B88':'E108']:
  36.         component = Component()
  37.         
  38.         component.model = each[0].value
  39.         component.cert = each[1].value
  40.         component.nb = each[2].value
  41.         component.company = each[3].value

  42.         original_data.BRAKE.append(component)

  43.     #缓冲器
  44.     for each in worksheet['B112':'E126']:
  45.         component = Component()
  46.         
  47.         component.model = each[0].value
  48.         component.cert = each[1].value
  49.         component.nb = each[2].value
  50.         component.company = each[3].value

  51.         original_data.BF.append(component)

  52.     #门锁
  53.     for each in worksheet['B130':'E159']:
  54.         component = Component()
  55.         
  56.         component.model = each[0].value
  57.         component.cert = each[1].value
  58.         component.nb = each[2].value
  59.         component.company = each[3].value

  60.         original_data.DL.append(component)

  61.     #UCMP
  62.     for each in worksheet['B163':'E188']:
  63.         component = Component()
  64.         
  65.         component.model = each[0].value
  66.         component.cert = each[1].value
  67.         component.nb = each[2].value
  68.         component.company = each[3].value

  69.         original_data.UCMP.append(component)


  70. def main():
  71.     '测试函数'
  72.     wb = openpyxl.load_workbook('A3-TECHNICAL SPECIFICATION SHEET-FUJI-MR.xlsx')
  73.     ws = wb.active
  74.     original_data = Original()
  75.     get_data_from_excel(original_data, ws)

  76.     print('共统计得到:')
  77.     print('安全钳:%d个' % len(original_data.SG))
  78.     print('限速器:%d个' % len(original_data.OG))
  79.     print('制动器:%d个' % len(original_data.BRAKE))
  80.     print('缓冲器:%d个' % len(original_data.BF))
  81.     print('门锁:%d个' % len(original_data.DL))
  82.     print('UCMP:%d个' % len(original_data.UCMP))

  83.    
  84. if __name__ == '__main__':
  85.     main()
  86.    
  87.    
  88.         
  89.         
  90.    
  91.    
  92.    
  93.    
复制代码


小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2020-4-2 10:34:16 | 显示全部楼层
弱弱的问一句:如此简单的功能,用这么多行代码,正常吗
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-24 21:25:16 | 显示全部楼层
allearn_Python 发表于 2020-4-2 10:34
弱弱的问一句:如此简单的功能,用这么多行代码,正常吗

你好 我也遇到了一个和你类似的问题  可我实在不会openpyxl  方便时帮我下吧  太感谢了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-8-25 13:06:14 | 显示全部楼层
超哥超级爱学习 发表于 2020-8-24 21:25
你好 我也遇到了一个和你类似的问题  可我实在不会openpyxl  方便时帮我下吧  太感谢了

我对openpyxl也是初学者,也就是对excel进行读写操作等基本功能熟悉,帮人解决问题怕能力还不够
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-25 16:42:52 | 显示全部楼层
allearn_Python 发表于 2020-8-25 13:06
我对openpyxl也是初学者,也就是对excel进行读写操作等基本功能熟悉,帮人解决问题怕能力还不够{:10_266: ...

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-26 03:20

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表