python遍歷sheet並將處理結果存儲到當前工作表中

1、背景

剛開始的時候,領導給了我一張excel表,她說每週都不定期更新,每次更新都是複製粘貼,不但容易出錯,而且要花費2個多小時,然後她問我,你在下班時間可以考慮怎麼用腳本如python,或VBA把這個東西做批量化處理,提高一下工作效率,我說好,然後就開始構思怎麼去處理這樣一種格式的數據,撿起我3個月都沒寫腳本的熱情,就展開了。剛開始也沒想着一下就能完全實現,一步一步來,快一點是一點,然後寫了一個不太完美的初級版本,後面在別人的刺激下對腳本進行了改善,完全做到了自動化腳本,目前已經正常無誤運轉了3次,打算再測4次,後面就正式投入使用了,哈哈!!!!

2、需求實現

大致的需求如下圖,就是如何把原始的數據格式變成目標格式(實際上就是把區域1,2,3根據字段名做一個縱向連接),大家可以先思考一下如何去做,下面一一爲大家揭曉:
原始數據:
在這裏插入圖片描述
目標樣式:
在這裏插入圖片描述
相信有很多小夥伴們都能想到,就是先把每一個彙報人所屬區域的起始位置和區域間隔識別出來,然後結合for用concat做個縱向拼接,不就ok了麼,能想到這一步,那就離成功不遠了,哈哈,下面將逐步分析怎麼去是實現這個功能,即如何實現這個功能呢????。

3、分析及代碼實現

(1)廢話不多說,先把文件讀進來再說;
在這裏插入圖片描述
(2)獲取區域的起始位置:大家有沒有發現,1,2,3(第一行合併單元格的數據)在excel中的數據表現和python不一致,excel佔據了多個單元格,python只佔用了一個單元格。從python輸出來看,第一行中不爲nan的數據是不是就是每一個區域的開始位置對應的值,那麼是不是可以使用argwhere函數來獲取它所對應的索引,也就是位置呢,下面繼續,這裏注意不加astype將其轉化成float類型會報錯,因爲isnan只適用於float類型;
在這裏插入圖片描述
(3)得到區域間隔:區域間隔,不就是後項減去前項嗎,這麼簡單的操作,構造一個新列就行,哈哈;確定了每個區域的起始位置和間隔,用個循環是不是就搞定了呢???
在這裏插入圖片描述
(4)for循環遍歷區域:這裏有幾個注意的小點,說明一下:
1、from numpy import * 是爲了使用tile函數,方便對第一列進行填充;
2、注意iloc每次取數的位置
3、爲什麼要使用dropna函數???這個讀者可以自己去探索,去掉和不去掉有什麼區別
4、concat的時候記得吧df重置索引,也就是用reset_index函數,
在這裏插入圖片描述
(5)如果是普通需求,將empty_df的數據直接用to_csv、to_excel、to_sql寫入就行,是不是就ok了,哈哈,大功告成!!!

附加想法

(1)如果要遍歷所有sheet,怎麼弄??

file_path = "D:\\test.xlsx"  # 獲取文件路徑
    
file = pd.ExcelFile(file_path)
sh_names = file.sheet_names  # 獲取sheet名稱
    
# 寫個循環遍歷所有sheet
for sh_name in sh_names:
    raw_data = pd.read_excel(file_path, sheet_name = sh_name, header = None)

(2)如何將數據寫入到原始的工作表中,並且不覆蓋原來的數據,怎麼操作(在實際工作中其實是有這種需求的,即原始表給我留着,過程表我也要,結果表我也要,統一放在一個工作簿中)??反正直接使用to_excel是行不通的,往下看,不加engine='openpyxl’參數就會覆蓋原表,不知道爲啥,有興趣的可以去探索一下:

# 將數據寫入到excel文件中,過程表,在寫入的時候不覆蓋原表
writer = pd.ExcelWriter(file_path,engine='openpyxl')  # 方便存儲原表
book = load_workbook(file_path)
writer.book = book
empty_df.to_excel(excel_writer = writer, sheet_name = '過程表')
writer.save()
writer.close()

源代碼


# -*- coding: utf-8 -*-
"""
遍歷整個excel工作簿,對所有sheet的每個區域進行同樣操作,實際上就是併到一塊,做自動化處理
This is a temporary script file.
"""

import pandas as pd
from numpy import *
import numpy as np
from openpyxl import load_workbook

'''遍歷sheet,對不同區域數據進行拼接'''
def deal_data(file_path, sh_name, empty_df):
    
    raw_data = pd.read_excel(file_path, sheet_name = sh_name, header = None)
    No1_row = np.array(raw_data.iloc[0, :]).astype(float) # 獲取第一行的數據,方便按照區域進行劃分,不加astype會報錯,isnan只適用於float類型
    
    # 得到起始位置
    No1_index = np.ravel(np.argwhere(~np.isnan(No1_row)))  # 獲取第一行的索引,方便進行區域劃分
    # 求出間隔
    col_num = raw_data.shape[1]
    No1_index_mk = np.append(No1_index[1:], col_num) # 構造列,實現錯位相減
    interval = No1_index_mk - No1_index  # 每次取數的間隔,也就是步長
    
    user_col_names= ['序號']
    
    # 將每個區域的數據拼接
    length = len(No1_index)
    for i in range(0, length):
    
        begin_position = No1_index[i]
        begin_interval = interval[i]
        # 獲取每一塊區域的數據
        part_data = raw_data.iloc[:, begin_position:begin_position + begin_interval]
        data = part_data.dropna(how="all")  # 去重掉該區域的空值
      
        # 獲取列名
        input_col_names = np.array(data.iloc[1, 0:begin_interval])
        # 獲取實際信息
        input_info = data.iloc[2:, :].reset_index(drop=True)
        input_info.columns = input_col_names
        row_num = len(input_info)  # 獲取行數,方便進行填充      
        # 獲取序號信息並填充
        user_info = np.array(data.iloc[0:1, 0])   # 獲取投放用戶信息
        user_info_fill = pd.DataFrame(tile(user_info,(row_num,1)), columns = user_col_names).reset_index(drop=True)
        
        # 橫向拼接
        data_1 = pd.concat([user_info_fill, input_info], axis = 1)
       
        # 縱向拼接
        empty_df = pd.concat([empty_df, data_1], axis = 0, sort = False)
        
    return empty_df
    

if __name__ == '__main__':
    
    file_path = "D:\\test.xlsx"  # 獲取文件路徑
    
    file = pd.ExcelFile(file_path)
    sh_names = file.sheet_names  # 獲取sheet名稱
    empty_df = pd.DataFrame()  # 創建一個空df,用來存儲數據
    
    # 將多個sheet中的數據整合到一個sheet中
    for sh_name in sh_names:
        empty_df = deal_data(file_path, sh_name, empty_df)
    
    
    # 將數據寫入到excel文件中,過程表,在寫入的時候不覆蓋原表
    writer = pd.ExcelWriter(file_path,engine='openpyxl')  # 方便存儲原表
    book = load_workbook(file_path)
    writer.book = book
    empty_df.to_excel(excel_writer = writer, sheet_name = '過程表')
    writer.save()
    writer.close()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章