234 lines
9.9 KiB
Python
234 lines
9.9 KiB
Python
import os
|
|
import tkinter as tk
|
|
from tkinter import filedialog, messagebox, ttk
|
|
from openpyxl import Workbook, load_workbook
|
|
import requests
|
|
import json
|
|
from datetime import datetime
|
|
import sys # 导入sys模块
|
|
|
|
|
|
class ExcelSplitterApp:
|
|
def __init__(self, root):
|
|
self.root = root
|
|
self.root.title('接车宝项目数据拆分工具')
|
|
self.root.geometry('700x350')
|
|
self.create_widgets()
|
|
|
|
# 宜搭API配置
|
|
self.appKey = "ding5kqocon5s9oph5uq"
|
|
self.appSecret = "HL1jgsIIfLAC0eTH0A1m4mwxUDqbgsiPeCCGGE3ocM6qJBTIW7Ivt9drxF_Z4Kb_"
|
|
|
|
# 记录程序启动时的打开时间
|
|
self.processing_info = {} # 用于存储处理信息的字典
|
|
self.open_time = datetime.now()
|
|
self.processing_info['textField_m4gewm35'] = self.get_application_path() # 获取程序的绝对路径
|
|
self.processing_info['textField_m4gewm34'] = self.root.title() # 工具名称
|
|
self.processing_info['textField_m4gewm36'] = self.open_time.strftime('%Y-%m-%d %H:%M:%S') # 程序打开时间
|
|
|
|
def get_application_path(self):
|
|
"""根据是否为打包的exe文件,返回应用程序的绝对路径"""
|
|
if getattr(sys, 'frozen', False):
|
|
# 如果是打包的exe文件
|
|
return os.path.dirname(sys.executable)
|
|
else:
|
|
# 如果是普通的Python脚本
|
|
return os.path.dirname(os.path.abspath(__file__))
|
|
|
|
def create_widgets(self):
|
|
self.file_label = tk.Label(self.root, text='选择Excel文件(只支持xlsx文件):')
|
|
self.file_label.grid(row=0, column=0, padx=10, pady=10)
|
|
|
|
self.file_path_entry = tk.Entry(self.root, width=50)
|
|
self.file_path_entry.grid(row=0, column=1, padx=10, pady=10)
|
|
|
|
self.file_button = tk.Button(self.root, text='浏览...', command=self.open_file)
|
|
self.file_button.grid(row=0, column=2, padx=10, pady=10)
|
|
|
|
self.sheet_name_label = tk.Label(self.root, text='工作表名称:')
|
|
self.sheet_name_label.grid(row=1, column=0, padx=10, pady=10)
|
|
|
|
self.sheet_name_combo = ttk.Combobox(self.root, state='readonly')
|
|
self.sheet_name_combo.grid(row=1, column=1, padx=10, pady=10)
|
|
|
|
self.id_label = tk.Label(self.root, text='要作为主键的字段:')
|
|
self.id_label.grid(row=2, column=0, padx=10, pady=10)
|
|
|
|
self.id_combo = ttk.Combobox(self.root, state='readonly')
|
|
self.id_combo.grid(row=2, column=1, padx=10, pady=10)
|
|
|
|
self.a_label = tk.Label(self.root, text='要拆分的内容a:')
|
|
self.a_label.grid(row=3, column=0, padx=10, pady=10)
|
|
|
|
self.a_combo = ttk.Combobox(self.root, state='readonly')
|
|
self.a_combo.grid(row=3, column=1, padx=10, pady=10)
|
|
|
|
self.b_label = tk.Label(self.root, text='要拆分的内容b:')
|
|
self.b_label.grid(row=4, column=0, padx=10, pady=10)
|
|
|
|
self.b_combo = ttk.Combobox(self.root, state='readonly')
|
|
self.b_combo.grid(row=4, column=1, padx=10, pady=10)
|
|
|
|
self.delimiter_label = tk.Label(self.root, text='切割字符(注意符号中英文):')
|
|
self.delimiter_label.grid(row=5, column=0, padx=10, pady=10)
|
|
|
|
self.delimiter_entry = tk.Entry(self.root)
|
|
self.delimiter_entry.grid(row=5, column=1, padx=10, pady=10)
|
|
|
|
self.split_button = tk.Button(self.root, text='开始拆分', command=self.split_data)
|
|
self.split_button.grid(row=6, column=1, padx=10, pady=10)
|
|
|
|
def open_file(self):
|
|
file_name = filedialog.askopenfilename(title="选择Excel文件", filetypes=[("Excel Files", "*.xlsx")])
|
|
if file_name:
|
|
self.file_path_entry.delete(0, tk.END)
|
|
self.file_path_entry.insert(0, file_name)
|
|
self.load_sheets_and_headers(file_name)
|
|
|
|
def load_sheets_and_headers(self, file_path):
|
|
try:
|
|
wb = load_workbook(file_path, read_only=True)
|
|
sheets = wb.sheetnames
|
|
|
|
self.sheet_name_combo['values'] = sheets
|
|
if sheets:
|
|
self.sheet_name_combo.current(0)
|
|
self.load_headers(file_path, sheets[0])
|
|
|
|
self.sheet_name_combo.bind('<<ComboboxSelected>>',
|
|
lambda event: self.load_headers(file_path, self.sheet_name_combo.get()))
|
|
except Exception as e:
|
|
messagebox.showerror("错误", str(e))
|
|
|
|
def load_headers(self, file_path, sheet_name):
|
|
try:
|
|
wb = load_workbook(file_path, read_only=True)
|
|
ws = wb[sheet_name]
|
|
headers = [cell.value for cell in next(ws.iter_rows(min_row=1, max_row=1))]
|
|
|
|
self.id_combo['values'] = headers
|
|
self.a_combo['values'] = headers
|
|
self.b_combo['values'] = headers
|
|
|
|
if headers:
|
|
self.id_combo.current(0)
|
|
self.a_combo.current(0)
|
|
self.b_combo.current(0)
|
|
except Exception as e:
|
|
messagebox.showerror("错误", str(e))
|
|
|
|
def generateToken(self) -> str:
|
|
"""生成访问令牌"""
|
|
token_api = 'https://api.dingtalk.com/v1.0/oauth2/accessToken'
|
|
data = {
|
|
"appKey": self.appKey,
|
|
"appSecret": self.appSecret
|
|
}
|
|
response = requests.post(token_api, json=data)
|
|
if response.status_code == 200:
|
|
return response.json().get('accessToken')
|
|
else:
|
|
raise Exception(f"Failed to get token: {response.text}")
|
|
|
|
def forms_instances(self, token, formDataJson):
|
|
"""新建表单内容"""
|
|
api = 'https://api.dingtalk.com/v1.0/yida/forms/instances'
|
|
headers = {
|
|
"Content-Type": "application/json",
|
|
"x-acs-dingtalk-access-token": token
|
|
}
|
|
payload = {
|
|
"appType": "APP_TNVBVZ3K8G56HG03Z45Q",
|
|
"systemToken": "CH7669818R0WN18TYTYJ42PE6GY22WZN0BYWKD1",
|
|
"userId": "yida_pub_account", # 曹伟 id
|
|
"formUuid": "FORM-D60584CCEBDB4CEF8AA1CF81D4E50770KEMY",
|
|
"formDataJson": json.dumps(formDataJson)
|
|
}
|
|
response = requests.post(api, headers=headers, json=payload)
|
|
return response
|
|
|
|
def split_data(self):
|
|
file_path = self.file_path_entry.get()
|
|
sheet_name = self.sheet_name_combo.get()
|
|
delimiter_input = self.delimiter_entry.get()
|
|
id_input = self.id_combo.get()
|
|
a_input = self.a_combo.get()
|
|
b_input = self.b_combo.get()
|
|
|
|
start_time = datetime.now() # 记录处理开始时间
|
|
processing_info = {} # 用于存储处理信息的字典
|
|
|
|
try:
|
|
wb = load_workbook(file_path, data_only=True)
|
|
ws = wb[sheet_name]
|
|
|
|
headers = [cell.value for cell in next(ws.iter_rows(min_row=1, max_row=1))]
|
|
id_index = headers.index(id_input)
|
|
a_index = headers.index(a_input)
|
|
b_index = headers.index(b_input)
|
|
|
|
split_data = []
|
|
for row in ws.iter_rows(min_row=2, values_only=True):
|
|
projects = str(row[a_index]).split(delimiter_input) # 使用用户输入的字符切割项目
|
|
prices = str(row[b_index]).split(delimiter_input) # 使用用户输入的字符切割价格
|
|
|
|
for project, price in zip(projects, prices):
|
|
split_data.append((row[id_index], project, price))
|
|
|
|
# 创建新的工作簿来保存拆分后的数据
|
|
new_wb = Workbook()
|
|
new_ws = new_wb.active
|
|
new_ws.append([id_input, a_input, b_input])
|
|
for data in split_data:
|
|
new_ws.append(data)
|
|
|
|
# 保存拆分后的数据到新的Excel文件
|
|
file_dir = os.path.dirname(file_path)
|
|
file_name = os.path.basename(file_path)
|
|
output_path = os.path.join(file_dir, f"拆分_{file_name}")
|
|
new_wb.save(output_path)
|
|
|
|
# 收集处理信息
|
|
processing_info = {
|
|
'textField_m4gewm33': start_time.strftime('%Y-%m-%d %H:%M:%S'), # 处理开始时间
|
|
'textField_m4glr9fm': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), # 处理结束时间
|
|
'textField_m4glr9fn': str(datetime.now() - start_time), # 处理时长
|
|
'textField_m4glr9fo': os.path.abspath(file_path), # 处理的文件绝对路径
|
|
'textField_m4glr9fp': os.path.abspath(output_path), # 新文件保存的绝对路径
|
|
'textField_m4gewm38': True, # 是否处理成功
|
|
}
|
|
|
|
except Exception as e:
|
|
processing_info = {
|
|
'textField_m4gewm33': start_time.strftime('%Y-%m-%d %H:%M:%S'), # 处理开始时间
|
|
'textField_m4glr9fm': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), # 处理结束时间
|
|
'textField_m4glr9fn': str(datetime.now() - start_time), # 处理时长
|
|
'textField_m4glr9fo': os.path.abspath(file_path), # 处理的文件绝对路径
|
|
'textField_m4glr9fp': '', # 新文件保存的绝对路径
|
|
'textField_m4gewm38': f"处理失败:{str(e)}", # 是否处理成功
|
|
}
|
|
messagebox.showerror("失败", f"处理过程中发生了错误: {str(e)}")
|
|
finally:
|
|
self.processing_info.update(processing_info)
|
|
# 生成令牌并提交表单
|
|
token = self.generateToken()
|
|
response = self.forms_instances(token, self.processing_info)
|
|
if response.status_code == 200:
|
|
processing_info['form_submission_status'] = "提交成功"
|
|
else:
|
|
processing_info['form_submission_status'] = f"提交失败:{response.text}"
|
|
|
|
# 打印处理信息
|
|
print("处理信息:")
|
|
for key, value in processing_info.items():
|
|
print(f"{key}: {value}")
|
|
|
|
messagebox.showinfo("成功",
|
|
f"数据已成功拆分并保存至 {output_path}\n表单提交状态: {processing_info['form_submission_status']}")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
root = tk.Tk()
|
|
app = ExcelSplitterApp(root)
|
|
root.mainloop()
|