Option Explicit

'===========================================================
' ■部品_シート存在チェック / SheetExists
'   ・指定したブックに、指定した名前のワークシートが存在するかを判定する
'     → Checks whether a worksheet with the specified name exists in the specified workbook.
'
'   ・存在する場合は True、存在しない場合は False を返す
'     → Returns True if it exists and False if it does not.
'
'   ・シートを操作する前の存在確認（エラー防止）に使用する
'     → Used to confirm a sheet exists before operating on it (error prevention).
'
'   ★ この部品は Sub（プロシージャ）ではなく「Function（関数）」で、Boolean を返す
'     → ★ This component is a Function (not a Sub) that returns a Boolean.
'===========================================================

'===========================================================
' ■区分 / Classification
'   ・基礎区分：土台 ／ 用途区分：確認 ／ 操作対象区分：シート
'     → Base: foundation / Purpose: check / Target: sheet
'
' ■バージョン / Version
'   ・Version 1.1（2026-11-02）  ErrHandler 内の Debug.Print を削除（「存在しない」は普通の結果のため。1.0 は 2026-10-27）
'===========================================================

'===========================================================
' ■URL（WordPress部品ページ）
'   https://feelcodelab.com/vba_parts/sheetexists/
'===========================================================

'===========================================================
' ■前提条件（AI誤動作防止の最重要項目） / Preconditions
'   ★【最重要】この部品は Function（関数）であり、戻り値（Boolean）を返す
'     → 呼び出し側は、戻り値を受け取って、存在の有無を判定する
'     → ★ [MOST IMPORTANT] This component is a Function that returns a Boolean.
'        The caller must receive the return value and use it for the check.
'
'   ★【最重要】調べるブック（vWb）は、必ず引数で指定する（省略できない）
'     → ThisWorkbook ＝ このマクロが入っているブック ／ ActiveWorkbook ＝ いまアクティブなブック
'     → ファイルを開く部品の後は、ActiveWorkbook が、開いたファイルに切り替わる。
'       開いた直後に、ActiveWorkbook を変数へ控えて、その変数を渡す
'     → ★ [MOST IMPORTANT] The workbook to check (vWb) must always be specified (it cannot be omitted).
'        After the "open file" component runs, ActiveWorkbook switches to the opened file,
'        so keep it in a variable right after opening and pass that variable.
'
'   ・ブックに何も設定していない変数（Nothing）を渡すと、エラーで止まる（vbObjectError + 1010）
'     → Passing a workbook variable that has not been set (Nothing) stops with an error (+1010).
'
'   ・確認対象はワークシートのみ（グラフシートは存在していても False を返す）
'     → Only worksheets are checked (chart sheets return False even if they exist).
'
'   ・シート名の大文字・小文字は区別されない
'     → Sheet names are compared case-insensitively.
'
'   ・シート名が空白・不正な場合は False を返す（エラーにはならない）
'     → An empty or invalid name also returns False (no error is raised).
'
'   ・Offset / Find / Resize / With は禁止
'     → Offset, Find, Resize, and With statements are prohibited.
'===========================================================

'===========================================================
' ■依存関係（部品同士） / Component Dependencies
'   ・なし（土台の部品。他の部品を参照しない。単独で使用可能）
'     → No required dependencies; this is a foundation component and is standalone.
'
'   ・シート名変更（RenameSheet）などのシート操作系の部品の「前」に呼び出して、
'     重複・不存在を事前に確認する使い方が多い
'     → Often called before RenameSheet or other sheet-operation components
'        to check for duplicates or missing sheets in advance.
'===========================================================

'===========================================================
' ■依存関係（シート・表） / Sheet Dependencies
'   ・特になし（マッピング表等は不要）
'     → No sheet-level dependencies (no mapping table etc. required).
'===========================================================

