2023年9月30日土曜日

ユーザ勤務表からスケジュールナース予定へのインポート

 顧客仕様を実装するにあたって、最初に行うのは、仕様の検討です。具体的な実装の目安がついたら、次に行うのは、顧客勤務表Excelから、予定へのインポートです。つまり、人力解(Excel)から、予定へインポートする作業です。それには、一部署でしたら、手入力してもよいのですが、多数の部署の場合は、インポートするスクリプトを書きます。

インポートの目的は、

1)初期状態の把握(人力解の達成度把握)

2)実装の検討、確認用

です。

で、インポートしてみると、多数のハード制約違反が見つかるのが普通です。私の理解の誤りも見つかりますが、大半は、お聞きしていた仕様そのものが達成されていないことにあります。

実装にあたっては、本当に達成そのものが難しいものがあります。当然そのような制約は、ソフト制約としますが、例えば、6連勤務の禁止や、明けの後の休み、等、これは当然ハード制約だろう、と思える制約も、時々達成出来ていないことが把握できます。

しかし、多くの達成できていない中でも、達成できている項目があるのも事実です。そういう風に人力勤務表を眺めていると、作成者が何を最重要視しているかが、判るときもあります。

お伝えしたいのは、多くの労力を要した勤務表作りの経験は、スケジュールナースにおいて無用ということではありません。むしろ、必要なことなのではないか? とも思います。何が大変か?という経験は、ほぼそのままスケジュールナースのエンジンでも、同じように大変なことなのです。

<インポートスクリプト例>


import os
import ctypes
import win32gui, win32con


def get_open_file_name(title):
    filter='xlsx\0*.xlsx\0'
    customfilter='Other file types\0*.*\0'
    fname, customfilter, flags=win32gui.GetOpenFileNameW(
    InitialDir=project_file_path, 
    Flags=win32con.OFN_ALLOWMULTISELECT|win32con.OFN_EXPLORER,
    File='', DefExt='xlsx',
    Title=title,#'Excel予定シートを開く',
    Filter=filter,
    CustomFilter=customfilter,
    FilterIndex=0)
    print ('読み込みファイル名:', repr(fname))
    print(fname,flags)
    return str(fname)

def output_question():
    MessageBox = ctypes.windll.user32.MessageBoxW
    res=MessageBox(HWND, 'スタッフ希望を入力しますか?', '人力解全体を出力しますか?', 3)
    print(res)
    if res==7 or res==2:##いいえ、キャンセル
        return False
    return True

def post_main():
    
    #import pdb
    #pdb.set_trace()
    print('\n\n*********ポスト処理を実行中です。*************\n')
    import win32com.client#pywin32をインポート

#すでにExcelが起動されている場合はそのタスクが使われる
#エラー終了するとタスクは残ります
    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,"ex1.xlsx")
    #file.replace("/","\\")
    file=get_open_file_name("人力解を開く")
    wb=xl.workbooks.Open(file)

# Excelシートオブジェクト
    ws = wb.Worksheets(1)
 
    # 指定したシートを選択
    # Select()の使用前にシートのActivate()が必要
    ws.Activate()
    #v=ws.Range("A3").Value
    #print(v)
    wk = ws.UsedRange 		# 使用範囲を取得
    columns = wk.Columns.Count	# 行数
    rows = wk.Rows.Count		# 列数
    cells = wk.Value
    days=0
    day_list=[]
    for col in range(0,columns):
        v=cells[0][col]#,colws.Cells(1,col).Value
        if v!=None:
            days+=1
            day_list.append(v)
            #print(v,v.year,v.month, v.day)
    
    print('Days',days)
    name_list=[]
    data_list=[]
    preferred_list=[]
    for row in range(3,1000,3):
        v=ws.Cells(row,1).Value
        if v !=None:
            print(v)
            name_list.append(v)
            list=[]
            plist=[]
            for col in range(2,2+days):
                v=ws.Cells(row+2,col).Value
                list.append(v)
                v=ws.Cells(row+1,col).Interior.ColorIndex
                plist.append(v)
            data_list.append(list)
            preferred_list.append(plist)
        else:
            break
    wb.Close()
    print("persons=",len(name_list),len(data_list))
    print(data_list)
    print(preferred_list)
    output_preferred_schedule=output_question()
    file=get_open_file_name("書き込みする予定ファイルを選択")
    wb=xl.workbooks.Open(file)

# Excelシートオブジェクト
    ws = xl.Worksheets(1)
 
    # 指定したシートを選択
    # Select()の使用前にシートのActivate()が必要
    ws.Activate()
    start_col=0
    for col in range(2,100):
        v=ws.Cells(2,col).Text
        #print(v)
        if v!=None and v=="1":
            start_col=col
            break
    print(start_col)
    start_row=4
    wk = ws.UsedRange 		# 使用範囲を取得
    columns = wk.Columns.Count	# 行数
    rows = wk.Rows.Count	
    for r in range(rows+1):#len(name_list)):
        name=ws.Cells(r+start_row,1).Value
        processed=False
        for k in range(len(name_list)):
            if name==name_list[k]:
                processed=True
                for c in range(days):
                #print(r,c)
                    if output_preferred_schedule:
                        if preferred_list[r][c]>0:
                            ws.Cells(r+start_row,c+start_col).Value=data_list[k][c]
                    else:
                        ws.Cells(r+start_row,c+start_col).Value=data_list[k][c]
        if not processed:
            for c in range(days):
                ws.Cells(r+start_row,c+start_col).Value=''#clear

    wb.Save()
    wb.Close()
    xl.Quit()

post_main()

0 件のコメント:

コメントを投稿