Choose path to download file .

本文详细阐述了如何配置和实现数据下载路径的功能,包括使用文件保存对话框获取用户选择的路径,以及通过GUI下载功能将数据从服务器下载到指定目录。文章还介绍了在下载过程中可能出现的各种异常情况及其处理方式,确保数据下载过程的稳定性和安全性。
"Definition of data for get download path
DATA : fullpath       TYPE                   string,
       filename       TYPE                   string,
       path           TYPE                   string,
       user_action    TYPE                   i,
       encoding       TYPE                   abap_encoding.
 
IF p_file IS INITIAL.
  CALL METHOD cl_gui_frontend_services=>file_save_dialog
    EXPORTING
      window_title         = 'Gui_Download Demo'
      with_encoding        = 'X'
      initial_directory    = 'D:\SAP'
    CHANGING
      filename             = filename
      path                 = path
      fullpath             = fullpath
      user_action          = user_action
      file_encoding        = encoding
    EXCEPTIONS
      cntl_error           = 1
      error_no_gui         = 2
      not_supported_by_gui = 3
      OTHERS               = 4.
 
  IF sy-subrc <> 0.
    EXIT.
  ENDIF.
 
  IF user_action <> cl_gui_frontend_services=>action_ok.
    EXIT.
  ENDIF.
 
ELSE.
  fullpath = p_file.
 
ENDIF.
 
CALL FUNCTION 'GUI_DOWNLOAD'
  EXPORTING
    filename                = fullpath
    filetype                = 'DAT'
  TABLES
    data_tab                = it_top             " download internal table
  EXCEPTIONS
    file_write_error        = 1
    no_batch                = 2
    gui_refuse_filetransfer = 3
    invalid_type            = 4
    no_authority            = 5
    unknown_error           = 6
    header_not_allowed      = 7
    separator_not_allowed   = 8
    filesize_not_allowed    = 9
    header_too_long         = 10
    dp_error_create         = 11
    dp_error_send           = 12
    dp_error_write          = 13
    unknown_dp_error        = 14
    access_denied           = 15
    dp_out_of_memory        = 16
    disk_full               = 17
    dp_timeout              = 18
    file_not_found          = 19
    dataprovider_exception  = 20
    control_flush_error     = 21
    OTHERS                  = 22.
IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
          WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
