需要注意的几个点

  • 脚本是按行复制粘贴的,如果抓取的文件表头设置不对,会出现错位

无标题.png
有的表可能不是按”表头1,表头2,…”这样设置,可能多了一列或者少了一列

  • 有的表的单元格会链接到别的表,运行时会跳出弹窗
  • 大多数的代码是用来处理合并单元格的
  • 默认选择工作簿的第一张表,需要抓取的表可能在第二张

    几个有用的库和函数

    这一块我就直接cv大法了

    文件名去除后缀

    1. def getFilenameWithoutSuffix(path):
    2. filename = os.path.basename(path)
    3. filename = filename.split('.')[1] #文件名是22.xxxx.xlsx
    4. return filename

    正则匹配字符串

    1. def matchStr(input_str,ref_str):
    2. if type(input_str) == str:#确定输入的是字符串
    3. match = re.search(ref_str,input_str)
    4. if match:
    5. return True
    6. else:
    7. return False
    8. else:
    9. return False

    字符串区间的差值

    1. #从"2:4"这样的字符串中获取差值
    2. def getDifNumber(input_str):
    3. num_list = input_str.split(':')
    4. dif_num = int(num_list[1]) - int(num_list[0])
    5. return dif_num

    获取单元格的地址/列数转成字母

    1. def getCellAddress(sheet,row,col):
    2. temp_address = sheet.Cells(row,col).Address
    3. cell_address = temp_address.replace('$','')
    4. return cell_address

    glob库

字符串拼接

代码

  1. import os,glob
  2. import win32com.client
  3. import win32api
  4. import re,time
  5. import io
  6. import sys
  7. sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8')
  8. #这三行为了让终端显示中文
  9. def getFilenameWithoutSuffix(path):
  10. filename = os.path.basename(path)
  11. filename = filename.split('.')[1] #文件名是22.xxxx.xlsx
  12. return filename
  13. def matchStr(input_str,ref_str):
  14. if type(input_str) == str:
  15. match = re.search(ref_str,input_str)
  16. if match:
  17. return True
  18. else:
  19. return False
  20. else:
  21. return False
  22. def checkNewTable(sheet,rowNum,colNum):
  23. for row in range(1,rowNum+1):
  24. for col in range(1,colNum+1):
  25. if matchStr(sheet.Cells(row,col).Value,'设备招标情况'):
  26. return [True,row,col]
  27. elif matchStr(sheet.Cells(row,col).Value,'采购状态'):
  28. return [False,row,col]
  29. print('\033[1;35m 查询不到表头! \033[0m')
  30. return [0,0,0]
  31. def strProcess(input_str):
  32. input_str = input_str.replace('$','')#去除$
  33. b=re.sub('[A-Za-z]','',input_str)#去除字母
  34. return b
  35. #从"2:4"这样的字符串中获取差值
  36. def getDifNumber(input_str):
  37. num_list = input_str.split(':')
  38. dif_num = int(num_list[1]) - int(num_list[0])
  39. return dif_num
  40. def pasteRows(sheet,row,paste):
  41. paste_range = str(row) + ':' + str(row)
  42. sheet.Range(paste_range).PasteSpecial(Paste=paste)#要带列宽的话需要多执行一遍Paste=8
  43. def getCellAddress(sheet,row,col):
  44. temp_address = sheet.Cells(row,col).Address
  45. cell_address = temp_address.replace('$','')
  46. return cell_address
  47. file_dir = glob.glob(r'E:\1、正在执行项目\*.xlsx')
  48. pos_col = 3 #以经办人这一列来确定是否为有效行
  49. sht2_row = 4 #开始复制的行
  50. try:
  51. xlApp = win32com.client.Dispatch('Excel.Application')
  52. xlBook2 = xlApp.Workbooks.Open(r'E:\测试\测试.xlsx')
  53. sht2 = xlBook2.Sheets(1)
  54. for i in range(len(file_dir)):
  55. xlBook1 = xlApp.Workbooks.Open(Filename=file_dir[i],ReadOnly=True)
  56. filenameWithoutSuffix = getFilenameWithoutSuffix(file_dir[i])
  57. print('\033[1;32;43m ',filenameWithoutSuffix,' \033[0m!')
  58. sht1 = xlBook1.Sheets(1) #默认选择第一张表
  59. rowNum = sht1.UsedRange.Rows.Count #返回文件1的行数
  60. colNum = sht1.UsedRange.Columns.Count #返回文件1的列数
  61. cell_state = checkNewTable(sht1,rowNum,colNum)
  62. header_row = cell_state[1] #如果表头是合并单元格,也没必要加一
  63. match_col = cell_state[2] #匹配列的列数
  64. if cell_state[0]==True:
  65. for row in range(header_row+1,rowNum+1):
  66. pos_cell = sht1.Cells(row,pos_col)
  67. cell = sht1.Cells(row,match_col)
  68. print('第',row,'行:',end=' ')
  69. sys.stdout.flush() #刷新缓存区
  70. if type(pos_cell.Value) == str:
  71. if pos_cell.MergeCells :
  72. temp_address = sht1.Cells(row,pos_col).MergeArea.Address#获取合并单元格的地址
  73. rows_range = strProcess(temp_address)#清洗得到的字符串
  74. print('合并单元格行数--',rows_range)
  75. sys.stdout.flush()
  76. dif_num = getDifNumber(rows_range)
  77. if matchStr(cell.Value,'合同已签') == False :
  78. print(cell.Value)
  79. sht1.Range(rows_range).Copy() #复制这几行
  80. pasteRows(sht2,sht2_row,14) #粘贴到总表
  81. cell_address = getCellAddress(sht2,sht2_row,colNum+1)
  82. sht2.Range(cell_address).Value = filenameWithoutSuffix
  83. #这两行在表末尾增加了一列,给单元格赋值,内容是表名称
  84. last_cell = getCellAddress(sht2,sht2_row + dif_num,colNum+1)
  85. merge_range = cell_address + ':' + last_cell
  86. sht2.Range(merge_range).Merge() #合并单元格
  87. sht2.Range(merge_range).Borders.LineStyle = 1 #加框线
  88. sht2.Range(merge_range).HorizontalAlignment = -4108 #设置水平居中
  89. print('复制到表2第',sht2_row,'行',end='***')
  90. sht2_row += dif_num + 1
  91. print('下次行数:',sht2_row)
  92. sys.stdout.flush()
  93. row += dif_num
  94. else:
  95. print('非空的标准单元格:',pos_cell.Value)
  96. if matchStr(cell.Value,'合同已签')==False :
  97. sht1.Rows(row).Copy()#复制这几行
  98. pasteRows(sht2,sht2_row,14)
  99. sht2_row += 1
  100. sys.stdout.flush() #刷新缓存区
  101. sht2.Cells.FormatConditions.Delete()#清除条件格式,不然格子的颜色会乱掉
  102. xlApp.CutCopyMode = False
  103. xlBook1.Close()
  104. xlBook2.Save()
  105. finally:
  106. # if xlApp.ClipboardFormats[0]:
  107. # xlApp.CutCopyMode = False#清空剪贴板
  108. xlApp.quit()