一、代碼
特殊操作包括(隱藏列,解鎖工作表保護,插入批注,創建文本框,追加修改單元格內容)
from openpyxl import load_workbook import win32com.client # 隱藏列 def hidden_column(path, column, sheet_name=0): ''' :param path: 文件路徑 :param column: 列名,如A,B,C,可以傳入單個,可以是區間[B,E] :return: ''' try: wb = load_workbook(path, data_only=True) if isinstance(sheet_name, str): ws = wb.get_sheet_by_name(sheet_name) else: ws = wb.worksheets[sheet_name] if isinstance(column, list): ws.column_dimensions.group(column[0], column[1], hidden=True) else: ws.column_dimensions[column].hidden = True wb.save(path) except Exception as e: print("打開文件失敗:%s" % e) # 解鎖工作表保護 def unlock_excel(path, password, sheet_name="Sheet1"): ''' :param path: 文件路徑 :param password:工作表保護密碼 :param sheetname: sheet名 :return: ''' xlApp = win32com.client.DispatchEx("Excel.Application") try: # 后台運行, 不顯示, 不警告 xlApp.Visible = False xlApp.DisplayAlerts = False wb = xlApp.Workbooks.Open(path) # 屏蔽彈窗 wb.Checkcompatibility = False sht = wb.Worksheets(sheet_name) sht.Unprotect(password) wb.Save() wb.Close(SaveChanges=True) except Exception as e: xlApp.Quit() print("打開文件失敗:%s" % e) # 插入批注 def insert_notes(path, cell, content, sheet_name="Sheet1"): ''' :param path: 文件路徑 :param cell: 批注單元格:如B4 :param content: 批注內容 :param notes_name: 批注人名 :param sheet_name: sheet名 :return: ''' xlApp = win32com.client.DispatchEx("Excel.Application") try: # 后台運行, 不顯示, 不警告 xlApp.Visible = False xlApp.DisplayAlerts = False wb = xlApp.Workbooks.Open(path) sht = wb.Worksheets(sheet_name) if not sht.Range(cell).Comment: sht.Range(cell).AddComment() sht.Range(cell).Comment.Text(content) wb.Save() wb.Close() except Exception as e: xlApp.Quit() print("打開文件失敗:%s" % e) # 創建文本框 def create_text_box(path, left,top,Width,Height,content, sheet_name="Sheet1"): xlApp = win32com.client.DispatchEx("Excel.Application") try: # 后台運行, 不顯示, 不警告 xlApp.Visible = False xlApp.DisplayAlerts = False wb = xlApp.Workbooks.Open(path) sht = wb.Worksheets(sheet_name) # 分別是文字方向,文本框的左上角相對於文檔左上角的位置, # 相對於文檔頂部的文本框左上角的位置,文本框的寬度,文本框的高度(以磅為單位) # 磅的大小為 1/72 英寸。 字號通常用磅衡量 sht.Shapes.AddTextbox(1, left,top,Width,Height).TextFrame.Characters().Text=content wb.Save() wb.Close() except Exception as e: xlApp.Quit() print("打開文件失敗:%s" % e) # 讀取單元格,並修改單元格 def add_content_cell(path,cell,add_content,sheet_name="Sheet1"): xlApp = win32com.client.DispatchEx("Excel.Application") try: # 后台運行, 不顯示, 不警告 xlApp.Visible = False xlApp.DisplayAlerts = False wb = xlApp.Workbooks.Open(path) sht = wb.Worksheets(sheet_name) value=sht.Range(cell).Value sht.Range(cell).Value=value.strip("\n")+"\n"+add_content wb.Save() wb.Close() except Exception as e: xlApp.Quit() print("打開文件失敗:%s" % e)
二、對win32進行了open,close封裝
class Win32_excel(object): def __init__(self, path, sheet_name="Sheet1"): self.xlApp = win32com.client.DispatchEx("Excel.Application") self.path = path self.sheet_name = sheet_name def __enter__(self): try: # 后台運行, 不顯示, 不警告 self.xlApp.Visible = False self.xlApp.DisplayAlerts = False self.wb = self.xlApp.Workbooks.Open(self.path) # 屏蔽彈窗 self.wb.Checkcompatibility = False self.sht = self.wb.Worksheets(self.sheet_name) return self except Exception as e:
self.xlApp.Quit() print("打開文件失敗:%s" % e) def __exit__(self, exc_type, exc_val, exc_tb): self.wb.Save() self.wb.Close(SaveChanges=True) self.xlApp.Quit() # 解鎖工作表保護 def unlock_excel(self, password): self.sht.Unprotect(password) # 插入批注 def insert_notes(self, cell, content): if not self.sht.Range(cell).Comment: self.sht.Range(cell).AddComment() self.sht.Range(cell).Comment.Text(content) # 創建文本框 def create_text_box(self, left, top, Width, Height, content): # 分別是文字方向,文本框的左上角相對於文檔左上角的位置, # 相對於文檔頂部的文本框左上角的位置,文本框的寬度,文本框的高度(以磅為單位) # 磅的大小為 1/72 英寸。 字號通常用磅衡量 self.sht.Shapes.AddTextbox(1, left, top, Width, Height).TextFrame.Characters().Text = content # 讀取單元格,並修改單元格 def add_content_cell(self, cell, add_content): value = self.sht.Range(cell).Value self.sht.Range(cell).Value = value.strip("\n") + "\n" + add_content # 復制單元格 def copy_cells(self, copy_cells, to_cells): # copy_cells,如:"A1:B1" # to_cells,如:"A2:B2" self.sht.Range(copy_cells).Copy() self.sht.Range(to_cells).PasteSpecial() # 插入單元格 def insert_cells(self,cells): # cells,如:"A1:E1" self.sht.Range(cells).Insert() # 插入行 def insert_row(self,row): # 在第幾行之前插入新行 self.sht.Rows(row).Insert() # 單元格寫入 def write(self,cell,content): self.sht.Range(cell).Value=content if __name__ == '__main__': path=r"日報.xlsx" df=pd.read_excel(path,sheet_name="sheet名") row=df.shape[0] print(row) with Win32_excel(path,sheet_name="sheet名") as w32: w32.insert_row(row+1) w32.copy_cells("A%s:G%s"%(row,row),"A%s:G%s"%(row+1,row+1))
三、改進更多方法
class Win32_excel(object): def __init__(self, path, sheet_name="Sheet1"): self.xlApp = win32com.client.DispatchEx("Excel.Application") self.path = path self.sheet_name = sheet_name try: # 后台運行, 不顯示, 不警告 self.xlApp.Visible = False self.xlApp.DisplayAlerts = False self.wb = self.xlApp.Workbooks.Open(self.path) # 屏蔽彈窗 self.wb.Checkcompatibility = False self.sht = self.wb.Worksheets(self.sheet_name) except Exception as e: self.xlApp.Quit() print("打開文件失敗:%s" % e) def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self.close() def close(self): self.wb.Save() self.wb.Close(SaveChanges=True) self.xlApp.Quit() # 解鎖工作表保護 def unlock_excel(self, password): self.sht.Unprotect(password) # 插入批注 def insert_notes(self, cell, content): if not self.sht.Range(cell).Comment: self.sht.Range(cell).AddComment() self.sht.Range(cell).Comment.Text(content) self.sht.Range(cell).Comment.Shape.TextFrame.Characters(6).Font.Bold = False # 取消字體加粗 # 判斷是否有批注 def have_notes(self,cell): if self.sht.Range(cell).Comment: return True # 追加批注 def add_notes(self, cell, content): if not self.sht.Range(cell).Comment: self.sht.Range(cell).AddComment() text = self.sht.Range(cell).Comment.Text() self.sht.Range(cell).Comment.Text(text + content) self.sht.Range(cell).Comment.Shape.TextFrame.Characters(6).Font.Bold = False # 取消字體加粗 self.sht.Range(cell).Comment.Shape.Height = 70 # 設置批注高度寬度 def set_notes_height_width(self, cell, height, width): self.sht.Range(cell).Comment.Shape.Height = height self.sht.Range(cell).Comment.Shape.Width = width # 創建文本框 def create_text_box(self, left, top, Width, Height, content): # 分別是文字方向,文本框的左上角相對於文檔左上角的位置, # 相對於文檔頂部的文本框左上角的位置,文本框的寬度,文本框的高度(以磅為單位) # 磅的大小為 1/72 英寸。 字號通常用磅衡量 self.sht.Shapes.AddTextbox(1, left, top, Width, Height).TextFrame.Characters().Text = content # 讀取單元格,並修改單元格 def add_content_cell(self, cell, add_content): value = self.sht.Range(cell).Value self.sht.Range(cell).Value = value.strip("\n") + "\n" + add_content # 復制單元格 def copy_cells(self, copy_cells, to_cells): # copy_cells,如:"A1:B1" # to_cells,如:"A2:B2" self.sht.Range(copy_cells).Copy() self.sht.Range(to_cells).PasteSpecial() # 復制單元格只黏貼數值 def copy_cells_only_data(self, copy_cells, to_cells): # copy_cells,如:"A1:B1" # to_cells,如:"A2:B2" self.sht.Range(copy_cells).Copy() self.sht.Range(to_cells).PasteSpecial(Paste=-4163) # 只清除單元格數據 def del_cells_only_data(self, cells): self.sht.Range(cells).ClearContents() # 刪除列 def del_cols(self, col): self.sht.Columns(col).Delete() # 刪除行 def del_rows(self, row): self.sht.Rows(row).Delete() # 向右復制一列 def copy_col(self, col): self.sht.Columns(col).Copy() self.sht.Columns(col + 1).PasteSpecial() # 復制一行到指定位置 def copy_col_to_other(self, col1, col2): self.sht.Rows(col1).Copy() self.sht.Rows(col2).PasteSpecial() # 向上復制一行 def copy_row_up(self, col): self.sht.Rows(col + 1).Copy() self.sht.Rows(col).PasteSpecial() # 向下復制一行 def copy_row_down(self, col): self.sht.Rows(col).Copy() self.sht.Rows(col + 1).PasteSpecial() # 插入單元格 def insert_cells(self, cells): # cells,如:"A1:E1" self.sht.Range(cells).Insert() # 插入行 def insert_row(self, row): # 在第幾行之前插入新行 self.sht.Rows(row).Insert() # 插入一列 def insert_col(self, col): # 在第幾行之前插入新行 self.sht.Columns(col).Insert() # 單元格寫入 def write(self, cell, content): self.sht.Range(cell).Value = content # 獲取值 def get_content(self, cell): content = self.sht.Range(cell).Value return content # 獲取圖表數據源 def get_ChartObject(self, num): Formula = self.sht.ChartObjects(num).Chart.SeriesCollection(7).Formula print(self.sht.ChartObjects(num).Chart.ChartTitle.Text) # 查看圖表標題 return Formula # 設置圖表數據源 def set_ChartObject(self, num, Formula): self.sht.ChartObjects(num).Chart.SeriesCollection(1).Formula = Formula # self.sht.ChartObjects(num).SetSourceData(Formula) # 獲取excel英文列名 def get_col_name(self, col_num): Address = self.sht.Columns(col_num).Address return Address # 查找內容 def find(self, what): res = self.sht.UsedRange.Find(what) return res # 設置單元格顏色 def set_color(self, cell, color): colors = {"無": 0, "黑": 1, "白": 2, "紅": 3, "綠": 4, "藍": 5, "黃": 6} self.sht.Range(cell).Interior.ColorIndex = colors.get(color, 0) # 獲取單元格公式 def get_cell_Formula(self, cell): res = self.sht.Range(cell).Formula return res # 設置單元格公式 def set_cell_Formula(self, cell, Formula): self.sht.Range(cell).Formula = Formula # 刪除批注 def del_comment(self, cell): if self.sht.Range(cell).Comment: self.sht.Range(cell).Comment.Delete() # 隱藏列 def hidden_col(self, col): self.sht.Columns(col).Hidden = True # 篩選 def cell_Filter(self, cell, Field, filter): self.sht.Range(cell).AutoFilter(Field=Field, Criteria1=filter) # 獲取A最后一行的行號 def get_last_row(self): row = self.sht.Range("A65536").End(-4162).Row return row # 獲取指定最后一行的行號 def get_assign_row(self, row): row = self.sht.Range("%s65536" % row).End(-4162).Row return row # 另存為pdf def save_to_pdf(self, path): self.sht.ExportAsFixedFormat(Type=0, Filename=path,From=1,To=1) # 激活sheet def activate_sheet(self): self.sht.Activate() # 刪除行內容 def del_col_content(self, col): self.sht.Rows(col).ClearContents() # 取消合並單元格 def un_merger(self, cell): self.sht.Range(cell).UnMerge() # 刷新數透表 def refreshAll(self): self.sht.PivotTables(1).PivotCache().Refresh() # 數值化 def set_range_values(self, cell): self.sht.Range(cell).value = self.sht.Range(cell).value # 自動設置行高 def set_row_high(self, cell, high): self.sht.Range(cell).RowHeight = high def set_PrintArea(self, col_name, col_num): self.sht.PageSetup.PrintArea = "$A$1:$%s$%s" % (col_name, col_num)
四、單文件多sheet,多文件多sheet
# -*- coding: utf-8 -*- import win32com.client class Win32_excel(object): def __init__(self, path=None,sheet_name=None,more_paths=None): ''' :param path: 單文件處理路徑 :param sheet_name: 單sheet :param more_paths: 多sheet或多文件,格式:{path1:[sheet1,sheet2],path2:[sheet1,sheet2]} ''' self.xlApp = win32com.client.DispatchEx("Excel.Application") # 后台運行, 不顯示, 不警告 self.xlApp.Visible = False self.xlApp.DisplayAlerts = False self.wbs=[] # [wb1,wb2] self.more=False if path and sheet_name: self.open(path,sheet_name) else: if not more_paths: raise ("請正確輸入文件路徑和sheet名參數") count=1 for path,sheet_names in more_paths.items(): self.more=True self.open(path,sheet_names,count) count+=1 def add_wb_sht(self,wb_name,sht_name,sht): self.__setattr__(wb_name+"_"+sht_name,sht) def open(self,path,sheet_name,count=1): try: if self.more: wb=self.xlApp.Workbooks.Open(path) # 屏蔽彈窗 wb.Checkcompatibility = False self.wbs.append(wb) count_num=1 for sheet in sheet_name: sht = wb.Worksheets(sheet) self.add_wb_sht("wb%s"%count,"sht%s"%count_num,sht) count_num+=1 else: self.wb = self.xlApp.Workbooks.Open(path) # 屏蔽彈窗 self.wb.Checkcompatibility = False self.sht = self.wb.Worksheets(sheet_name) except Exception as e: self.xlApp.Quit() raise ("打開文件失敗:%s" % e) def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self.close() def close(self): if self.more: for wb in self.wbs: wb.Save() wb.Close(SaveChanges=True) else: self.wb.Save() self.wb.Close(SaveChanges=True) self.xlApp.Quit() # 解鎖工作表保護 def unlock_excel(self, password): self.sht.Unprotect(password) # 插入批注 def insert_notes(self, cell, content): if not self.sht.Range(cell).Comment: self.sht.Range(cell).AddComment() self.sht.Range(cell).Comment.Text(content) self.sht.Range(cell).Comment.Shape.TextFrame.Characters(6).Font.Bold = False # 取消字體加粗 # 判斷是否有批注 def have_notes(self, cell): if self.sht.Range(cell).Comment: return True # 追加批注 def add_notes(self, cell, content): if not self.sht.Range(cell).Comment: self.sht.Range(cell).AddComment() text = self.sht.Range(cell).Comment.Text() self.sht.Range(cell).Comment.Text(text + content) self.sht.Range(cell).Comment.Shape.TextFrame.Characters(6).Font.Bold = False # 取消字體加粗 self.sht.Range(cell).Comment.Shape.Height = 70 # 設置批注高度寬度 def set_notes_height_width(self, cell, height, width): self.sht.Range(cell).Comment.Shape.Height = height self.sht.Range(cell).Comment.Shape.Width = width # 創建文本框 def create_text_box(self, left, top, Width, Height, content): # 分別是文字方向,文本框的左上角相對於文檔左上角的位置, # 相對於文檔頂部的文本框左上角的位置,文本框的寬度,文本框的高度(以磅為單位) # 磅的大小為 1/72 英寸。 字號通常用磅衡量 self.sht.Shapes.AddTextbox(1, left, top, Width, Height).TextFrame.Characters().Text = content # 讀取單元格,並修改單元格 def add_content_cell(self, cell, add_content): value = self.sht.Range(cell).Value self.sht.Range(cell).Value = value.strip("\n") + "\n" + add_content # 復制單元格 def copy_cells(self, copy_cells, to_cells): # copy_cells,如:"A1:B1" # to_cells,如:"A2:B2" self.sht.Range(copy_cells).Copy() self.sht.Range(to_cells).PasteSpecial() # 復制單元格只黏貼數值 def copy_cells_only_data(self, copy_cells, to_cells): # copy_cells,如:"A1:B1" # to_cells,如:"A2:B2" self.sht.Range(copy_cells).Copy() self.sht.Range(to_cells).PasteSpecial(Paste=-4163) # 只清除單元格數據 def del_cells_only_data(self, cells): self.sht.Range(cells).ClearContents() # 刪除列 def del_cols(self, col): self.sht.Columns(col).Delete() # 刪除行 def del_rows(self, row): self.sht.Rows(row).Delete() # 向右復制一列 def copy_col(self, col): self.sht.Columns(col).Copy() self.sht.Columns(col + 1).PasteSpecial() # 復制一行到指定位置 def copy_col_to_other(self, col1, col2): self.sht.Rows(col1).Copy() self.sht.Rows(col2).PasteSpecial() # 向上復制一行 def copy_row_up(self, col): self.sht.Rows(col + 1).Copy() self.sht.Rows(col).PasteSpecial() # 向下復制一行 def copy_row_down(self, col): self.sht.Rows(col).Copy() self.sht.Rows(col + 1).PasteSpecial() # 插入單元格 def insert_cells(self, cells): # cells,如:"A1:E1" self.sht.Range(cells).Insert() # 插入行 def insert_row(self, row): # 在第幾行之前插入新行 self.sht.Rows(row).Insert() # 插入一列 def insert_col(self, col): # 在第幾行之前插入新行 self.sht.Columns(col).Insert() # 單元格寫入 def write(self, cell, content): self.sht.Range(cell).Value = content # 獲取值 def get_content(self, cell): content = self.sht.Range(cell).Value return content # 獲取圖表數據源 def get_ChartObject(self, num): Formula = self.sht.ChartObjects(num).Chart.SeriesCollection(1).Formula print(self.sht.ChartObjects(num).Chart.ChartTitle.Text) # 查看圖表標題 return Formula # 設置圖表數據源 def set_ChartObject(self, num, Formula): self.sht.ChartObjects(num).Chart.SeriesCollection(1).Formula = Formula # self.sht.ChartObjects(num).SetSourceData(Formula) # 獲取excel英文列名 def get_col_name(self, col_num): Address = self.sht.Columns(col_num).Address return Address # 查找內容 def find(self, what): res = self.sht.UsedRange.Find(what) return res # 設置單元格顏色 def set_color(self, cell, color): colors = {"無": 0, "黑": 1, "白": 2, "紅": 3, "綠": 4, "藍": 5, "黃": 6} self.sht.Range(cell).Interior.ColorIndex = colors.get(color, 0) # 獲取單元格公式 def get_cell_Formula(self, cell): res = self.sht.Range(cell).Formula return res # 設置單元格公式 def set_cell_Formula(self, cell, Formula): self.sht.Range(cell).Formula = Formula # 刪除批注 def del_comment(self, cell): if self.sht.Range(cell).Comment: self.sht.Range(cell).Comment.Delete() # 隱藏列 def hidden_col(self, col): self.sht.Columns(col).Hidden = True # 篩選 def cell_Filter(self, cell, Field, filter): self.sht.Range(cell).AutoFilter(Field=Field, Criteria1=filter) # 獲取A最后一行的行號 def get_last_row(self): row = self.sht.Range("A65536").End(-4162).Row return row # 獲取指定最后一行的行號 def get_assign_row(self, row): row = self.sht.Range("%s65536" % row).End(-4162).Row return row # 另存為pdf def save_to_pdf(self, path): self.sht.ExportAsFixedFormat(Type=0, Filename=path, From=1, To=1) # 激活sheet def activate_sheet(self): self.sht.Activate() # 刪除行內容 def del_col_content(self, col): self.sht.Rows(col).ClearContents() # 取消合並單元格 def un_merger(self, cell): self.sht.Range(cell).UnMerge() # 刷新數透表 def refreshAll(self): self.sht.PivotTables(1).PivotCache().Refresh() # 數值化 def set_range_values(self, cell): self.sht.Range(cell).value = self.sht.Range(cell).value # 自動設置行高 def set_row_high(self, cell, high): self.sht.Range(cell).RowHeight = high # 設置打印區域 def set_PrintArea(self, col_name, col_num): self.sht.PageSetup.PrintArea = "$A$1:$%s$%s" % (col_name, col_num) # range向下復制一行 def copy_range_down(self, up_cell, down_cell): self.sht.Range(up_cell).Copy() self.sht.Range(down_cell).PasteSpecial() #單文件單sheet with Win32_excel(path=r"********",sheet_name=1) as w32: print(w32.wb) #獲取的是wb對象 print(w32.sht) #獲取的是sheet對象 # 單文件多sheet,多文件多sheet with Win32_excel(more_paths={r"********":[1,2,3]}) as w32: print(w32.wbs) #獲取的是wb列表 print(w32.wb1_sht1) #獲取的是sheet對象 print(w32.wb1_sht2) # 使用方法前,重新賦值w32.sht w32.sht=w32.wb1_sht1 w32.write("A1","內容")