GUI拆分Excel

  1. # -*- encoding: utf-8 -*-
  2. """
  3. @Author:暗香彻骨.沐之杰 (Addis)
  4. @Contact : qyx01@qq.com
  5. @Time: 2022/3/8 14:02
  6. @Software: PyCharm
  7. @File: 文件处理v1.3.py
  8. @Description: 可以将一个Excel工作簿中的多个工作表拆分成多个工作簿,按照指定字段
  9. pip install pyinstaller, pyinstaller -F -w
  10. """
  11. import os
  12. import pathlib
  13. import pandas as pd
  14. from openpyxl import load_workbook
  15. import ttkbootstrap as ttk
  16. from tkinter.filedialog import askdirectory
  17. from ttkbootstrap.constants import *
  18. from ttkbootstrap.dialogs import MessageDialog
  19. from ttkbootstrap.icons import Icon
  20. from ttkbootstrap.scrolled import ScrolledText
  21. from ttkbootstrap.tooltip import ToolTip
  22. from tkinter.filedialog import askopenfilename
  23. def show_dialog(msg, **kwargs):
  24. md = MessageDialog(title="警告!", message=msg, buttons=["OK:primary"],
  25. icon=Icon.error,
  26. alert=True,
  27. )
  28. if "position" in kwargs:
  29. position = kwargs.pop("position")
  30. else:
  31. position = None
  32. md.show()
  33. class FileHandling(ttk.Frame):
  34. def __init__(self, master):
  35. super().__init__(master, padding=15)
  36. self.suffix_entry = None
  37. self.fields_combox = None
  38. self.sheets_combox = None
  39. self.pack(fill=BOTH, expand=YES)
  40. _path = pathlib.Path().absolute().as_posix()
  41. self.path_var = ttk.StringVar(value=_path)
  42. self.term_var = ttk.StringVar(value='md')
  43. self.filename = ttk.StringVar()
  44. # 目标文件
  45. self.file_path = None
  46. # 输出文件路径
  47. self.out_path = None
  48. self.sheets_data = []
  49. self.fields_data = []
  50. # header and labelframe option container
  51. option_text = "操作区域"
  52. self.option_lf = ttk.Labelframe(self, text=option_text, padding=15)
  53. self.option_lf.pack(fill=X, expand=YES, anchor=N)
  54. self.create_path_row()
  55. self.create_file_row()
  56. self.create_textbox()
  57. self.create_combox_row()
  58. self.create_suffix_row()
  59. self.create_author_info()
  60. def create_path_row(self):
  61. """添加该组件 to labelframe"""
  62. path_row = ttk.Frame(self.option_lf)
  63. path_row.pack(fill=X, expand=YES)
  64. path_lbl = ttk.Label(path_row, text="路径:", width=8)
  65. path_lbl.pack(side=LEFT, padx=(15, 0))
  66. path_entry = ttk.Entry(path_row, bootstyle="info", textvariable=self.path_var)
  67. path_entry.pack(side=LEFT, fill=X, expand=YES, padx=5)
  68. browse_btn = ttk.Button(master=path_row, text="Path", command=self.on_path, bootstyle="info",
  69. width=8)
  70. browse_btn.pack(side=LEFT, padx=5)
  71. ToolTip(path_entry, text="该路径用于保存拆分后的文件")
  72. def create_file_row(self):
  73. """添加该组件 to labelframe"""
  74. file_row = ttk.Frame(self.option_lf)
  75. file_row.pack(fill=X, expand=YES, pady=15)
  76. file_lbl = ttk.Label(file_row, text="文件:", width=8)
  77. file_lbl.pack(side=LEFT, padx=(15, 0))
  78. file_entry = ttk.Entry(file_row, bootstyle="info", textvariable=self.filename)
  79. file_entry.pack(side=LEFT, fill=X, expand=YES, padx=5)
  80. browse_btn = ttk.Button(master=file_row, text="File", command=self.open_file, bootstyle="info",
  81. width=8)
  82. browse_btn.pack(side=LEFT, padx=5)
  83. def create_combox_row(self):
  84. """添加该组件 to labelframe"""
  85. combox_row = ttk.Frame(self.option_lf)
  86. combox_row.pack(fill=X, expand=YES, pady=15)
  87. sheets_combox_lbl = ttk.Label(combox_row, text="工作表:", width=8)
  88. sheets_combox_lbl.pack(side=LEFT, padx=(15, 0))
  89. self.sheets_combox = ttk.Combobox(combox_row, values=self.sheets_data, state="readonly", bootstyle="info")
  90. self.sheets_combox.pack(side=LEFT, padx=5)
  91. self.sheets_combox.bind('<<ComboboxSelected>>', self.sheet_selected)
  92. fields_combox_lbl = ttk.Label(combox_row, text="字段名:", width=8)
  93. fields_combox_lbl.pack(side=LEFT, padx=(15, 0))
  94. self.fields_combox = ttk.Combobox(combox_row, values=self.fields_data, state="readonly", bootstyle="info")
  95. self.fields_combox.pack(side=LEFT, padx=5)
  96. def create_suffix_row(self):
  97. """添加该组件 to labelframe"""
  98. suffix_row = ttk.Frame(self.option_lf)
  99. suffix_row.pack(fill=X, expand=YES, pady=15)
  100. suffix_lbl = ttk.Label(suffix_row, text="后缀名:", width=8)
  101. suffix_lbl.pack(side=LEFT, padx=(15, 0))
  102. self.suffix_entry = ttk.Entry(suffix_row, bootstyle="info")
  103. self.suffix_entry.pack(side=LEFT, fill=X, padx=5)
  104. Start_but = ttk.Button(master=suffix_row, text="开始", command=self.on_start, bootstyle="primary", width=8)
  105. Start_but.pack(side=RIGHT, fill=X, padx=5)
  106. def create_textbox(self):
  107. """Create and add the widget elements"""
  108. style = ttk.Style()
  109. self.textbox = ScrolledText(
  110. master=self,
  111. highlightcolor=style.colors.primary,
  112. highlightbackground=style.colors.border,
  113. highlightthickness=1,
  114. autohide=True
  115. )
  116. self.textbox.pack(fill=BOTH)
  117. default_txt = "点击Path、File,然后开始拆分Excel文件吧!"
  118. self.textbox.insert(END, default_txt + '\n')
  119. def create_author_info(self):
  120. author_info = ttk.Label(master=self, text="@Copyright 沐之杰.Addis Email:qyx01@qq.com")
  121. author_info.pack(side=RIGHT, padx=(15, 0))
  122. version_info = ttk.Label(master=self, text="Version:1.3")
  123. version_info.pack(side=RIGHT, padx=(15, 15))
  124. """ 方法区 """
  125. def insert_log(self, log, *args):
  126. self.textbox.insert(END, log + '\n')
  127. def on_path(self):
  128. """输出文件路径 for directory browse"""
  129. out_path = askdirectory(title="Browse directory")
  130. if out_path:
  131. self.path_var.set(out_path) # 文本框
  132. self.out_path = out_path
  133. def on_start(self):
  134. file_path = self.file_path
  135. out_path = self.out_path
  136. filepath_is = os.path.exists(out_path)
  137. if filepath_is:
  138. if len(out_path) == 0:
  139. show_dialog(msg="未选择目标路径!")
  140. return
  141. elif len(file_path) == 0:
  142. show_dialog(msg="未选择目标文件!")
  143. return
  144. self.operate_excel()
  145. else:
  146. show_dialog(msg="目标路径错误!")
  147. return
  148. def open_file(self):
  149. file_path = askopenfilename(title='选择Excel文件',
  150. filetypes=[('Excel', '*.xlsx'), ('All Files', '*')])
  151. if not file_path:
  152. show_dialog("未选择文件!")
  153. return
  154. self.file_path = file_path
  155. self.filename.set(file_path)
  156. # 读取 excel文件中的sheetname
  157. excel_data = pd.read_excel(file_path, None)
  158. list_sheet = list(excel_data.keys())
  159. # list_sheet = list(excel_data)
  160. # print(list(excel_data))
  161. # print(list_sheet)
  162. self.sheets_name(list_sheet) # 方法
  163. # 工作表名
  164. def sheets_name(self, list_sheet):
  165. self.sheets_data = list_sheet
  166. self.sheets_combox["values"] = self.sheets_data
  167. self.sheets_combox.current(0)
  168. # 工作表名-选择
  169. def sheet_selected(self, *args):
  170. sheets_name = self.sheets_combox.get()
  171. print(sheets_name)
  172. df = pd.read_excel(self.file_path, sheet_name=sheets_name, dtype=str)
  173. # field_name = list(df)
  174. print(list(df))
  175. self.fields_data = list(df)
  176. self.fields_name(list(df))
  177. # 字段名
  178. def fields_name(self, field_name):
  179. # field_name = self.field_name()
  180. fields_data = field_name
  181. self.fields_combox["values"] = fields_data
  182. self.fields_combox.current(0)
  183. # 字段名-选择
  184. def field_selected(self, *args):
  185. self.field_name = self.fields_combox.get()
  186. log = "选择了字段:" + self.field_name
  187. self.insert_log(log)
  188. # --------------- 读取多个工作表 -----------------
  189. def operate_excel(self, *args):
  190. markname = str(self.suffix_entry.get())
  191. out_path = self.out_path + '\\'
  192. input_sheet_name = self.sheets_combox.get()
  193. input_separation_fieldName = self.fields_combox.get()
  194. print("文件:", self.file_path)
  195. print("后缀名:", markname)
  196. print("输出路径:", out_path)
  197. print("工作表:", input_sheet_name)
  198. print("字段名:", input_separation_fieldName)
  199. # excel_data = pd.read_excel(self.file_path, None)
  200. # list_sheet = list(excel_data.keys())
  201. # print("工作表:", list_sheet)
  202. # input_sheet_name = self.sheets_data
  203. input_sheet_name = input_sheet_name.split(',')
  204. circulation = 0
  205. for only_sheet in input_sheet_name:
  206. circulation += 1
  207. print(only_sheet)
  208. data = pd.read_excel(self.file_path, sheet_name=only_sheet, dtype=str)
  209. rows = data.shape[0] # 获取行数 shape[1]获取列数
  210. department_list = []
  211. # print(data.columns)
  212. # print(input_separation_fieldName)
  213. print("总计 %s 行记录。" % rows)
  214. for i in range(rows):
  215. temp = data[input_separation_fieldName][i]
  216. if temp not in department_list:
  217. department_list.append(temp) # 分类存在一个列表中
  218. # 写入Excel
  219. if circulation == 1:
  220. for department in department_list:
  221. new_df = pd.DataFrame()
  222. for i in range(0, rows):
  223. if data[input_separation_fieldName][i] == department:
  224. new_df = pd.concat([new_df, data.iloc[[i], :]], axis=0, ignore_index=True)
  225. new_df.to_excel(out_path + str(department) + markname + ".xlsx",
  226. sheet_name=only_sheet,
  227. index=False) # 存成一个新excel
  228. # writer_file = pd.ExcelWriter(file_path + '多工作表.xlsx') # 利用pd.ExcelWriter()存多张sheets
  229. # print(circulation)
  230. elif circulation >= 1:
  231. for department in department_list:
  232. output_excel = pd.ExcelWriter(out_path + str(department) + markname + ".xlsx")
  233. book = load_workbook(output_excel)
  234. new_df = pd.DataFrame()
  235. for i in range(0, rows):
  236. if data[input_separation_fieldName][i] == department:
  237. new_df = pd.concat([new_df, data.iloc[[i], :]], axis=0, ignore_index=True)
  238. # new_df.to_excel(output_excel, sheet_name=only_sheet,engine='openpyxl', index=False) # 注意加上index=FALSE 去掉index列
  239. # output_excel.save()
  240. with pd.ExcelWriter(self.output_excel, engine='openpyxl') as writer: # doctest: +SKIP
  241. writer.book = book
  242. new_df.to_excel(writer, sheet_name=only_sheet, index=False)
  243. else:
  244. print("\033[31;0m Error!")
  245. print("End")
  246. log = "成功:" + "总计 %s 行记录。" % rows
  247. self.insert_log(log)
  248. if __name__ == '__main__':
  249. app = ttk.Window(title="文件处理", themename="litera")
  250. FileHandling(app)
  251. app.mainloop()

API请求

def get_url_batch(address, lng='', lat=''):
    headers = {
        'User-Agent': 'Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19',
        "Content-Type": "application/json",
        "AppKey": "915610589609328640"
    }
    # 互联网url
    # url = ""
    # 政务外网url
    url = ""
    # 需要的参数
    params = {
        "page": 1,
        "limit": 10,
        "address": address,
    }
    try:
        r = requests.post(url, json=params, headers=headers)
        # print(r.text)
        res_json = json.loads(r.text)
        res_data = res_json["data"]
        # print(res_data)
        # 打印序号,先用global关键字变成一个全局变量
        global serialNumber
        serialNumber += 1
        time_now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        if len(res_data["rows"]) > 0:
            print(serialNumber, res_data["rows"][0])
            address = res_data["rows"][0]["address"]
            lat = res_data["rows"][0]["lat"]
            lng = res_data["rows"][0]["lng"]

            res = [address, lng, lat, time_now]

            # res_dict = {
            #     "province": res_data["rows"][0]["province"],
            #     "city": res_data["rows"][0]["city"],
            #     "town": res_data["rows"][0]["town"],
            #     "address": res_data["rows"][0]["address"],
            #     "lat": res_data["rows"][0]["lat"],
            #     "lng": res_data["rows"][0]["lng"]
            # }
            # print(res_dict)
            return res

        else:
            print(serialNumber, res_data["rows"])
            address = ""
            lat = ""
            lng = ""
            res = [address, lng, lat, time_now]
            return res
    except Exception as e:
        print(e)
        address = address
        lat = "异常"
        lng = "异常"
        res = [address, lng, lat, time_now]
        return res

def read_excel_v2():
    """
    返回多列更新到Excel
    @return:
    """
    df = pd.read_excel(r'../../../data_static/files/excel/地址获取经纬度.xlsx', sheet_name="结果")
    # df["标准地址"] = df["地址"].apply(lambda x: get_url(x))  # 将返回结果直接保存在新的一列
    df[["标准地址", "lng", "lat", "时间"]] = df.apply(lambda x: get_url_batch(x['地址']), axis=1, result_type='expand')
    # df[['lng_', 'lat_']] = df.apply(lambda x: bd09_to_wgs84(x['lng'], x['lat']), axis=1, result_type='expand')

    # 获取当前日期作为文件名的后缀
    time_now = datetime.now().strftime('%Y-%m-%d')
    out_file = r"../../../data_static/files/excel/地址获取经纬度 {_time}.xlsx".format(_time=time_now)
    df.to_excel(out_file, sheet_name='结果', index=False)