見出し画像

Python、「作業リストから指定した日付の作業内容を抽出する」デスクトップアプリを作ってみた。

sheetが何枚もあると、ブックで検索をすればいいのですがそれも面倒なので、デスクトップアプリを作成してみます。


こんな感じのExcelシートを使って仕事の管理をしています。
今日の仕事内容を探すために「Ctrl+Fのブックで検索」をしないといけないのが
面倒なので、Pythonでコードを書いてみました。

import PySimpleGUI as sg
import openpyxl
from datetime import datetime

def perform_search(selected_date):
    excel_file_path = "パスデータを入力してください.xlsx"
    result_data = []

    # 全てのシートに対して検索を行います
    for sheet_name in workbook.sheetnames:
        sheet = workbook[sheet_name]

        for row in sheet.iter_rows(min_row=2, max_row=sheet.max_row, min_col=3, max_col=5):  # 2行目から最終行まで検索
            date_value = row[0].value
            if date_value and date_value.date() == selected_date.date():
                result_data.append(f"{row[0].value}_{row[1].value}_{row[2].value}")

    return result_data

sg.theme('LightGreen8')

# Excelファイルを読み込み、コンボボックスに表示するデータを取得します
excel_file_path = "パスデータを入力してください.xlsx"
workbook = openpyxl.load_workbook(excel_file_path)

# すべてのシートから日付の一覧を取得
all_dates = set()
for sheet_name in workbook.sheetnames:
    sheet = workbook[sheet_name]
    for date_cell in sheet.iter_cols(min_row=2, max_row=sheet.max_row, min_col=3, max_col=3):
        date_value = date_cell[0].value
        if date_value:
            all_dates.add(date_value.date())

combo_values = [str(date) for date in sorted(all_dates)]

layout = [
    [sg.Text('検索する日付を選択してください:')],
    [sg.Combo(combo_values, key='-COMBO-', enable_events=True)],
    [sg.Button('検索', key='-SEARCH-')], [sg.Button('クリア', key='-CLEAR-')],
    [sg.Text('検索結果:', size=(30, 1))],
    [sg.Listbox(values=[], size=(50, 10), key='-RESULT-')],
]

window = sg.Window('作業予定検索', layout)

while True:
    event, values = window.read()
    if event == sg.WIN_CLOSED:
        break
    elif event == '-SEARCH-':
        selected_date_str = values['-COMBO-']
        if selected_date_str:
            selected_date = datetime.strptime(selected_date_str, "%Y-%m-%d")
            search_result = perform_search(selected_date)
            window['-RESULT-'].update(search_result)
    elif event == '-CLEAR-':
        window['-RESULT-'].update([])

window.close()
完璧ではありませんが、いい感じのが出来ました。

  • より直感的に使えるように、カレンダーウェジットを追加してみました。

import PySimpleGUI as sg
import openpyxl
from datetime import datetime

def perform_search(selected_date):
    excel_file_path = "パスデータを入力してください.xlsx"
    result_data = []

    # 全てのシートに対して検索を行います
    for sheet_name in workbook.sheetnames:
        sheet = workbook[sheet_name]

        for row in sheet.iter_rows(min_row=2, max_row=sheet.max_row, min_col=3, max_col=5):  # 2行目から最終行まで検索
            date_value = row[0].value
            if date_value and date_value.date() == selected_date.date():
                result_data.append(f"{row[0].value}_{row[1].value}_{row[2].value}")

    return result_data

sg.theme('LightGreen8')

# Excelファイルを読み込み、コンボボックスに表示するデータを取得します
excel_file_path = "パスデータを入力してください.xlsx"
workbook = openpyxl.load_workbook(excel_file_path)

# カレンダーウィジェットを追加
layout = [
    [sg.Text('検索する日付を選択してください:')],
    [sg.CalendarButton('選択', target='-COMBO-', key='-CALENDAR-', format='%Y-%m-%d')],
    [sg.InputText(key='-COMBO-', enable_events=True), sg.Button('検索', key='-SEARCH-'), sg.Button('クリア', key='-CLEAR-')],
    [sg.Text('検索結果:', size=(30, 1))],
    [sg.Listbox(values=[], size=(50, 10), key='-RESULT-')],
]

window = sg.Window('作業予定検索', layout)

while True:
    event, values = window.read()
    if event == sg.WIN_CLOSED:
        break
    elif event == '-SEARCH-':
        selected_date_str = values['-COMBO-']
        if selected_date_str:
            selected_date = datetime.strptime(selected_date_str, "%Y-%m-%d")
            search_result = perform_search(selected_date)
            window['-RESULT-'].update(search_result)
    elif event == '-CLEAR-':
        window['-RESULT-'].update([])