import os import requests import xlwings as xw from io import BytesIO from PIL import Image, ImageOps from tkinter import filedialog, messagebox, ttk import tkinter as tk from openpyxl import load_workbook from concurrent.futures import ThreadPoolExecutor, as_completed # 下载并保存单张图片(带验证,安全保存) def download_image(url, path): try: print(f"📥 正在下载图片:{url}") response = requests.get(url, timeout=10) img = Image.open(BytesIO(response.content)) img.verify() # 验证图片是否损坏 img = Image.open(BytesIO(response.content)) # 必须重新加载 with open(path, 'wb') as f: img.save(f, format='PNG') f.flush() os.fsync(f.fileno()) print(f"✅ 保存成功:{path}") return True except Exception as e: print(f"❌ 下载失败:{url},原因:{e}") return False # 多线程批量下载图片 def download_images_multithreaded(url_map, folder): downloaded = {} with ThreadPoolExecutor(max_workers=5) as executor: future_to_row = { executor.submit(download_image, url, os.path.join(folder, f"img_{row}.png")): row for row, url in url_map.items() } for future in as_completed(future_to_row): row = future_to_row[future] try: success = future.result() if success: downloaded[row] = os.path.join(folder, f"img_{row}.png") except Exception as e: print(f"❌ 第 {row} 行下载任务异常: {e}") return downloaded # 获取最大有内容的行数 def get_max_data_row(file_path, sheet_name, column_letter): wb = load_workbook(file_path, read_only=True) ws = wb[sheet_name] for row in reversed(range(1, ws.max_row + 1)): if ws[f"{column_letter}{row}"].value: return row return 0 # 处理单个Sheet的图片插入 def process_excel(file_path, sheet_name, column_letter, start_row, progress_widget=None, label_widget=None, max_img_width=200, max_img_height=200): import tempfile from PIL import Image # 兼容 Pillow 新旧版本的重采样参数 try: resample_method = Image.Resampling.LANCZOS except AttributeError: resample_method = Image.ANTIALIAS app = xw.App(visible=False) wb = app.books.open(file_path) ws = wb.sheets[sheet_name] sheet_folder = os.path.join("images", sheet_name) os.makedirs(sheet_folder, exist_ok=True) max_row = get_max_data_row(file_path, sheet_name, column_letter) # 收集下载链接 url_map = {} for row in range(start_row, max_row + 1): cell = ws.range(f"{column_letter}{row}") if cell.value: url_map[row] = cell.value # 多线程下载图片 downloaded_images = download_images_multithreaded(url_map, sheet_folder) for row in range(start_row, max_row + 1): if progress_widget: progress_value = row - start_row + 1 progress_widget["value"] = progress_value progress_widget.update() if label_widget: label_widget.config(text=f"正在处理 [{sheet_name}] 第 {row} 行 / 共 {max_row} 行") label_widget.update() if row in downloaded_images: img_path = os.path.abspath(downloaded_images[row]) print(f"🖼️ 正在插入图片:{img_path}(存在:{os.path.exists(img_path)})") try: cell = ws.range(f"{column_letter}{row}") left = cell.left top = cell.top img = Image.open(img_path) img_width, img_height = img.size # 计算缩放比例,保持图片比例 scale_ratio = min(max_img_width / img_width, max_img_height / img_height) new_width = int(img_width * scale_ratio) new_height = int(img_height * scale_ratio) resized_img = img.resize((new_width, new_height), resample_method) # 新建白底背景,尺寸固定为 max_img_width x max_img_height canvas = Image.new("RGB", (max_img_width, max_img_height), (255, 255, 255)) paste_x = (max_img_width - new_width) // 2 paste_y = (max_img_height - new_height) // 2 canvas.paste(resized_img, (paste_x, paste_y)) with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as temp_file: canvas.save(temp_file.name) temp_img_path = temp_file.name # 调整单元格宽高以匹配图片尺寸,增加10%的边距 cell_width = new_width * 0.14 * 1.1 # Excel列宽单位转换,增加10%边距 cell_height = new_height * 0.75 * 1.1 # Excel行高单位转换,增加10%边距 ws.range(f"{column_letter}{row}").column_width = cell_width ws.range(f"{column_letter}{row}").row_height = cell_height # 插入图片,并设置图片大小与调整后的单元格匹配 pic = ws.pictures.add( temp_img_path, left=left, top=top, width=new_width, height=new_height ) # 设置图片随单元格移动但不随单元格调整大小 pic.api.Placement = 1 # 1 = xlMove (图片随单元格移动) print(f"✅ 插入成功:[{sheet_name}] 第 {row} 行") os.remove(temp_img_path) except Exception as e: print(f"❌ 插入失败({sheet_name} 第 {row} 行):{e}") output_path = file_path.replace(".xlsx", f"_{sheet_name}_带图.xlsx") wb.save(output_path) wb.close() app.quit() return output_path # 批量处理多个sheet def batch_process(file_path, sheet_names, column_letter, start_row): results = [] total_sheets = len(sheet_names) for idx, sheet in enumerate(sheet_names, 1): progress_label.config(text=f"处理第 {idx}/{total_sheets} 个Sheet:{sheet}") progress_label.update() progress["value"] = 0 max_row = get_max_data_row(file_path, sheet, column_letter) progress["maximum"] = max_row - start_row + 1 if max_row >= start_row else 1 output = process_excel(file_path, sheet, column_letter, start_row, progress_widget=progress, label_widget=progress_label) results.append(output) return results # GUI逻辑 def start_process(): file_path = file_var.get() sheet_names_str = sheet_var.get() column_letter = column_var.get().upper() try: start_row = int(start_row_var.get()) except: messagebox.showerror("错误", "起始行必须是数字") return if not os.path.exists(file_path): messagebox.showerror("错误", "文件路径无效") return sheet_names = [s.strip() for s in sheet_names_str.split(",") if s.strip()] if not sheet_names: messagebox.showerror("错误", "请输入至少一个Sheet名称") return try: outputs = batch_process(file_path, sheet_names, column_letter, start_row) msg = "图片插入完成,生成文件列表:\n" + "\n".join(outputs) messagebox.showinfo("完成", msg) except Exception as e: messagebox.showerror("出错", str(e)) def choose_file(): file_path = filedialog.askopenfilename(filetypes=[("Excel 文件", "*.xlsx")]) file_var.set(file_path) # 创建图形界面 root = tk.Tk() root.title("Excel 图片插入工具") root.option_add("*Font", "SimHei 10") file_var = tk.StringVar() sheet_var = tk.StringVar(value="Sheet1") column_var = tk.StringVar(value="A") start_row_var = tk.StringVar(value="2") tk.Label(root, text="选择 Excel 文件:").grid(row=0, column=0, sticky='e', padx=10, pady=10) tk.Entry(root, textvariable=file_var, width=50).grid(row=0, column=1, padx=5, pady=10) tk.Button(root, text="浏览", command=choose_file).grid(row=0, column=2, padx=10, pady=10) tk.Label(root, text="Sheet 名称(多个用逗号分隔):").grid(row=1, column=0, sticky='e', padx=10, pady=10) tk.Entry(root, textvariable=sheet_var).grid(row=1, column=1, padx=5, pady=10) tk.Label(root, text="图片列(如 B):").grid(row=2, column=0, sticky='e', padx=10, pady=10) tk.Entry(root, textvariable=column_var).grid(row=2, column=1, padx=5, pady=10) tk.Label(root, text="起始行号(如 2):").grid(row=3, column=0, sticky='e', padx=10, pady=10) tk.Entry(root, textvariable=start_row_var).grid(row=3, column=1, padx=5, pady=10) tk.Button( root, text="开始处理", command=start_process, bg="#4CAF50", fg="white", font=("SimHei", 12, "bold"), width=15 ).grid(row=4, column=0, columnspan=3, pady=20) progress_label = tk.Label(root, text="") progress_label.grid(row=5, column=0, columnspan=3, pady=5) progress = ttk.Progressbar( root, orient="horizontal", length=400, mode="determinate" ) progress.grid(row=6, column=0, columnspan=3, pady=5) copyright_label = tk.Label( root, text="© 2025 Project Name: Excel图片插入工具 Author: songyuting. All rights reserved.", font=("SimHei", 8) ) copyright_label.grid(row=7, column=0, columnspan=3, pady=10, sticky='s') root.grid_rowconfigure(7, weight=1) root.grid_columnconfigure(1, weight=1) root.mainloop() 我需要保留不规则图片处理及保留图片清晰度的部分,使插入的每个图片的宽度和高度不超出单元格,我的目的是让图片随单元格变化大小及位置
06-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值