库存分析实销-代码

本文介绍了如何使用Python的openpyxl和pandas库对Excel文件进行数据预处理,包括读取数据、修改工作表名、选择和删除列、格式设置(如边框、对齐和字体),以及数据处理(如计算汇总、填充缺失值和创建新列)。最后,文章还展示了如何应用格式规则,如颜色和百分比格式,以美化Excel报告。
摘要由CSDN通过智能技术生成

准备工作

导入包

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

引入依赖

from openpyxl import load_workbook
from openpyxl import styles
from openpyxl.styles import *
import pandas as pd
import string

原始数据的字段

部门名称	品牌名称	00-期初	01-进货	09-配货入	10-配退入	12-移仓入	18-零售退	01-进货退	07-配货出	08-配退出	11-移仓出	17-零售	22-调整	23-期末

数据读入

	file_path1 = './src/超级原始数据精修.xlsx'
    # 加载工作簿
    wb = load_workbook(file_path1)
    # 获取sheet页,修改第一个sheet页面为
    name1 = wb.sheetnames[0]
    ws1 = wb[name1]
    ws1.title = "销售明细"
    #销售明细
    df0 = pd.read_excel(file_path1, sheet_name='销售明细')

修改工作表名

def sheet_name_deal(file_path):
    wb = load_workbook(file_path)
    # 获取sheet页,修改第一个sheet页面名为销售明细
    name1 = wb.sheetnames[0]
    ws1 = wb[name1]
    ws1.title = "销售明细"
    wb.save(file_path)

创建文件

def create_excel(file_path):
    # 没有就创建
    if os.path.exists(file_path):
        print("文件已存在")
        print(file_path)
    else:
        # 创建一个新的 Excel 文件
        wb = Workbook()
        wb.save(file_path)

选择列

import pandas as pd

df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6], 'C': [7, 8, 9]})
df = df[['B', 'C']]

删除列

df.drop(['A', 'B'], axis=1, inplace=True)

现有列名

部门名称	品牌名称	00-期初	01-进货	09-配货入	10-配退入	12-移仓入	18-零售退	01-进货退	07-配货出	08-配退出	11-移仓出	17-零售	22-调整	23-期末

完整代码

from openpyxl import load_workbook
from openpyxl import Workbook
from openpyxl import styles
from openpyxl.styles import *
import openpyxl
import pandas as pd
import string
import re
import os
import numpy as np

def create_excel(file_path):
    # 没有就创建
    if os.path.exists(file_path):
        print("文件已存在")
        print(file_path)
    else:
        # 创建一个新的 Excel 文件
        wb = Workbook()
        wb.save(file_path)


def sheet_name_deal(file_path):
    wb = load_workbook(file_path)
    # 获取sheet页,修改第一个sheet页面名为销售明细
    name1 = wb.sheetnames[0]
    ws1 = wb[name1]
    ws1.title = "销售明细"
    wb.save(file_path)


# 处理格式
def set_cell_style(ws):
    # 边框
    border = Border(
        left=Side(border_style='thin', color='000000'),
        right=Side(border_style='thin', color='000000'),
        top=Side(border_style='thin', color='000000'),
        bottom=Side(border_style='thin', color='000000'),
    )
    # 对齐
    alignment = Alignment(
        horizontal='center',
        vertical='center',
        text_rotation=0,
        indent=0
    )
    # 字体
    font = Font(
        name='微软雅黑',
        size=11,
        bold=False,
        italic=False,
        strike=False,
        color='000000'
    )

    rows = ws.max_row  # 获取最大行
    columns = ws.max_column  # 获取最大列
    # 遍历表格内容,注意:openpyxl下标是从1开始
    for i in range(1, rows + 1):
        for j in range(1, columns + 1):
            # 设置边框
            ws.cell(i, j).border = border
            # 设置居中对齐
            ws.cell(i, j).alignment = alignment
            # 设置字体
            ws.cell(i, j).font = font
    return ws


def number_to_column(n):
    """Convert a number to the corresponding column letter in Excel"""
    column = ""
    while n > 0:
        n -= 1
        column = string.ascii_uppercase[n % 26] + column
        n //= 26
    return column


def auto_col_width(ws):
    lks = []  # 英文变量太费劲,用汉语首字拼音代替
    for i in range(1, ws.max_column + 1):  # 每列循环
        lk = 1  # 定义初始列宽,并在每个行循环完成后重置
        for j in range(1, ws.max_row + 1):  # 每行循环
            sz = ws.cell(row=j, column=i).value  # 每个单元格内容
            if isinstance(sz, str):  # 中文占用多个字节,需要分开处理
                lk1 = len(sz.encode('gbk'))  # gbk解码一个中文两字节,utf-8一个中文三字节,gbk合适
            else:
                lk1 = len(str(sz))
            if lk < lk1:
                lk = lk1  # 借助每行循环将最大值存入lk中
            # print(lk)
        lks.append(lk)  # 将每列最大宽度加入列表。(犯了一个错,用lks = lks.append(lk)报错,append会修改列表变量,返回值none,而none不能继续用append方法)

    # 第二步:设置列宽
    for i in range(1, ws.max_column + 1):
        k = number_to_column(i)  # 将数字转化为列名,26个字母以内也可以用[chr(i).upper() for i in range(97, 123)],不用导入模块
        ws.column_dimensions[k].width = lks[i - 1] + 2  # 设置列宽,一般加两个字节宽度,可以根据实际情况灵活调整
    return ws