window.close()
こんな感じです。かっこよくないですか?

コマンドでインストール

pip install openpyxl
pip install PySimpleGUI

すべてのExcelデータシート内容(2行目より下)を抽出できるか、チェック

import openpyxl

# Excelファイルを読み込みます
excel_file_path = "パスデータを入力してください.xlsx"
workbook = openpyxl.load_workbook(excel_file_path)

# 全てのシートに対して検索を行います
for sheet_name in workbook.sheetnames:
    sheet = workbook[sheet_name]

    for row in sheet.iter_rows(min_row=2, max_row=sheet.max_row, min_col=1, max_col=3):  # 2行目から最終行まで検索
        print(f"{row[0].value}_{row[1].value}_{row[2].value}")


完璧ではありませんが、近づいてきました。
import PySimpleGUI as sg
import openpyxl
from datetime import datetime

def perform_search(selected_date):
    result_data = []

    # 全てのシートに対して検索を行います
    for sheet_name in workbook.sheetnames:
        sheet = workbook[sheet_name]

        for row in sheet.iter_rows(min_row=2, max_row=sheet.max_row, min_col=1, max_col=3):  # 2行目から最終行まで検索
            date_value = row[-1].value
            if date_value and datetime.strptime(str(date_value.date()), "%Y-%m-%d").date() == selected_date.date():
                result_data.append(str(row))

    return result_data


sg.theme('LightGreen8')

# Excelファイルを読み込み、コンボボックスに表示するデータを取得します
excel_file_path = "パスデータを入力してください.xlsx"
workbook = openpyxl.load_workbook(excel_file_path)

# カレンダーウィジェットを追加
layout = [
    [sg.Text('検索する日付を選択してください:')],
    [sg.CalendarButton('選択', target='-COMBO-', key='-CALENDAR-', format='%Y-%m-%d')],
    [sg.InputText(key='-COMBO-', enable_events=True), sg.Button('検索', key='-SEARCH-'), sg.Button('クリア', key='-CLEAR-')],
    [sg.Text('検索結果:', size=(30, 1))],
    [sg.Listbox(values=[], size=(50, 10), key='-RESULT-')],
]

window = sg.Window('作業予定検索', layout)

while True:
    event, values = window.read()
    if event == sg.WIN_CLOSED:
        break
    elif event == '-SEARCH-':
        selected_date_str = values['-COMBO-']
        if selected_date_str:
            selected_date = datetime.strptime(selected_date_str, "%Y-%m-%d")
            search_result = perform_search(selected_date)
            window['-RESULT-'].update(search_result)  # ここを修正

    elif event == '-CLEAR-':
        window['-RESULT-'].update([])

window.close()


ついにゴールが近づいてきた感じがします。
検索結果が表示されました。
import PySimpleGUI as sg
import openpyxl
from datetime import datetime

def perform_search(selected_date):
    result_data = []

    # Iterate through all sheets for search
    for sheet_name in workbook.sheetnames:
        sheet = workbook[sheet_name]

        for row in sheet.iter_rows(min_row=2, max_row=sheet.max_row, min_col=1, max_col=3):
            date_value = row[-1].value
            if date_value and datetime.strptime(str(date_value.date()), "%Y-%m-%d").date() == selected_date.date():
                # Extract values from cells and append to result_data
                row_values = [cell.value for cell in row]
                result_data.append(row_values)

    return result_data

sg.theme('LightGreen8')

# Load Excel file and get data for the combo box
excel_file_path = "パスデータを入力してください.xlsx"
workbook = openpyxl.load_workbook(excel_file_path)

layout = [
    [sg.Text('Select a date for search:')],
    [sg.CalendarButton('Select', target='-COMBO-', key='-CALENDAR-', format='%Y-%m-%d')],
    [sg.InputText(key='-COMBO-', enable_events=True), sg.Button('Search', key='-SEARCH-'), sg.Button('Clear', key='-CLEAR-')],
    [sg.Text('Search Results:', size=(30, 1))],
    [sg.Listbox(values=[], size=(50, 10), key='-RESULT-')],
]

window = sg.Window('Task Search', layout)

while True:
    event, values = window.read()
    if event == sg.WIN_CLOSED:
        break
    elif event == '-SEARCH-':
        selected_date_str = values['-COMBO-']
        if selected_date_str:
            selected_date = datetime.strptime(selected_date_str, "%Y-%m-%d")
            search_result = perform_search(selected_date)
            window['-RESULT-'].update(search_result)

    elif event == '-CLEAR-':
        window['-RESULT-'].update([])

