【tkGo】替换Excel里的图片链接为图片

1,849 阅读2分钟

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.com/TheUncleWho…