# 首行
def style_deal(file_path1):
    wb = load_workbook(file_path1)
    name_list = wb.sheetnames
    for name in name_list:
        ws = wb[name]
        set_cell_style(ws)
        # 自适应列宽
        auto_col_width(ws)
    wb.save(file_path1)


def data_deal(file_path1, file_path2):

    create_excel(file_path2)
    # 读入数据
    sheet_name_deal(file_path1)
    df1 = pd.read_excel(file_path1, sheet_name='销售明细')
    # 去除NaN,变为0
    df1 = df1.fillna('0')

    # print(df1)
    # 判断列是否存在
    # 创建厂进货
    if '00-期初' in df1.columns:
        df1['00-期初'] = df1['00-期初'].astype(int)
        df1["01-进货"] = df1["01-进货"].astype(int)
        df1['厂进货'] = df1['00-期初'] + df1["01-进货"]
    else:
        df1["01-进货"] = df1["01-进货"].astype(int)
        df1['厂进货'] = df1["01-进货"] * 1.0

    # 此时是浅拷贝,修改了df1

    # df2 = df1[df1['厂进货'] == 0]
    # df2['厂进货'] = df2['22-调整']
    # 创建厂退货
    df1['01-进货退'] = df1['01-进货退'].astype(int)
    df1['厂退货'] = df1['01-进货退'] * (-1)
    # 创建实际进货
    df1['实际进货'] = df1["厂进货"] - df1['厂退货']
    # 创建销售数量
    df1['销售数量'] = df1['17-零售'] * (-1)
    # 填充空值为0
    df1['销售数量'] = df1['销售数量'].fillna(0)
    df1['销售数量'] = df1['销售数量'].replace('', 0)
    print(df1['销售数量'])
    df1['销售数量'] = df1['销售数量'].astype(int)
    # 创建库存数量
    df1['库存数量'] = df1['23-期末']
    # 创建销比
    df1['销比'] = df1['销售数量'].div(df1['厂进货']).fillna('')
    # 创建备注
    df1['备注'] = ''
    # 选取列
    result_list = ['部门名称', '品牌名称', '厂进货', '厂退货', '实际进货', '销售数量', '库存数量', '销比', '备注']
    df1 = df1[result_list]
    # 将0值变为空
    df1 = df1.replace(0, '')
    df1 = df1.replace('0', '')
    result_sheet = pd.ExcelWriter(file_path2, engine='openpyxl')  # 先定义要存入的文件名xxx,然后分别存入xxx下不同的sheet
    # df1将0转变为空
    df1.to_excel(result_sheet, "销售明细", index=False, na_rep=0, inf_rep=0)
    # 这步不能省,否则不生成文件
    result_sheet.save()


def column_ordinal_by_name(ws, name):
    header_row = 1  # 假设表头在第1行
    header_column = None
    for row in ws.iter_rows(min_row=header_row, max_row=header_row):
        for cell in row:
            if cell.value == name:
                header_column = cell.column
                break

    if header_column is not None:
        print(f"表头'Name'在第{header_column}列")
    else:
        print("未找到指定的表头")
    return header_column


def self_style(file_path2):
    sheet_name_deal(file_path2)
    # df1 = pd.read_excel(file_path1, sheet_name='销售明细')
    # 选择需要修改格式的列,例如第一列(A列)
    wb = load_workbook(file_path2)
    ws = wb['销售明细']
    # 获取列名的列序号
    column_ordinal_num = column_ordinal_by_name(ws, '销比')
    # 将列数字序号转化为字母序号
    column_ordinal_letter = number_to_column(column_ordinal_num)
    print(column_ordinal_letter)
    # 将列格式转换为百分比
    column = ws[column_ordinal_letter]
    for cell in column:
        cell.number_format = '0.00%'

    # 全局染色
    high_light_color = 'D8E4BC'
    for i in range(1, ws.max_row+1):
        for cell in ws[i]:
            cell.fill = PatternFill(start_color=high_light_color, end_color="FF0000", fill_type="solid")
            #print(cell)

    # 关键染色
    key_color = '92D050'
    for cell in ws[1]:
        cell.fill = PatternFill(start_color=key_color, end_color="FF0000", fill_type="solid")
    for cell in ws['A']:
        cell.fill = PatternFill(start_color=key_color, end_color="FF0000", fill_type="solid")
    for cell in ws[ws.max_row]:
        cell.fill = PatternFill(start_color=key_color, end_color="FF0000", fill_type="solid")
    # 品牌名为合计染色
    for i in range(1, ws.max_row+1):
        if ws['B'+str(i)].value == '合计':
            for cell in ws[i]:
                cell.fill = PatternFill(start_color=key_color, end_color="FF0000", fill_type="solid")

    wb.save(file_path2)


if __name__ == '__main__':
    file_path1 = './src/23春数据.xlsx'
    file_path2 = './src/23春库存精修.xlsx'
    data_deal(file_path1, file_path2)
    style_deal(file_path2)

    self_style(file_path2)
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值