window.close()

欲しい内容だけ表示できました。
続きは、会社で細かい設定をして完成させます。
import PySimpleGUI as sg
import openpyxl
from datetime import datetime

def perform_search(selected_date):
    result_data = []

    # Iterate through all sheets for search
    for sheet_name in workbook.sheetnames:
        sheet = workbook[sheet_name]

        for row in sheet.iter_rows(min_row=2, max_row=sheet.max_row, min_col=1, max_col=3):
            date_value = row[-1].value
            if date_value and datetime.strptime(str(date_value.date()), "%Y-%m-%d").date() == selected_date.date():
                # Extract values from cells excluding column C and append to result_data
                row_values = [cell.value for cell in row[:-1]]  # Exclude the last cell (column C)
                result_data.append(row_values)

    return result_data

sg.theme('LightGreen8')

# Load Excel file and get data for the combo box
excel_file_path = "パスデータを入力してください.xlsx"
workbook = openpyxl.load_workbook(excel_file_path)

layout = [
    [sg.Text('Select a date for search:')],
    [sg.CalendarButton('Select', target='-COMBO-', key='-CALENDAR-', format='%Y-%m-%d')],
    [sg.InputText(key='-COMBO-', enable_events=True), sg.Button('Search', key='-SEARCH-'), sg.Button('Clear', key='-CLEAR-')],
    [sg.Text('Search Results:', size=(30, 1))],
    [sg.Listbox(values=[], size=(50, 10), key='-RESULT-')],
]

window = sg.Window('Task Search', layout)

while True:
    event, values = window.read()
    if event == sg.WIN_CLOSED:
        break
    elif event == '-SEARCH-':
        selected_date_str = values['-COMBO-']
        if selected_date_str:
            selected_date = datetime.strptime(selected_date_str, "%Y-%m-%d")
            search_result = perform_search(selected_date)
            window['-RESULT-'].update(search_result)

    elif event == '-CLEAR-':
        window['-RESULT-'].update([])

window.close()


VBAでコードを入力するなら下記のコードらしいです。
(まだ試していません)
カレンダーは使えないみたいです。

Option Explicit

Sub PerformSearch()
    Dim selectedDate As Date
    Dim resultData As Variant
    Dim ws As Worksheet
    Dim cell As Range
    Dim rowValues As Variant
    Dim excelFilePath As String
    
    ' Excelファイルのパスを設定
    excelFilePath = "パスデータを入力してください.xlsx"
    
    ' 選択した日付を取得
    On Error Resume Next
    selectedDate = Application.InputBox("検索する日付を入力してください (YYYY-MM-DD)", Type:=1)
    On Error GoTo 0
    
    ' キャンセルされた場合や無効な日付の場合は終了
    If selectedDate = 0 Then Exit Sub
    
    ' 検索結果を格納する配列
    ReDim resultData(1 To 1, 1 To 2)
    
    ' 全てのシートに対して検索を行う
    For Each ws In ThisWorkbook.Sheets
        For Each cell In ws.Range("A2:C" & ws.Cells(ws.Rows.Count, "A").End(xlUp).Row)
            If IsDate(cell.Offset(0, 2).Value) Then
                If DateValue(cell.Offset(0, 2).Value) = DateValue(selectedDate) Then
                    ' C列以外の値を取得して結果に追加
                    rowValues = Array(cell.Value, cell.Offset(0, 1).Value)
                    resultData(UBound(resultData, 1), UBound(resultData, 2)) = rowValues
                    ReDim Preserve resultData(1 To UBound(resultData, 1) + 1, 1 To UBound(resultData, 2))
                End If
            End If
        Next cell
    Next ws
    
    ' 空の行を削除
    If UBound(resultData, 1) > 1 Then
        ReDim Preserve resultData(1 To UBound(resultData, 1) - 1, 1 To UBound(resultData, 2))
    End If
    
    ' 検索結果を表示
    If UBound(resultData, 1) > 0 Then
        MsgBox "検索結果:" & vbCrLf & Join(Application.Transpose(resultData), vbCrLf), vbInformation, "検索結果"
    Else
        MsgBox "該当するデータはありません。", vbInformation, "検索結果"
    End If
End Sub

最後までお読みいただきありがとうございます。
♡頂けますと、励みになります。

この記事が気に入ったらサポートをしてみませんか?