1 背景
因爲某些原因,我們的Excel裏會放入一些圖片鏈接,但查看的時候需要一個個點開,通過瀏覽器顯示,非常麻煩。
我們可以通過python的openpyxl這個庫來解決此問題,一鍵替換所有鏈接爲圖片。
2 環境
Python 3.7.3 64-bit
openpyxl 3.0.0 (用於操作Excel)
requests 2.22.0 (用於下載圖片)
validators 0.14.1 (用於校驗文本是否是鏈接)
3 openpyxl
wb = openpyxl.load_workbook(path) # 加載Excel文件
sheet_names = wb.sheetnames # 獲取Excel的sheet列表
sheet = wb[sheet_name] # 指定sheet
row_num = sheet.max_row # 獲取sheet行數
column_num = sheet.max_column # 獲取sheet列數
for row in sheet.rows: # 遍歷sheet所有行
for column in sheet.columns: # 遍歷sheet所有列
for row in sheet.rows: # 遍歷sheet數據單元格
for cell in row:
cell_value = cell.value # 單元格值
cell_row = cell.row # 單元格所在行索引
cell_column = cell.column # 單元格所在列索引
cell_column_letter = openpyxl.utils.get_column_letter(cell.column) # 單元格所在列名稱
cell_coordinate = cell.coordinate # 單元格座標
sheet.row_dimensions[cell_row].height = IMG_CELL_HEIGHT # 設置行高
sheet.column_dimensions[cell_column_letter].width = IMG_CELL_WIDTH # 設置列寬
img = openpyxl.drawing.image.Image(img_path)
sheet.add_image(img, cell_coordinate) # 往Excel裏嵌入圖片
wb.save(filename=path_excel_with_img) # 保存Excel
4 主要代碼
def is_img_url(self, value: str):
"""檢測單元格值是否是圖片鏈接
"""
if value.startswith("=HYPERLINK"): value = value[12:-2] # 去掉excel超鏈接函數
is_img_url = False
if validators.url(value): # 判斷是否是url
for img_ext in self.img_ext:
if value.lower().endswith(img_ext): # 判斷是否是圖片文件後綴名
is_img_url = True
break
return is_img_url, value
def download_img(self, img_url, sheet_name=None, coordinate=None, timeout=15):
"""圖片下載
:param img_url: 圖片鏈接
:param sheet_name: ExcelSheet名稱
:param coordinate: Excel單元格座標
:param timeout: 圖片下載超時時間
"""
img_path = self.img_url_to_path(img_url) # 圖片保存地址
if os.path.exists(img_path): # 判斷圖片是否已經存在
self.stdout(sheet_name, coordinate, img_url, self.IMG_DOWNLOAD_EXISTS)
else:
self.check_and_mkdir(path=img_path) # 判斷保存圖片的文件夾是否存在,不存在則創建
r = requests.get(img_url, timeout=timeout) # 發起HTTP請求
if not r.content[:4] == b'\xff\xd8\xff\xe0': # 判斷返回內容是否是圖片格式
self.stdout(sheet_name, coordinate, img_url, self.IMG_DOWNLOAD_ERROR, self.IMG_URL_ERROR)
return False
with open(img_path, "wb") as f: # 保存圖片至本地
f.write(r.content)
self.stdout(sheet_name, coordinate, img_url, self.IMG_DOWNLOAD_DONE)
return True
def add_img_of_sheet(self, sheet_name):
"""Excel中添加圖片
:param sheet_name: Sheet名稱
"""
sheet = self.wb[sheet_name] # 指定Sheet
for row in sheet.rows: # 遍歷所有行
for cell in row: # 遍歷單元格
cell_value = str(cell.value) # 單元格值
is_img_url, img_url = self.is_img_url(cell_value)
if is_img_url: # 如果單元格存放的是圖片鏈接
img_path = self.img_url_to_path(img_url) # 獲取圖片本地保存地址
if os.path.exists(img_path): # 判斷本地圖片是否存在
try:
img = openpyxl.drawing.image.Image(img_path) # 加載圖片
img.height = self.IMG_HEIGHT # 設置圖片高度
img.width = self.IMG_WIDTH # 設置圖片寬度
sheet.add_image(img, cell.coordinate) # 嵌入圖片
sheet.row_dimensions[cell.row].height = self.IMG_CELL_HEIGHT # 設置行高
column_letter = openpyxl.utils.get_column_letter(cell.column) # 獲取列名
sheet.column_dimensions[column_letter].width = self.IMG_CELL_WIDTH # 設置列寬
cell.alignment = openpyxl.styles.Alignment(wrapText=True) # 設置單元格屬性 - 自動換行
except Exception as e:
print_exc() # 打印詳細錯誤
self.img_add_failed[img_url] = (sheet_name + " " + cell.coordinate, str(e)) # 記錄錯誤信息
self.stdout(sheet_name, cell.coordinate, img_url, str(e))
else:
self.img_add_failed[img_url] = (sheet_name + " " + cell.coordinate, self.IMG_DOWNLOAD_NOT_EXISTS)
self.stdout(sheet_name, cell.coordinate, img_url, self.IMG_DOWNLOAD_NOT_EXISTS)
5 最終效果
點擊Trans菜單下的IMG to Excel選項,一鍵將Excel中的圖片鏈接轉化爲圖片,首先需要複製Excel文件,否則會報如下錯誤:
正常效果:
6 源碼地址
項目代碼在github上:https://github.com/TheUncleWhoGrowsBeans/tkGo