2022年6月13日月曜日

Pywin32によるExcel整形その2

 別なプロジェクトでも記述してみました。訪問クリニックプロジェクトです。従来のCSVは、次のような出力をしていました。

これをEXCEL整形手法で同じようにExcelに直接出力します。ついでに予定も付加しています。
同じ内容ですが、断然、見易さが違います。予定との齟齬チェックも容易です。


コードは以下のように結構な量です。
前のコードもそうですが、100行を超えるとデバッガなしではつらいものがあります。
なので、デバッガを実装することにします。
def post_main():
    
    xl,wb,ws=invoke_excel()
    for person in 全スタッフ:
        staff_name=staffdef[person]
        c=ws.Range("B1:B51").Find(staff_name)
        #print(c.Row,c.Column)
        for day in 今月:
            col=day-制約開始日
            #print(day)
            
            shift_label=shift_schedules[person][day][2]
            ws.Cells(c.Row,c.Column+3+col).Value=shift_label#シフト予定
            
            shift_color=get_shift_label_color(shift_label)
            ws.Cells(c.Row,c.Column+3+col).Interior.Color=shift_color
            draw_cell(ws,c.Row+1,c.Column+3+col,person,day)
    wb.Close(True)# Trueで保存。False=Defaultでブックを保存せずにクローズ
    # Excel終了
    xl.Quit()
    print('\n\n*********ポスト処理を実行終了しました。*************\n')


def draw_cell(ws,row,col,person,day):
    phases=3
    print(person,day)
    t0=task_solution[person][day*phases+0]
    t1=task_solution[person][day*phases+1]
    t2=task_solution[person][day*phases+2]


#勤務処理
    if t0=='日T' and t1=='日T':
        if day in 休勤日今月:
            label='休勤'
            color='128,128,100'
        else :
            label='日勤'
            color='255,128,128'
    elif t0=='日T' and t1=='有給':
        label='後有'
        color='128,255,128'
    elif t1=='日T' and t0=='有給':
        label='前有'
        color='128,128,255'
    elif t0=='有給' and t1=='有給':
        label='有休'
        color='200,200,200'
    elif t0=='公休' and t1=='公休':
        label='休み'
        color='200,255,200'
    elif t0=='日T' and t1=='公休':
        label='午前'
        color='255,200,200'
    elif t1=='日T' and t0=='公休':
        label='午後'
        color='200,200,255'
    elif t0=='希望休み' and t1=='希望休み':
        label='希休'
        color='200,128,200'
    else:
        label='M休'
        color='128,200,128'
    ws.Cells(row,col).Value=label
    ws.Cells(row,col).Interior.Color=rgb_str_to_hex(color)

#属性処理
    label=''
    color='255,255,255'
    if t2 !='公休':
        if day in 土:
            label='土拘'
            color='200,128,200'
        else :
            label='拘束'
            color='128,128,255'
        if shift_schedules[person][day]=='希望休み扱い':
            if row0[d] !='希休':
                label='希休'
                color='128,128,255'
    ws.Cells(row+1,col).Value=label
    ws.Cells(row+1,col).Interior.Color=rgb_str_to_hex(color)

#すでにExcelが起動されている場合はそのタスクが使われる
#エラー終了するとタスクは残ります
def invoke_excel():
    sc3.hook_stdout()#printをリダイレクトする
    print('\n\n*********ポスト処理を実行中です。*************\n')
    import win32com.client#pywin32をインポート

    try :
        xl = win32com.client.Dispatch("Excel.Application")
    except:
        print("can not invoke excel")
        exit()
    #動いている様子を見てみる
    xl.Visible = True
    os.chdir(project_file_path)
    file=os.path.join(project_file_path,"excel_post_export.xlsx")
    file.replace("/","\\") #なぜか逆スラッシュでないと動かない
    wb = xl.Workbooks.Open(file)
    # Excelシートオブジェクト
    ws = wb.Worksheets(1)

    # 指定したシートを選択
    # Select()の使用前にシートのActivate()が必要
    ws.Activate()
    return xl,wb,ws

def get_shift_label_color(shift_label):
    if len(shift_label)==0 or shift_label=='・':
        return 0xffffff #空白ならWhiteを返す
    for item_array in shift_label_color_map.values():#task集合から探して
        for item in item_array:#taskは複数のラベルを持つ
            shift_label_candidate=item[0]
            #print(shift_label,shift_label_candidate)
            if shift_label==shift_label_candidate:#ラベル名が一致したなら
                color_str=item[1]
                rgb = re.findall(r"\d+",color_str)
                if len(rgb)==3:
                    return rgb_to_hex(rgb)
                else:
                    return 0xffffff #rgb形式でなければWhiteを返す
    for item in shift_collections_def.values():#無かったらtask aggregatesから探す
        shift_label_candidate=item[0]
        #if len(task_label)>=1:
        #    print("list",task_label,task_label_candidate)
        if shift_label==shift_label_candidate:
            #print("matched",task_label_candidate)
            color_str=item[1]
            rgb = re.findall(r"\d+",color_str)
            if len(rgb)==3:
                return rgb_to_hex(rgb)
            else:
                return 0xffffff #rgb形式でなければWhiteを返す
    for item in phase_objects_def.values():
        shift_label_candidate=item[0]
        if shift_label==shift_label_candidate:
            color_str=item[1]
            rgb = re.findall(r"\d+",color_str)
            if len(rgb)==3:
                return rgb_to_hex(rgb)
            else:
                return 0xffffff #rgb形式でなければWhiteを返す
    for item in phase_aggregate_object_def.values():
        shift_label_candidate=item[0]
        if shift_label==shift_label_candidate:
            color_str=item[1]
            rgb = re.findall(r"\d+",color_str)
            if len(rgb)==3:
                return rgb_to_hex(rgb)
            else:
                return 0xffffff 
    #print("unmatched",task_label)
    return 0xffffff #なければWhiteを返す  

def get_task_label(task):
    
    if task in  task_label_color_map:
        return task_label_color_map[task][0][0]
    else:
        print("Invalid Task", task)
        exit()
def rgb_to_hex(rgb):
    '''
    ws.Cells(1, i).Interior.color uses bgr in hex

    '''
    bgr = (int(rgb[2]),int(rgb[1]),int(rgb[0]))
    strValue = '%02x%02x%02x' % bgr
    # print(strValue)
    iValue = int(strValue, 16)
    return iValue
def rgb_str_to_hex(color_str):
    rgb = re.findall(r"\d+",color_str)
    if len(rgb)==3:
        return rgb_to_hex(rgb)
    else:
        return 0xffffff

0 件のコメント:

コメントを投稿