###### tags: `python` # python讀取/修改excel ```shell= pip3 install openpyxl ``` ## 專有名詞 **workbook(活頁簿)**:也就是一個excel檔案 **worksheet(工作表)**:一個excel可以有很多個工作表,目前正在觀看或處理的工作表又稱作「活動中的工作表(active sheet)」 **欄(column)**:工作表中的直欄,以A、B、C...代表 **行(row)**:工作表中的橫列,以1、2、3...代表 **儲存格(cell)**:工作表中的每一個都是一個儲存格 --- ## 新增空白excel ```python= import openpyxl fn = 'new_excel.xlsx' wb = openpyxl.Workbook() wb.save(fn) ``` --- ## 新增工作表並指定放置位置 ```python= import openpyxl fn = 'new_excel.xlsx' wb = openpyxl.Workbook() wb.create_sheet("Mysheet1", 1) # 新增工作表並指定放置位置 wb.create_sheet("Mysheet0", 0) wb.save(fn) ``` --- ## 讀取excel檔案每個工作表的名稱 ```python= import openpyxl fn = 'test.xlsx' wb = openpyxl.load_workbook(fn) print(wb.sheetnames) print(wb.active) print(wb.active.title) ``` ## 修改工作表名稱 ```python= import openpyxl workbook = openpyxl.load_workbook("sample.xlsx") sheet = workbook['AAA'] sheet.title = 'Fruit' workbook.save("sample.xlsx") ``` ## 修改工作表顏色 ```python= import openpyxl workbook = openpyxl.load_workbook("sample.xlsx") sheet = workbook.active sheet.sheet_properties.tabColor = "1072BA" workbook.save("sample.xlsx") ``` ## 隱藏/取消隱藏工作表 ```python= import openpyxl workbook = openpyxl.load_workbook("sample.xlsx") sheet = workbook['BBB'] sheet.sheet_state = 'hidden' # sheet = workbook['BBB'] # sheet.sheet_state = 'visible' workbook.save("sample.xlsx") ``` ## 修改目前工作表 ```python= import openpyxl fn = 'test.xlsx' wb = openpyxl.load_workbook(fn) print('excel活動工作表: ', wb.active) wb.active = 0 print('excel活動工作表: ', wb.active) ``` ```python= import openpyxl from openpyxl.utils import get_column_letter, column_index_from_string fn = 'test.xlsx' wb = openpyxl.load_workbook(fn) print('目前工作表: ', wb.active.title) wb.active = wb['銷售明細表'] print('目前工作表: ', wb.active.title) ``` ## 複製工作表 ```python= import openpyxl workbook = openpyxl.load_workbook("sample.xlsx") sheet = workbook['BBB'] target = workbook.copy_worksheet(sheet) target.title = 'new' workbook.save("sample.xlsx") ``` ## 刪除工作表 ```python= import openpyxl workbook = openpyxl.load_workbook("sample.xlsx") sheet = workbook['new'] workbook.remove(sheet) workbook.save("sample.xlsx") ``` ## 讀取工作表所有內容 ```python= import openpyxl fn = 'test.xlsx' wb = openpyxl.load_workbook(fn) wb.active = 0 ws = wb.active print('excel活動工作表: ', ws) for row in ws: for cell in row: print(cell.value) print() print('D1內容: ', ws['D1'].value) ``` ```python= import openpyxl fn = 'test.xlsx' wb = openpyxl.load_workbook(fn) ws = wb.active range = ws['A1': 'B6'] for a, b in range: print("{0} {1}".format(a.value, b.value)) print() for a, b, c in ws[ws.dimensions]: print(a.value, b.value, c.value) ``` ## 寫入儲存格 所有的修改都只是針對記憶體中的excel檔 只有save才會把修改的內容寫到儲存媒體上 ```python= import openpyxl fn = 'test.xlsx' wb = openpyxl.load_workbook(fn) wb.active = 0 ws = wb.active print('B2內容: ', ws['B2'].value) ws['B2'].value = 20 print('B2內容: ', ws['B2'].value) ws.cell(column=2, row=3).value = 999 wb.save(fn) # 若給予不同檔名代表另存新檔的意思 ``` ## 顯示最大、最小 欄數、列數 ```python= import openpyxl fn = 'test.xlsx' wb = openpyxl.load_workbook(fn) wb.active = 0 ws = wb.active print('儲存格 欄名', ws['A1'].column) print('儲存格 列名', ws['A1'].row) print('儲存格名', ws['A1'].coordinate) print('工作表有資料最大欄數', ws.max_column) print('工作表有資料最小欄數', ws.min_column) print('工作表有資料最大列數', ws.max_row) print('工作表有資料最小列數', ws.min_row) ``` ## 循欄列印 & 循列列印 ```python= import openpyxl fn = 'test.xlsx' wb = openpyxl.load_workbook(fn, data_only=True) # 要excel開啟才可以看到值,否則會顯示None wb.active = 0 ws = wb.active for cell in list(ws.columns)[1]: print(cell.value) print() for cell in list(ws.rows)[1]: print(cell.value) ``` ## 欄名 vs 欄數 轉換 ```python= import openpyxl from openpyxl.utils import get_column_letter, column_index_from_string fn = 'test.xlsx' wb = openpyxl.load_workbook(fn, data_only=False) # 要excel開啟才可以看到值,否則會顯示None wb.active = 0 ws = wb.active for i in range(1, ws.max_column+1): print(i, ' = ', get_column_letter(i)) print("A = ", column_index_from_string('A')) print("B = ", column_index_from_string('B')) ``` ## 讀取指定區域內容 ```python= import openpyxl from openpyxl.utils import get_column_letter, column_index_from_string fn = 'test.xlsx' wb = openpyxl.load_workbook(fn, data_only=False) # 要excel開啟才可以看到值,否則會顯示None wb.active = 0 ws = wb.active for row in ws['A2':'D5']: for cell in row: print(cell.value, end=' ') print() ``` ## 新增工作表 & 修改工作表名稱 ```python= import openpyxl from openpyxl.utils import get_column_letter, column_index_from_string fn = 'test.xlsx' wb = openpyxl.load_workbook(fn, data_only=False) # 要excel開啟才可以看到值,否則會顯示None wb.active = 0 ws = wb.active ws.title = 'hello' wb.create_sheet('新工作表') wb.save(fn) ``` ## 新增、修改、刪除工作表 ```python= import openpyxl fn = 'test.xlsx' wb = openpyxl.load_workbook(fn) wb.active = 0 ws = wb.active # 新增工作表,若名稱已經存在則原本名稱之後加數字 wb.create_sheet(title='amos') # 修改工作表 wb['amos'].title = 'carol' # 刪除工作表 wb.remove(wb['carol']) wb.save(fn) ``` ---- ## ```python= import openpyxl fn = 'test5.xlsx' wb = openpyxl.load_workbook(fn) ws = wb['hi'] for cell in ws['C']: # 讀取C欄所有資料,並列印出來 print(cell.value) for cell in ws['2']: # 讀取第2列所有資料,並列印出來 print(cell.value) ``` ## 合併、解除合併儲存格 ```python= import openpyxl fn = 'test.xlsx' wb = openpyxl.load_workbook(fn) ws = wb.active # ws.merge_cells('A5:D9') # ws.unmerge_cells('A5:D9') # or equivalently # ws.merge_cells(start_row=5, start_column=1, end_row=9, end_column=4) ws.unmerge_cells(start_row=5, start_column=1, end_row=9, end_column=4) wb.save(fn) ``` ## 插入圖片 ```python= import openpyxl from openpyxl.drawing.image import Image fn = 'test.xlsx' wb = openpyxl.load_workbook(fn) ws = wb.active img = Image('logo.png') ws.add_image(img, 'B5') wb.save(fn) ``` ## 建立大綱並折疊 ```python= import openpyxl from openpyxl.drawing.image import Image fn = 'test.xlsx' wb = openpyxl.load_workbook(fn) ws = wb.active ws.column_dimensions.group('A','D', hidden=True) ws.row_dimensions.group(1,10, hidden=True) wb.save(fn) ``` ## 改變字體 & 加上註解 ```python= import openpyxl from openpyxl.styles import Font from openpyxl.comments import Comment fn = 'test.xlsx' wb = openpyxl.load_workbook(fn) ws = wb.active ws['A1'].font = Font(name='Courier', size=36, color='EF0A1D') ws['A2'].comment = Comment(text="這是註解", author="Amos") print(ws['A2'].comment.text) print(ws['A2'].comment.author) ws['A2'].comment = None # 取消註解 wb.save(fn) ``` ## 新增/刪除 欄、列 ```python= import openpyxl from openpyxl.styles import Font fn = 'test.xlsx' wb = openpyxl.load_workbook(fn) ws = wb.active # ws.insert_rows(1) # ws.insert_cols(1, 2) ws.delete_rows(1, 2) ws.delete_cols(1, 2) wb.save(fn) ``` ## 畫統計圖(openpyxl範例) [官方範例](https://openpyxl.readthedocs.io/en/stable/charts/introduction.html) ```python= from openpyxl import Workbook from openpyxl.chart import BarChart, Series, Reference wb = Workbook(write_only=True) ws = wb.create_sheet() rows = [ ('Number', 'Batch 1', 'Batch 2'), (2, 10, 30), (3, 40, 60), (4, 50, 70), (5, 20, 10), (6, 10, 40), (7, 50, 30), ] for row in rows: ws.append(row) chart1 = BarChart() chart1.type = "col" chart1.style = 10 chart1.title = "Bar Chart" chart1.y_axis.title = 'Test number' chart1.x_axis.title = 'Sample length (mm)' data = Reference(ws, min_col=2, min_row=1, max_row=7, max_col=3) cats = Reference(ws, min_col=1, min_row=2, max_row=7) chart1.add_data(data, titles_from_data=True) chart1.set_categories(cats) chart1.shape = 4 ws.add_chart(chart1, "A10") from copy import deepcopy chart2 = deepcopy(chart1) chart2.style = 11 chart2.type = "bar" chart2.title = "Horizontal Bar Chart" ws.add_chart(chart2, "G10") chart3 = deepcopy(chart1) chart3.type = "col" chart3.style = 12 chart3.grouping = "stacked" chart3.overlap = 100 chart3.title = 'Stacked Chart' ws.add_chart(chart3, "A27") chart4 = deepcopy(chart1) chart4.type = "bar" chart4.style = 13 chart4.grouping = "percentStacked" chart4.overlap = 100 chart4.title = 'Percent Stacked Chart' ws.add_chart(chart4, "G27") wb.save("bar.xlsx") ``` ## 鎖定、解除鎖定 ```python= import openpyxl from openpyxl.styles import Alignment fn = 'test5.xlsx' wb = openpyxl.load_workbook(fn) ws = wb.active # ws.freeze_panes = 'B2' ws.freeze_panes = None wb.save(fn) ``` ## 設定日期格式 ```python= import openpyxl import datetime workbook = openpyxl.load_workbook("sample.xlsx") sheet = workbook['BBB'] sheet['A1'] = datetime.datetime(2010, 7, 21) # sheet['A1'].number_format = 'yyyy-mm-dd h:mm:ss' # sheet['A1'].number_format = 'yyyy-mm-dd' sheet['A1'].number_format = 'dd-mm-yyyy' workbook.save("sample.xlsx") ``` ## 設定公式 ```python= import openpyxl import datetime workbook = openpyxl.load_workbook("sample.xlsx") sheet = workbook['BBB'] sheet['A1'] = 6 sheet['A2'] = 10 sheet["A3"] = "=SUM(A1:A2)" workbook.save("sample.xlsx") ``` ## 移動資料 ```python= import openpyxl wb = openpyxl.load_workbook('sample.xlsx') ws = wb.active ws.move_range("D4:F10", rows=-1, cols=2) wb.save('sample.xlsx') ``` ## 參考資料 [HTML Color Codes](https://html-color-codes.info/)