1. 程式人生 > >Python實戰之Excel資料按索引更新

Python實戰之Excel資料按索引更新

    在日常工作中,我們經常需要需要批量更新資料,比如有個destination表,裡面有一列的資料需要被更新,更新的依據為reference表,python指令碼執行前和執行後的資料列示意圖如下:

    我們使用Excel檔案作為config引數表,reference和destination也使用Excel作為資料,其中config引數如下圖,python例子讀取該檔案中的引數,獲取各個引數的值,從而獲取源資料和目的資料資訊。

   實現程式碼設計為幾個函式,其各個功能如下:

函式名 函式功能
get_str_for_cell(cell_value)

把傳入的內容轉換為字串格式,主要針對浮點型資料。

在python讀取Excel單元格時,會把數值讀為浮點數,此處方法重新轉換為整數型的字串

get_saveas_name(origin_name)

把傳入的檔名改名為帶時間戳,例如原檔名為abc.xls,則返回abc_2018-11-13-10-10-07.xls。

get_mainpara()
獲config檔案中main的sheet頁的引數,該資訊是源資料和目標資料的定位資訊。
get_optionpara()
獲config檔案中option的sheet頁的引數,該資訊是資料替換的引數,比如是否進行force替換。
get_reference_dict(main_paras)
根據main引數獲取到reference資料的資料字典。
update_xlsx_file(main_paras, option_paras, reference_dict)
更新destination的表格資訊

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

    整個功能實現程式碼如下:

import xlrd
import xlutils.copy
import time
import datetime


def get_str_for_cell(cell_value):
    if isinstance(cell_value, float):
        if cell_value == int(cell_value):
            cell_value = int(cell_value)
    return str(cell_value)


def get_saveas_name(origin_name):
    now_time = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
    
    if origin_name.rfind('.'):
        return origin_name.split('.')[0] + "_" + str(now_time) + "." + origin_name.split('.')[1]
    

def get_mainpara():
    main_paras = {}
    wb = xlrd.open_workbook("config.xlsx")
    ws = wb.sheet_by_name(u"main")
    rown = 1; coln = 1
    main_paras["ReferenceFileName"] = ws.cell_value(rown,coln)
    rown = 2
    main_paras["ReferenceSheetName"] = ws.cell_value(rown,coln)
    rown = 3
    main_paras["ReferenceColumnName"] = ws.cell_value(rown,coln)
    rown = 4
    main_paras["ReferenceDataColumnName"] = ws.cell_value(rown,coln)
    rown = 5
    main_paras["DestinationFileName"] = ws.cell_value(rown,coln)
    rown = 6
    main_paras["DestinationSheetName"] = ws.cell_value(rown,coln)
    rown = 7
    main_paras["DestinationColumnName"] = ws.cell_value(rown,coln)
    rown = 8
    main_paras["DestinationDataColumnName"] = ws.cell_value(rown,coln)

    wb = xlrd.open_workbook(main_paras["ReferenceFileName"])
    ws = wb.sheet_by_name(main_paras["ReferenceSheetName"])
    reference_column_index = get_column_index(ws, main_paras["ReferenceColumnName"])
    reference_data_column_index = get_column_index(ws, main_paras["ReferenceDataColumnName"])
    main_paras["reference_column_index"] = reference_column_index
    main_paras["reference_data_column_index"] = reference_data_column_index

    wb = xlrd.open_workbook(main_paras["DestinationFileName"])
    ws = wb.sheet_by_name(main_paras["DestinationSheetName"])
    dest_column_index = get_column_index(ws, main_paras["DestinationColumnName"])
    dest_data_column_index = get_column_index(ws, main_paras["DestinationDataColumnName"])
    main_paras["dest_column_index"] = dest_column_index
    main_paras["dest_data_column_index"] = dest_data_column_index

    return main_paras


def get_optionpara():
    option_paras = {}
    wb = xlrd.open_workbook("config.xlsx")
    ws = wb.sheet_by_name(u"option")
    rown = 1; coln = 1
    option_paras["ForceReplace"] = ws.cell_value(rown,coln)
    
    return option_paras


def get_column_index(table, column_name):
    column_index = -1    
    for i in range(table.ncols):     
        if(table.cell_value(0, i) == column_name):
            column_index = i
            break
    return column_index


def get_reference_dict(main_paras):
    reference_dict = {}
    wb = xlrd.open_workbook(main_paras["ReferenceFileName"])
    ws = wb.sheet_by_name(main_paras["ReferenceSheetName"])
    
    reference_column_index = main_paras["reference_column_index"]
    reference_data_column_index = main_paras["reference_data_column_index"]
    
    num_rows = ws.nrows
    for rown in range(num_rows):
        if rown == 0:
            continue        
        reference_dict[get_str_for_cell(ws.cell_value(rown, reference_column_index))] = get_str_for_cell(ws.cell_value(rown, reference_data_column_index))

    return reference_dict

def update_xlsx_file(main_paras, option_paras, reference_dict):
    rb = xlrd.open_workbook(main_paras["DestinationFileName"], formatting_info = True)
    wb = xlutils.copy.copy(rb)
    ws_origin = rb.sheet_by_name(main_paras["DestinationSheetName"])
    ws = wb.get_sheet(main_paras["DestinationSheetName"])
    dest_column_index = main_paras["dest_column_index"]
    dest_data_column_index = main_paras["dest_data_column_index"]

    writen_count = 0
    num_rows = ws_origin.nrows
    for rown in range(num_rows):
        if rown < 5:
            continue
        key_cell = get_str_for_cell(ws_origin.cell_value(rown, dest_column_index))
        if key_cell not in reference_dict:
            print("error! can't find the value for key:", key_cell)
            continue
        data_value = reference_dict.get(key_cell)
        data_value_old = ws_origin.cell_value(rown, dest_data_column_index)
        if data_value == data_value_old:
            continue
        ws.write(rown, dest_data_column_index, data_value)
        ws.write(rown, 1, "M")
        writen_count = writen_count + 1

    print("totally modified rows:", writen_count)
    wb.save(get_saveas_name(main_paras["DestinationFileName"]))
    return


print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())), "PlanDataReplacer started work, please wait...")
main_paras = get_mainpara()
print("main_paras:", main_paras)

option_paras = get_optionpara()
print("option_paras:", option_paras)

reference_dict = get_reference_dict(main_paras)
print("reference_dict length:", len(reference_dict))
#print(reference_dict)

update_xlsx_file(main_paras, option_paras, reference_dict)


print(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())), "PlanDataReplacer work complete.")

    執行後列印資訊如下,則說明有479行資料已被更新。

 

 

如果您喜歡這篇文章,別忘了點贊和評論哦!