'===========================================================
' ■技術解説 / Technical Notes
'
'   ・Sub ではなく Function（関数）にしている理由
'       → 「存在する／しない」という結果を呼び出し側へ返す必要があるため。Sub では結果を返せない。
'       → The result (exists / does not exist) must be returned to the caller, which a Sub cannot do.
'
'   ・Function の呼び出し方（Sub との違い）
'       → 戻り値を使う場合は、引数を「かっこ」で囲んで呼び出す。
'            If 部品_シート存在チェック(ThisWorkbook, "入力") Then ...
'       → かっこなしや Call で呼ぶと戻り値が捨てられ、判定できない。
'       → Wrap the arguments in parentheses to use the return value.
'          Calling without parentheses or with Call discards it, so no check is possible.
'
'   ・ブックを、省略できない引数にしている理由
'       → シート名（文字列）だけでは、どのブックのシートか決まらない。
'          ブックを必ず引数で渡す形にすると、呼び出しの行に「どのブックを調べるか」が書かれ、
'          ThisWorkbook 用・ActiveWorkbook 用の部品を、1つにまとめられる。
'          渡し忘れた場合も、実行前に「引数は省略できません」のエラーになり、気づきやすい。
'       → A sheet name alone does not identify the workbook. Always passing the workbook puts
'          "which workbook to check" in the call itself and lets one component serve both
'          ThisWorkbook and ActiveWorkbook; a forgotten argument is caught before running.
'
'   ・シート（Worksheet）ではなく、シート名を引数にする理由
'       → 存在しないシートを ThisWorkbook.Worksheets("名前") で取得しようとすると、
'          その時点で「インデックスが有効範囲にありません」のエラーになり、部品に届かない。
'          「存在するかを調べる」部品は、シートがなくても受け取れる文字列（シート名）で受け取る必要がある。
'       → Getting a missing sheet with ThisWorkbook.Worksheets("name") already raises
'          "Subscript out of range" at the call site, before the component runs.
'          A component that checks existence must receive something that exists even when the sheet
'          does not: the sheet name as a string.
'
'   ・On Error GoTo で判定する理由
'       → Worksheets("存在しない名前") は実行時エラー（添字が範囲外）になる。
'          そのエラーを利用し、「エラーになれば存在しない」と判定する。
'          エラーでマクロを止めず、False を返して呼び出し側へ戻すため。
'       → Worksheets("missing name") raises a runtime error (subscript out of range).
'          The error is trapped and treated as "does not exist", returning False
'          instead of stopping the macro.
'
'   ・ブックが Nothing のとき、False ではなく、エラーで止める理由
'       → ブックが設定されていない変数を渡すと、「シートが存在しない」と誤って判定されるおそれがある。
'          設定の誤りは、結果（False）として返さず、エラーで止めて原因を示す。
'       → A workbook variable that was never set could be mistaken for "the sheet does not exist";
'          the component stops with an error naming the cause instead of returning False.
'
'   ・Worksheets を使い、Sheets を使わない理由
'       → Sheets はグラフシートを含むため、ワークシートのみを対象にする本部品では
'          Worksheets を使う（後続でワークシートとして操作する前提）。
'       → Sheets also includes chart sheets; Worksheets is used because
'          this component targets worksheets only, which are operated on afterwards.
'
'   ・Offset / Find / Resize / With を禁止する理由
'       → 生成AIが誤って不正な範囲操作を行う可能性が高く、
'          行数可変の処理で誤動作を引き起こしやすいため。
'       → These statements often cause misaligned or ambiguous range operations
'          when generated by AI, leading to unpredictable behavior.
'
'   ・本部品が「土台」である理由
'       → シート名変更・シートコピー・シート削除・転記など、多くの部品がシートの存在確認を必要とし、
'          しかも他の部品を参照せずに単独で動くため。
'       → Many components need a sheet-existence check, and this works on its own
'          without referencing other components.
'===========================================================

'---------------------------------------------
' ■引数（型＋意味） / Arguments
'   vWb        : 調べるブック（Workbook）※必須（省略できない）
'                → Workbook to check (Workbook); required.
'
'   vSheetName : 存在を確認したいシートのシート名（String）
'                → Name of the worksheet whose existence is checked (String).
'---------------------------------------------

'---------------------------------------------
' ■戻り値（型＋意味） / Return Value
'   Boolean : 指定したブックにシートが存在する場合は True、存在しない場合は False
'             → True if the worksheet exists in the specified workbook, otherwise False.
'---------------------------------------------

'---------------------------------------------
' ■エラー / Errors (Err.Raise)
'   ・vbObjectError + 1010：ブック（vWb）が Nothing
'---------------------------------------------

