Python 實現自動化 Excel 報表

Py 實現自動化Excel報表

好幾個月沒有寫筆記了, 並非沒有積累, 而是有點懶了. 想想還是要續上, 作為工作成長的一部分哦.

最近有做一些報表, 但一直找不到一個合適的報表工具, 又實在不想寫前端, 後端… 思來想去, 感覺 Excel 就一定程度上能做可視化的, 除了不能動態交互外, 其他都挺好. 今天分享的就是一個關於如何用 Py 來自動化Excel 報表, 解放雙手, 提高工作效率哦.

總體解決方案

輸出報表

當然是測試用的假數據啦.

自動化Py腳本

基本思路: 
1. 準備模板數據需要的 SQL 
2. 用 Pandas 連接 數據庫 並執行 SQL, 返回 DataFrame 
3. 用 Xlwings 直接打開 Excel, 並將這些 DataFrame 填充到 寫死的 單元格
4. 保存並退出

具體代碼如下哦:

import pandas as pd 
import xlwings as xw
import pymssql


# 各品類月同期 
def get_last_year_sale(start_date, end_date):
    """各品類同期銷量, 對比19年"""
    sql_01 = f"""
    SELECT 
      品類
      , SUM(數量) AS QTY
    FROM XXX
    WHERE 是否電商 = 1 
      AND 銷售時間 BETWEEN DATEADD(YEAR, -2, '{start_date}') AND DATEADD(YEAR, -2, '{end_date}')     
    GROUP BY 品類
    """
    df = pd.read_sql(sql_01, con=con)
    df_xtc = df[df['品類'] == 'A品類'][['品類', 'QTY']]
    df_bbk = df[df['品類'] == 'B品類'][['品類', 'QTY']]
    return df_xtc, df_bbk 
    
def get_anget_sale(start_date, end_date):
        """返回各品類, 各區域的時間段銷量"""
        sql = f"""
        SELECT 
          品類
          , AGENT
          , SUM(數量) AS QTY
          , ROW_NUMBER()OVER(PARTITION BY 品類 ORDER BY SUM(數量) DESC) MY_RANK
        FROM XXX
        WHERE 是否電商 = 1 
          AND 銷售時間 BETWEEN '{start_date}' AND '{end_date}'
        GROUP BY AGENT, 品類
        """
        df = pd.read_sql(sql, con=con)
        df_xtc = df[df['品類'] == 'A品類'][['AGENT', 'QTY']]
        df_bbk = df[df['品類'] == 'B品類'][['AGENT', 'QTY']]
        df_pad = df[df['品類'] == 'C品類'][['AGENT', 'QTY']]

        return df_xtc, df_bbk, df_pad  
    
def get_machine_sale(start_date, end_date):
    """返回各品類, 各區域的時間段銷量"""
    sql = f"""
    SELECT 
      品類
      , 機型
      , SUM(數量) AS QTY
      , ROW_NUMBER()OVER(PARTITION BY 品類 ORDER BY SUM(數量) DESC) MY_RANK
    FROM V_REALSALE
    WHERE 是否電商 = 1 
      AND 銷售時間 BETWEEN '{start_date}' AND '{end_date}'
    GROUP BY 機型, 品類
    """
    df = pd.read_sql(sql, con=con)
    df_xtc = df[df['品類'] == 'A品類'][['機型', 'QTY']]
    df_bbk = df[df['品類'] == 'B品類'][['機型', 'QTY']]

    return df_xtc, df_bbk 


# main 
con = pymssql.connect('172.28.1.158', 'sa', 'dwbbkkzw168', 'biee')

# 基礎配置: 根據用戶輸入當前日期, 輸出當月, 當季度第一天 
print("歡迎哦, 此小程序專門為XX看板做數據自動更新呢~")
print()

today = input("請輸入截止日期(昨天), 形如: 2021/5/20 按回車結束:   ")

if len(today.split('/')) != 3:
    raise "日期格式輸入錯誤!!, 請按照形如 '2021/5/20'的格式重新輸入"
else:
    m_cur = today.split('/')[1]
    m_first_day = '2021/' + m_cur + '/1'

# 季度第一天 
if m_cur in ('1', '01', '2', '02', '3', '03'):
    q_time_start = '2021/1/1'
    
elif m_cur in ('4', '04', '5', '05', '6', '06'):
    q_time_start = '2021/4/1'
    
elif m_cur in ('7', '07', '8', '08', '9', '09'):
    q_time_start = '2021/7/1'
else:
    q_time_start = '2021/10/1'

print()
print("正在開始更新....")
print("提示, 接下看到閃退, 是正常現象, 就程序模擬人去打開文件, 填充數據, 不要緊張哦~~~")

# 去年月, 季度同期 
df_mm_xtc, df_mm_bbk = get_last_year_sale(m_first_day, today)
df_qq_xtc, df_qq_bbk = get_last_year_sale(q_time_start, today)

# 當月各地區累積銷量
df_m_xtc, df_m_bbk, df_m_pad = get_anget_sale(m_first_day, today)

# 各地區當季度銷量 
df_q_xtc, df_q_bbk, df_q_pad = get_anget_sale(q_time_start, today)

# 各機型當季度銷量 
df_q_type_xtc, df_q_type_bbk = get_machine_sale(q_time_start, today) 
# 過濾掉 銷量為0的型號 
df_q_type_xtc = df_q_type_xtc[df_q_type_xtc.QTY > 0]
df_q_type_xtc.replace('Z6áÛ·å°æ', 'Z6巔峰版', inplace=True)

df_q_type_bbk = df_q_type_bbk[df_q_type_bbk.QTY > 0]

# 打開excel 模板 等待數據填充 
app = xw.App(visible=True, add_book=False)

app.display_alerts = False    # 關閉一些提示信息,可以加快運行速度。 默認為 True。
app.screen_updating = True

wb = app.books.open("XXX_全品類_看板.xlsx")
data_sht = wb.sheets['數據']

# 19年當月同期銷量
data_sht.range('B9').value = df_mm_xtc.values
data_sht.range('G9').value = df_mm_bbk.values

# 當季度同比
data_sht.range('B10').value = df_qq_xtc.values
data_sht.range('G10').value = df_qq_bbk.values

# 填充各品類當月銷量, 注意單元格是寫死的哦
data_sht.range('I72').value = df_m_xtc.values
data_sht.range('T72').value = df_m_bbk.values
data_sht.range('AE72').value = df_m_pad.values

# 填充當季度銷量, 同理是寫死的
data_sht.range('A54').value = df_q_xtc.values
data_sht.range('F54').value = df_q_bbk.values
data_sht.range('K54').value = df_q_pad.values

# 填充當季度各型號, 同理是寫死的
data_sht.range('A21').value = df_q_type_xtc.values
data_sht.range('F21').value = df_q_type_bbk.values

wb.save()
app.quit()

print()
print("~~更新結束了哦~~")
print()
input("請按任意鍵退出~~")
print()
print('BYE~~ 人生若只如初見呢~~')

打包 EXE 桌面小程序

最好用一個純凈的 虛擬環境打包.

終端命令: python -m venv 虛擬環境名稱

然後進入腳本目錄下, 進行打包哦.

pyinstaller main.py -F

打包成功後的樣子.

雙擊運行即可哦.

這時候再重新打開該目錄下的 Excel 模板, 發現數據已經自動更新了.

我現在真的感受到, 用開發的思維做一些腳本工具, 真的會極大提高我現在當文員的很多重複性工作哦!