URLhttps://learnscript.net/zh-hant/office-programming/openpyxl/images/
    複製連結移至說明  範例

    如何使用 openpyxl 處理 Excel 影像?Image 物件介紹

    閱讀 9:45·字數 2926·更新 
    Youtube 頻道
    訂閱 375

    openpyxl Excel 影像物件 Image

    openpyxl套件的Image類別,屬於模組openpyxl.drawing.image,表示 Microsoft Excel 工作表中的影像。Image物件一般儲存在 Excel 工作表物件中,而不是儲存格物件,雖然影像可以將錨點設定到某一個儲存格。

    Image 類別相依於 pillow 套件

    要讓Image類別正常工作,需要安裝套件pillow,否則,openpyxl將無法讀取工作表中的影像,也無法新增影像至工作表。

    建立 Excel 影像

    如果你希望為 Excel 工作表新增影像,那麽需要首先建立Image物件,然後通過工作表物件的相關方法執行新增操作。

    Image(img)

    img 參數

    img參數一般是一個表示影像檔案路徑的字串,或一個實作了抽象基底類別os.PathLike的物件。

    create.py
    from openpyxl.drawing.image import Image
    
    # 建立一個 Image 物件 print(Image('python.png'))
    <openpyxl.drawing.image.Image object at >

    為 Excel 工作表新增影像

    WorksheetWriteOnlyWorksheet物件的add_image方法,可用於為 Excel 工作表新增影像,當然,這需要一個有效的Image物件。

    worksheet|writeonlyworksheet.add_image(img, anchor=None)

    img 參數

    img參數是一個Image物件,其對應的影像將被新增至工作表。

    anchor 參數

    anchor參數是一個表示儲存格位址的字串,相關的儲存格將作為被新增影像的錨點(影像將被定位至儲存格的左上角)。

    在下面的範例中,我們將影像新增至工作表Images,並設定其錨點為儲存格B2

    add.py
    # 建立唯寫活頁簿,並新增工作表 Images
    from openpyxl import Workbook
    wb = Workbook(True)
    ws = wb.create_sheet('Images')
    
    from openpyxl.drawing.image import Image
    # 將影像 python.png 新增至工作表,錨點為 B2 img = Image('python.png') ws.add_image(img, 'B2')
    wb.save('Add.xlsx')

    將同一個 Image 物件重複新增至同一個工作表物件可能會導致警告

    如果一個Image物件已經存在於某個工作表物件中,那麽再次將其新增至該工作表可能會產生警告,但這些警告不會影響影像的新增。

    如果你為同一個影像檔案建立多個Image物件,那麽將這些Image物件新增至某個工作表不會導致警告的出現,但可能導致儲存後的檔案過大,因為每個影像都會被儲存,即使他們是一樣的。

    在下面的範例中,我們反覆將Image物件新增到工作表Images,這導致了警告的產生。

    add_again.py
    # 建立唯寫活頁簿,並新增工作表 Images
    from openpyxl import Workbook
    wb = Workbook(True)
    ws = wb.create_sheet('Images')
    
    from openpyxl.drawing.image import Image
    # 建立一個 Image 物件,並新增至 Images img = Image('python.png') ws.add_image(img, 'A1') # 重複新增會產生警告,但不影響新增 ws.add_image(img, 'B2') ws.add_image(img, 'C3')
    wb.save('Again.xlsx')
    zipfile\__init__.py:: UserWarning: Duplicate name: 'xl/media/image3.png'

    不要將同一個 Image 物件新增至不同的工作表物件

    如果將同一個Image物件新增到不同的工作表物件中,那麽該Image物件所對應的影像僅能在一個工作表中正常顯示,其他工作表將無法載入該Image物件對應的影像。

    並且,在儲存 Excel 檔案之後,再次以非唯讀方式讀取儲存的 Excel 檔案,可能會導致例外狀況KeyError: "There is no item named 'xl/media/…' in the archive"

    在下面的範例中,我們首先將Image物件新增至工作表Images1,然後又將其新增至工作表Images2,這會導致工作表Images1中的影像無法正常載入。

    add_diff.py
    # 建立唯寫活頁簿,並新增工作表 Images1,Images2
    from openpyxl import Workbook
    wb = Workbook(True)
    ws1 = wb.create_sheet('Images1')
    ws2 = wb.create_sheet('Images2')
    
    from openpyxl.drawing.image import Image
    # 建立一個 Image 物件,並新增至 Images1 img = Image('python.png') ws1.add_image(img, 'A1') # 將 Image 物件新增至 Images2 ws2.add_image(img, 'B2')
    wb.save('Diff.xlsx')
    from openpyxl import load_workbook # ERROR 不能以非唯讀方式讀取 Diff.xlsx wb = load_workbook('Diff.xlsx')
    zipfile\__init__.py:: UserWarning: Duplicate name: 'xl/media/image2.png'

    KeyError: "There is no item named 'xl/media/image1.png' in the archive"

    取得,取代,刪除 Excel 工作表中的影像

    openpyxl套件的設計者似乎不希望開發人員可以取得或設定 Excel 工作表中的影像,因此,WorksheetWriteOnlyWorksheet物件擁有一個以_開頭的變數_images,該變數是一個包含Image物件的 Python 串列,每一個Image物件對應工作表中的一個影像。

    事實上,為WorksheetWriteOnlyWorksheet物件的_images串列新增Image物件,或者取代或刪除_images串列中的Image物件,等同於為工作表新增影像,或者取代或刪除工作表中的影像。當然,你可以將一個新的 Python 串列直接指派給WorksheetWriteOnlyWorksheet物件的_images變數,這將取代工作表中的所有影像。

    worksheet|writeonlyworksheet._images
    worksheet|writeonlyworksheet._images = images

    images 值

    images是一個 Python 串列,串列中的元素應該是Image物件。

    在下面的範例中,我們通過Worksheet物件的_images串列,對工作表中的影像進行了取代,刪除和新增。

    images.py
    # 讀取 Excel 檔案 Img.xlsx 中的工作表 Images
    from openpyxl import load_workbook
    wb = load_workbook('Img.xlsx')
    ws = wb['Images']
    
    from openpyxl.drawing.image import Image
    # 取得 Excel 工作表中的影像 print(f'一共 {len(ws._images)} 個影像')
    # 取代第一個影像 ws._images[0] = Image('imac-icon.png') # 刪除第二個影像 del ws._images[1] # 新增一個影像 ws._images.append(Image('python.png'))
    wb.save('NewImg.xlsx')
    一共 2 個影像

    取得和設定 Excel 影像的錨點

    Image物件的anchor變數,表示Image物件對應的 Excel 影像的錨點,該變數可能是一個字串,表示作為錨點的儲存格的位址,也可能是openpyxl套件的TwoCellAnchor物件,表示影像的顯示範圍。當你希望設定影像在工作表中的錨點時,可將表示儲存格位址的字串指派給Image物件的anchor變數。

    image.anchor
    image.anchor = anchor

    anchor 值

    anchor可以是表示儲存格位址的字串。

    TwoCellAnchor 物件

    上述TwoCellAnchor物件,可被Image物件用於表示影像的顯示範圍。TwoCellAnchor物件的_from特性的colrow變數,是影像錨點所對應的儲存格的欄索引和列索引,0表示第一欄或第一列。

    anchor.py
    # 讀取 Excel 檔案 Img.xlsx 中的工作表 Images
    from openpyxl import load_workbook
    wb = load_workbook('Img.xlsx')
    ws = wb['Images']
    
    for i in ws._images: # 取得 Excel 工作表中的影像的錨點 a = i.anchor print(type(a)) print(f'錨點:{a._from.col}{a._from.row}')
    # 設定新的錨點 i.anchor = 'E5'
    wb.save('Anchor.xlsx')
    <class 'openpyxl.drawing.spreadsheet_drawing.TwoCellAnchor'>
    錨點:0,0
    <class 'openpyxl.drawing.spreadsheet_drawing.TwoCellAnchor'>
    錨點:2,1

    取得 Excel 影像的原始大小

    Image物件的widthheight變數,表示Image物件對應的 Excel 影像的原始寬度和高度,這可能與影像在工作表中的實際顯示大小不同。

    image.width
    image.height

    在 Excel 檔案Img.xlsx中,工作表Images包含兩個顯示大小不同的影像,但其原始大小一致。

    size.py
    # 讀取 Excel 檔案 Img.xlsx 中的工作表 Images
    from openpyxl import load_workbook
    wb = load_workbook('Img.xlsx')
    ws = wb['Images']
    
    # 取得 Excel 工作表中的影像的原始大小 for i in ws._images: print(f'原始大小:{i.width}x{i.height}')
    原始大小:128x128
    原始大小:128x128

    取得 Excel 影像的格式

    Image物件的format變數是一個字串,表示Image物件對應的 Excel 影像的格式,如果無法得知影像的格式,那麽format變數保持其預設值png

    image.format

    在 Excel 檔案Img.xlsx中,工作表Chat包含兩個影像,他們的格式分別為pngsvg,但格式為svg的影像被識別為png格式。

    format.py
    # 讀取 Excel 檔案 Img.xlsx 中的工作表 Chat
    from openpyxl import load_workbook
    wb = load_workbook('Img.xlsx')
    ws = wb['Chat']
    
    # 取得 Excel 工作表中的影像的格式 for i in ws._images: print(f'格式:{i.format}')
    格式:png
    格式:png

    Image 物件的其他特性

    以下是Image物件的其他相關特性。

    ref 變數

    Image物件的ref變數表示影像的來源,他可能是表示影像檔案路徑的字串,也可能是包含影像資料的物件,比如一個_io.BytesIO物件。

    原始碼

    src/zh-hant/openpyxl/images·codebeatme/office-programming·GitHub