'===========================================================
' ■禁止事項（AI向け） / Prohibitions
'   ・Function を Sub（プロシージャ）に変更することの禁止
'     → Do not convert this Function into a Sub; the Boolean return value is essential.
'
'   ・戻り値（Boolean）を確認せずに後続処理を行うことの禁止
'     → Do not proceed to the following processing without checking the Boolean return value.
'
'   ・調べるブックを省略することの禁止（必ず引数で指定する）
'     → Do not omit the workbook to check; always specify it.
'
'   ・シート名の代わりに、Worksheets("名前") で取得したシートを渡すことの禁止
'     （存在しないシートの場合、呼び出しの時点でエラーになる）
'     → Do not pass a sheet obtained with Worksheets("name") instead of the name
'        (a missing sheet raises an error at the call).
'
'   ・セル参照の直書き禁止（Range("A1") など）
'     → Hard-coded cell references are prohibited.
'
'   ・Offset禁止
'     → Offset may cause misaligned row calculations.
'
'   ・Find禁止
'     → Find leads to unpredictable search behavior.
'
'   ・Resize禁止
'     → Resize may unintentionally expand ranges.
'
'   ・With禁止
'     → With blocks cause ambiguous object references.
'===========================================================

'===========================================================
' ■使用例（サンプルコード） / Example
'   ＜例1：マクロのファイル（ThisWorkbook）を調べる / Example 1: check the macro file＞
'   If 部品_シート存在チェック(ThisWorkbook, "入力") Then
'       ThisWorkbook.Worksheets("入力").Activate
'   Else
'       MsgBox "シート「入力」が存在しません"
'   End If
'
'   ＜例2：開いたファイルを調べる / Example 2: check an opened file＞
'   Dim wbDst As Workbook
'
'   If 部品_ファイルを開く("E:\TEST\テンプレート.xlsx") = False Then Exit Sub
'   Set wbDst = ActiveWorkbook                          '開いた直後に控える / keep it right after opening
'
'   If 部品_シート存在チェック(wbDst, "帳票") = False Then
'       MsgBox "テンプレートにシート「帳票」がありません"
'   End If
'
'   ＜例3：シート名変更の前に、重複を確認する / Example 3: check for a duplicate before renaming＞
'   If 部品_シート存在チェック(ThisWorkbook, "TEMP") = False Then
'       MsgBox "シート「TEMP」が存在しません"
'   ElseIf 部品_シート存在チェック(ThisWorkbook, "入力_2026") Then
'       MsgBox "「入力_2026」は既に存在します"
'   Else
'       isRenamed = 部品_シート名変更(ThisWorkbook.Worksheets("TEMP"), "入力_2026")
'   End If
'===========================================================

'===========================================================
' ■ラッパー関数（日本語名） / Wrapper Function
'   ・辞書の日本語名で呼び出すための窓口
'     → Entry point callable by the Japanese dictionary name.
'
'   ・内部では英語名の本体処理を呼び出し、結果（Boolean）をそのまま返す
'     → Internally calls the English-named core function and returns its result (Boolean) as it is.
'===========================================================
Function 部品_シート存在チェック( _
        ByVal vWb As Workbook, _
        ByVal vSheetName As String) As Boolean

    '本体処理（英語名）を呼び出し、結果をそのまま返す / Call core function and return its result
    部品_シート存在チェック = f_SheetExists(vWb, vSheetName)

End Function

'===========================================================
' ■本体処理（英語名） / Core Function
'   ・指定したブックに、指定したシートが存在するかを判定する
'     → Checks whether the specified worksheet exists in the specified workbook.
'
'   ・存在する場合：True、存在しない場合：False を返す
'     → Returns True if it exists and False if it does not.
'===========================================================
Function f_SheetExists( _
        ByVal vWb As Workbook, _
        ByVal vSheetName As String) As Boolean

    Dim ws As Worksheet

    f_SheetExists = False

    '---------------------------------------------
    ' ■ブックが設定されているかを確認（Nothing の場合はエラーで止める）
    '   ※ On Error GoTo より前に置く（Err.Raise を False に変えず、呼び出し側へ届けるため）
    '   / Check that the workbook is set (stop with an error if Nothing);
    '     placed before On Error GoTo so that Err.Raise reaches the caller
    '---------------------------------------------
    If vWb Is Nothing Then
        Err.Raise vbObjectError + 1010, "f_SheetExists", _
                  "調べるブック（vWb）が設定されていません（Nothing）。"
    End If

    '---------------------------------------------
    ' ■エラー時は ErrHandler へ（存在しない＝False）
    '   / On error, jump to ErrHandler (does not exist = False)
    '---------------------------------------------
    On Error GoTo ErrHandler

    '---------------------------------------------
    ' ■シートの取得（存在しなければここでエラー）
    '   / Get the sheet (raises an error here if it does not exist)
    '---------------------------------------------
    Set ws = vWb.Worksheets(vSheetName)

    f_SheetExists = True
    Exit Function

ErrHandler:
    f_SheetExists = False

End Function
