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文件,否则会报如下错误:
正常效果: