victory的博客

长安一片月,万户捣衣声

0%

一键更新Excel中的图表

场景: 小编每周都要更新最近12周的“生产订单周报”给老板,而且要对比最近两年相同周数的数据。主要是两张图,一张是“一周生产订单对比”,另一张是“各部门订单比例”。虽然在Excel表中建了数据透视表,但是每周都还是需要花时间进行一通凶猛的操作,才能搞定。可不可以每周一键更新,并得到这两张图呢?

阅读全文 »

生成器输出小于max_num的偶数或奇数

代码:

# 1.输出小于max_num的偶数或奇数
def odd(max_num):
    
    i = 1
    while i < max_num:
        if i % 2 == 0:  # if % 2 == 1可生成奇数
            yield i
        i += 1

g = odd(10)
for n in g:
    print(n)

# 2.输出任意个偶数或奇数
def odd():
i = 2
while i:
    if i % 2 == 0:  # if % 2 == 1可生成奇数
        yield i
    i += 1
g = odd()
for i in range(100):
    print(next(g))

生成器输出小于max_num的fibonacci数列

代码:

def feb(max_num):
    n_1 = 1
    n_2 = 1
    n = 0
    while n < max_num:
        if n == 0 or n == 1:
            yield 1
            n += 1
        else:
            yield n_1 + n_2
            new_n_2 = n_1
            n_1 = n_1 + n_2
            n_2 = new_n_2
            n += 1

g = feb(5)
for n in g:
    print(n)

生成器输出小于max_num的质数

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。
而且,创建一个包含成百上千完个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前
面几个元素,那后面绝大多数元素占用的空间都白白浪费了。生成器有效的解决了这个问题。

阅读全文 »

识别加密word文件

Python本身是难以识别word文件的加密状态的,那我们可以考虑利用程序在处理有密码的文档的时候的报错信息来进行处理。word文件有两种密码,一种是“打开密码”,另一种是“修改密码”。对于前者,若不输入正确的密码,是无法打开文件查看内容的;对于后者,即使不知道密码,还是可以用只读模式打开文件,查看内容并另存为新的文件的。
因此对于设置了“修改密码”的doc文件,并不影响用如下程序另存为docx文件。只是在另存之前,窗口会弹出如下对话框,我们只需要点击一下“只读”即可,程序就能正常运行下去。
如果设置了“打开密码”,程序在运行的时候也会弹出对话框,让输入密码。如果输入正确的密码,程序也是可以运行的;如果不知道密码或输入错误密码,则程序会出现如下的“com_error”错误。如果不知道密码,可以加入try..except..语句,让程序在except语句中将这个文件移动到名字为“有密码文件”的文件夹,以便后续处理。

阅读全文 »

分块拆分txt文件中的数据

代码:

# -*- coding:utf-8 -*-
# 读取txt文件中的数据
file = open("数据.txt")
lines = file.readlines()
# print(lines[:5])

data = {}  # 储存分割的数据
line_list = []  # 中转列表
last_id = "start"  # 数据分块标识
for line in lines:
    row_data = line.split(" ")  # 将一行数据按空格分隔
    ID = row_data[0]  # 获得ID
    if last_id == "start":  # 用于处理数据第一行
        line_list.append(line)  # 将第一行数据放入中转列表
    else:  # 不是第一行数据,则按如下执行
        if ID != last_id:  # 如果出现新的数据块
            if last_id in data:  # 新的数据块的ID已存在字典data中
                data[last_id].append(line_list)  # 将中转列表的数据添加到对应的ID中
            else:  # 新的数据快的ID不在字典data中
                data[last_id] = [line_list]  # 将上一个数据块加入对应的ID
            line_list = [line]  # 将中转列表清空,并放入新数据快的第一行数据
        else:  # 没出现新的数据块
            line_list.append(line)  # 将数据继续加入中转列表
    last_id = ID  # 每处理一行,将分块标识last_id更行为最新的ID

# 将最后一个文字块的数据放入字典
if last_id in data:
    data[last_id].append(line_list)
else:
    data[last_id] = [line_list]

# print(data['89031'])

# for i in data.keys():
#     for block in data[i]:
#         print(block)
#         print("- -"*50)


# 写入数据函数
def to_txt(filename, data_list):  # filename为写入文件的名字,data为要写入数据列表
    file = open("分块\\" + filename + '.txt', 'a')
    for i in range(len(data_list)):
        file.write(data_list[i])
    file.close()  # 保存数据并关闭


# 批量写入数据
for ID in data.keys():
    for i in range(len(data[ID])):
        to_txt(f"{ID}_{i+1}", data[ID][i])
        

数据.txt

Tkinter制作python程序的图形化界面

代码:

from os import listdir, getcwd
from xlrd import open_workbook, xldate
from datetime import datetime
from time import time, localtime, strftime
from openpyxl import Workbook
from openpyxl.styles import Border, Side, PatternFill, Font, GradientFill, Alignment
from tkinter import Tk, Entry, Button, Listbox, X, Y, END, Scrollbar, RIGHT, BOTTOM, HORIZONTAL
from tkinter.filedialog import askdirectory


class MainGUI():
    def __init__(self):
        myWindow = Tk()
        myWindow.title("领料记录汇总")
        # 设置窗口大小
        myWindow.geometry('590x400')
        myWindow.iconbitmap(getcwd() + "\\PO.ico")
        # 增加文本框
        self.input_entry = Entry(myWindow, highlightcolor='red', highlightthickness=1)
        self.input_entry.place(x=10, y=10, width=480, height=30)
        self.btn_in = Button(myWindow, text='输入文件目录', command=self.select_dir1, width=10, height=1)
        self.btn_in.place(x=500, y=10)

        self.output_entry = Entry(myWindow, highlightcolor='blue', highlightthickness=1)
        self.output_entry.place(x=10, y=50, width=480, height=30)
        self.btn_out = Button(myWindow, text='输出文件目录', command=self.select_dir2, width=10, height=1)
        self.btn_out.place(x=500, y=50)

        self.btn_run = Button(myWindow, text='执行汇总', width=10, height=1, command=self.Summary_data)
        self.btn_run.place(x=500, y=90)
        # 增加列表框
        self.result_show = Listbox(myWindow, bg='DarkSeaGreen')  # yscrollcommand = scroll_bar,
        self.result_show.place(x=10, y=130, width=570, height=260)
        self.sbY = Scrollbar(self.result_show, command=self.result_show.yview)  # 在列表框中增加Y轴滚动条
        self.sbY.pack(side=RIGHT, fill=Y)
        self.result_show.config(yscrollcommand=self.sbY.set)
        self.sbX = Scrollbar(self.result_show, command=self.result_show.xview, orient=HORIZONTAL)  # 在列表框中增加X轴滚动条
        self.sbX.pack(side=BOTTOM, fill=X)
        self.result_show.config(xscrollcommand=self.sbX.set)

        myWindow.mainloop()

    def select_dir1(self):
        self.input_entry.delete(0, END)
        self.input_entry.insert(0, askdirectory(initialdir="D:\\"))

    def select_dir2(self):
        self.output_entry.delete(0, END)
        self.output_entry.insert(0, askdirectory(initialdir="D:\\"))

    # 读取xls文件中的数据
    def Get_data(self, file):
        wb = open_workbook(file)  # 读取工作簿
        ws = wb.sheets()[0]  # 选第一个工作表
        data = {}
        for row in range(7, ws.nrows - 2):
            dept = ws.cell(2, 16).value  # 部门
            dept_id = ws.cell(3, 16).value  # 部门编号
            dt = ws.cell(row, 0).value  # 时间
            if type(dt) is float:
                date_time = xldate.xldate_as_datetime(dt, 0)
            else:
                date_time = datetime.strptime(dt, '%Y-%m-%d %H:%M:%S')
            business = ws.cell(row, 2).value  # 业务类型
            model = ws.cell(row, 3).value  # 品种
            qty = ws.cell(row, 4).value  # 数量
            unit_price = ws.cell(row, 6).value  # 单价
            price = ws.cell(row, 8).value  # 总价
            reward = ws.cell(row, 9).value  # 额外值
            discount = ws.cell(row, 11).value  # 调整
            balance = ws.cell(row, 13).value  # 剩余
            location = str(ws.cell(row, 15).value).strip()  # 库位
            operator = ws.cell(row, 17).value  # 操作员
            date = date_time.date()  # 日期
            time = date_time.time()  # 时间
            info_list = [dept, dept_id, date_time, business, model, qty, unit_price, price, reward, discount,
                         balance, location, operator, date, time]
            data.setdefault(date, [])  # 以日期为键
            if info_list[3] != "备注":  # 不要业务类型为“备注”的数据
                data[date].append(info_list)
        # 增加当日领取次数
        for key in data.keys():
            for i in data[key]:
                i.append(len(data[key]))

        return data

    def Get_file_path(self, path):
        files = []
        for file in listdir(path):
            if file.endswith(".xls"):  # 排除文件夹内的其它干扰文件
                files.append(path + "\\" + file)
        return files

    def Get_current_time(self):
        time_stamp = time()  # 当前时间的时间戳
        local_time = localtime(time_stamp)  #
        str_time = strftime('%Y-%m-%d %H.%M.%S', local_time)
        return str_time

    def Summary_data(self):
        thin = Side(border_style="thin", color="000000")  # 定义边框粗细及颜色
        title = ['部门', '部门编号', '时间', '业务类型', '品种', '数量', '单价', '金额', '额外值',
                 '调整', '剩余', '库位', '操作员', '领取日期', '领取时间', '领取次数']

        wb = Workbook()
        ws = wb.active

        ws.merge_cells("A1:P1")
        ws.cell(1, 1).value = "领料明细汇总表"
        ws.cell(1, 1).font = Font(name=u'黑体', bold=True, size=18)
        ws.row_dimensions[1].height = 22.2
        ws.cell(1, 1).alignment = Alignment(horizontal="center", vertical="center")
        ws.append(title)

        # 插入数据
        files = self.Get_file_path(self.input_entry.get())  # get()获取文本编辑框中的输入文件目录,并获取目录下的xls文件
        for file in files:
            data = self.Get_data(file)
            for key in data.keys():
                for i in data[key]:
                    ws.append(i)
            f = f"{file} 的内容已加入总表."  # 创建一个显示项
            self.result_show.insert("end", f)  # 将结果添加到列表框中

        # 设置字号,对齐,缩小字体填充,加边框
        # Font(bold=True)可加粗字体
        for row_number in range(2, ws.max_row + 1):
            for col_number in range(1, 17):
                c = ws.cell(row=row_number, column=col_number)
                c.font = Font(size=9)
                c.border = Border(top=thin, left=thin, right=thin, bottom=thin)
                c.alignment = Alignment(horizontal="left", vertical="center")

        col_name = list("ABCDEFGHIJKLMNOP")
        col_width = [8, 8, 16, 8, 16, 8, 8, 9.8, 8, 8, 8, 11, 8.3, 9, 8, 8]
        for i in range(len(col_name)):
            ws.column_dimensions[col_name[i]].width = col_width[i]

        ws.column_dimensions.group('I', 'K', hidden=True)
        ws.column_dimensions.group('N', 'O', hidden=True)

        wb.save(f"{self.output_entry.get()}\\领料明细汇总表{self.Get_current_time()}.xlsx")
        f = "-" * 100  # 创建分割线
        self.result_show.insert("end", f)  # 将分割线添加到列表框
        f = f"领料明细汇总表{self.Get_current_time()}.xlsx 已生成,请去输出文件夹查看."  # 创建一个显示项
        self.result_show.insert("end", f)  # 将结果添加到列表框
        f = " " * 100
        self.result_show.insert("end", f)  # 将以上空格添加到列表框


if __name__ == "__main__":
    MainGUI()

python程序打包

通常情况我们在pycharm中写的python程序只能在安装了python的电脑上运行,那么如何移植到其他电脑上也能运行呢?
我们可以将py文件打包成可执行程序(exe文件).

步骤:

1. pyinstaller库安装

pip install pyinstaller -i https://pypi.doubanio.com/simple/

2.打包

pyinstaller -D program.py ---> 打包成一个文件夹(默认操作)
pyinstaller -F program.py ---> 打包成单个可执行文件

程序运行后,会在目录生成一个文件:
1.program.spec(打包规则)
三个文件夹:
1.__pycache __(Python版本信息)
2.build(存储日志文件)
3.dist(储存可执行文件即相关的文件夹)
注:打包完成后,除了dist文件夹,其它都可以删除,没什么用。

3.将打包好的文件制作成一个安装文件

使用NSIS文件夹压缩器来制作安装文件。