Option Explicit

'===========================================================
' ■部品_範囲コピー_値 / CopyRange_Values
'   ・指定した範囲（Range）を、コピー先の左上セルを起点にして、値だけをコピーする
'     → Copies the specified range (Range), starting at the top-left cell of the destination, values only.
'
'   ・コピー元とコピー先は、範囲設定部品（SetRange_Fixed / SetRange_VariableRows）で作った Range を、そのまま渡す
'     → Pass the Ranges made by the range-setting components as they are.
'
'   ・コピー先のブック・シートは、コピー先の Range が持っているので、ブックを別に指定する必要はない
'     → The destination Range carries its own workbook and sheet; no separate workbook argument is needed.
'
'   ★ この部品は Sub（プロシージャ）ではなく「Function（関数）」で、成功／失敗を Boolean で返す
'     → ★ This component is a Function (not a Sub) that returns success/failure as a Boolean.
'===========================================================

'===========================================================
' ■区分 / Classification
'   ・基礎区分：土台 ／ 用途区分：処理 ／ 操作対象区分：範囲
'     → Base: foundation / Purpose: process / Target: range
'
' ■バージョン / Version
'   ・Version 1.0（2026-10-29）
'===========================================================

'===========================================================
' ■URL（WordPress部品ページ）
'   https://feelcodelab.com/vba_parts/copyrange_values/
'===========================================================

'===========================================================
' ■前提条件（AI誤動作防止の最重要項目） / Preconditions
'   ★【最重要】この部品は Function（関数）であり、戻り値（Boolean）を返す
'     → コピーできた場合は True、実行時にできなかった場合は False（この場合は、エラーでは止まらない）
'     → 呼び出し側は、必ず戻り値を確認してから後続処理を行い、メッセージも呼び出し側で表示する
'       （False のときは、MsgBox のあとに Exit Sub まで書く）
'     → ★ [MOST IMPORTANT] This component is a Function that returns a Boolean: True if copied, False if it
'        failed at run time (no error is raised then). The caller must check the return value before the
'        following processing and show any message itself (write Exit Sub after the MsgBox).
'
'   ★【最重要】コピー元（vSrcRng）とコピー先（vDstTopLeft）は、どちらも Set 済みの Range を渡す
'     → コピー先は、コピーを始める左上の 1 セルを、範囲設定_固定で作って渡す
'       （例：Set dst = 部品_範囲設定_固定(wbDst, "転記先", 3, 1, 3, 1)）
'     → コピー先に複数セルの範囲を渡した場合は、その左上の 1 セルだけを使う
'     → ★ [MOST IMPORTANT] Pass Ranges that have already been set for both the source (vSrcRng) and the
'        destination (vDstTopLeft). Make the destination as a single top-left cell with SetRange_Fixed; if a
'        multi-cell range is passed, only its top-left cell is used.
'
'   ・コピー先の範囲の大きさは、コピー元と同じ行数・列数になる（コピー先では指定しない）
'     → The destination gets the same number of rows and columns as the source (not specified at the destination).
'
'   ・コピーされるのは「値だけ」（書式・罫線・色・入力規則は、コピー先のまま変わらない）。数式は、結果の値になる
'     → Only values are copied; formats, borders, colors and validation at the destination stay as they are, and formulas become their result values.
'
'   ・コピー先に、すでに入っている値は、上書きされる（確認なし）。残したいセルが、コピー先に
'     含まれていないか、呼び出し側で確認する
'     → Existing values in the destination are overwritten without confirmation; the caller must make sure
'        the destination does not include cells that must be kept.
'
'   ・複数の領域（離れたセルの集まり）の範囲は、対象外
'     → Ranges made of several separate areas are out of scope.
'
'   ・設定の誤りは、False ではなく、原因を示すエラーで止まる（Err.Raise）
'       - コピー元（vSrcRng）が Nothing（vbObjectError + 1014）
'       - コピー先（vDstTopLeft）が Nothing（vbObjectError + 1014）
'       - コピー先が、シートの上限（行数・列数）を超える（vbObjectError + 1009）
'     → Setting mistakes stop with an error naming the cause (a Nothing source or destination +1014, a
'        destination beyond the sheet limit +1009).
'
'   ・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.
'
'   ・組み合わせ：f_SetRange_Fixed / f_SetRange_VariableRows → f_CopyRange_Values
'     （範囲設定部品で、コピー元の範囲と、コピー先の左上セルを作ってから、渡す）
'     → Typical combination: [SetRange_Fixed / SetRange_VariableRows] -> [CopyRange_Values]
'        (make the source range and the destination top-left cell, then pass them).
'===========================================================

'===========================================================
' ■依存関係（シート・表） / Sheet Dependencies
'   ・特になし（マッピング表等は不要）
'     → No sheet-level dependencies (no mapping table etc. required).
'===========================================================

'===========================================================
' ■技術解説 / Technical Notes
'
'   ・ブックやシート名ではなく、Range を引数にする理由
'       → 範囲（Range）は、自分がどのブック・どのシートのものかを持っている。
'          ActiveWorkbook を前提にしないので、ファイルを開いて ActiveWorkbook が切り替わっても、
'          コピー先を取り違えない。
'       → A Range carries its own workbook and sheet. Since ActiveWorkbook is not assumed, the destination is
'          not mixed up even after ActiveWorkbook switches by opening a file.
'
'   ・コピー先を、左上の 1 セルで受け取る理由
'       → コピー先の大きさは、コピー元で決まるため。大きさを、コピー先でも指定すると、
'          コピー元と合わない指定ができてしまう。
'       → The destination size is decided by the source; specifying it again would allow a mismatch.
'
'   ・値の代入（Value ＝ Value）を使う理由
'       → Assigning Value to Value copies only the values, without the clipboard, so the destination formats stay and the old copy mode is not disturbed.
'
'   ・通常のコピーと、値だけのコピーを、分けている理由
'       → 動きの違いを、部品名で分かるようにして、取り違えを防ぐため。
'          もう一方の部品は、「部品_範囲コピー」（値・数式・書式のすべてをコピーする） である。
'       → The difference in behavior is shown by the component name; the other component is CopyRange (copies values, formulas and formats).
'
'   ・コピー元・コピー先が Nothing のとき、False ではなく、エラーで止める理由
'       → Set し忘れた Range を渡すと、「コピーに失敗した」と、区別がつかなくなる。
'          設定の誤りは、結果（False）として返さず、エラーで止めて原因を示す。
'       → A Range that was never set would be indistinguishable from "copy failed"; the setting mistake
'          stops with an error naming the cause instead of returning False.
'
'   ・コピー先が、シートの上限を超えるとき、False ではなく、エラーで止める理由
'       → コピー元の大きさと、コピー先の位置から決まる、設定の誤りであるため。
'          False にすると、実行時の失敗（保護されたシートなど）と区別がつかない。
'       → It is a setting mistake decided by the source size and the destination position; returning False
'          would be indistinguishable from a run-time failure (e.g., a protected sheet).
'
'   ・コピーできなかった場合に、False を返す理由
'       → コピー先の保護されたシート、結合セルとの不整合などで、コピーが失敗することがある。
'          呼び出し側が、戻り値で確認できるようにして、メッセージやエラー処理は、呼び出し側で調整できるようにしている。
'          原因は、イミディエイトウィンドウ（Ctrl+G）に、Debug.Print で出る。
'       → Copying can fail (protected sheet, merged cells). The Boolean return value lets the caller check
'          the result; the cause is printed to the Immediate window (Ctrl+G).
'
'   ・確認を On Error GoTo より前に置く理由
'       → On Error GoTo ErrHandler の有効な範囲でエラーを出すと、False に変えられてしまい、原因が伝わらない。
'          確認を前に置くことで、Err.Raise が呼び出し側へ届く。
'       → Raising inside the range where On Error GoTo is active would turn it into False and hide the cause;
'          the check is placed before it so that Err.Raise reaches the caller.
'
'   ・Offset / Find / Resize / With を禁止する理由
'       → 生成AIが誤って不正な範囲操作を行う可能性が高く、行数可変の処理で誤動作を引き起こしやすいため。
'       → These statements often cause misaligned or ambiguous range operations when generated by AI.
'
'   ・本部品が「土台」である理由
'       → 範囲をコピーする処理は、多くの場面で必要になり、しかも他の部品を参照せずに単独で動くため。
'       → Copying a range is needed in many situations, and it works on its own without referencing other
'          components.
'===========================================================

'---------------------------------------------
' ■引数（型＋意味） / Arguments
'   vSrcRng     : コピー元の範囲（Range）。範囲設定部品などで作った、Set 済みの範囲
'                 → Source range (Range); already set, e.g., made by a range-setting component.
'
'   vDstTopLeft : コピー先の左上のセル（Range）。範囲設定_固定で、1 セルとして作った範囲
'                 → Top-left cell of the destination (Range); made as a single cell with SetRange_Fixed.
'---------------------------------------------

'---------------------------------------------
' ■戻り値（型＋意味） / Return Value
'   Boolean : コピーできた場合は True、実行時にできなかった場合は False
'             → True if copied, False if it failed at run time.
'---------------------------------------------

'---------------------------------------------
' ■エラー / Errors (Err.Raise)
'   ・vbObjectError + 1014：コピー元（vSrcRng）またはコピー先（vDstTopLeft）が Nothing
'   ・vbObjectError + 1009：コピー先が、シートの上限（行数・列数）を超える
'---------------------------------------------

'===========================================================
' ■禁止事項（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.
'
'   ・Set していない Range 変数を渡すことの禁止
'     → Do not pass a Range variable that has not been set.
'
'   ・コピー先に、コピー元と同じ大きさの範囲を渡すことの禁止（左上の 1 セルを渡す）
'     → Do not pass a destination range of the same size as the source; pass the top-left cell.
'
'   ・複数の領域の範囲を渡すことの禁止
'     → Do not pass a range made of several separate areas.
'
'   ・Select / Activate / Selection を使ったコピーの禁止（範囲は、引数で渡す）
'     → Do not copy with Select / Activate / Selection; pass the ranges as arguments.
'
'   ・セル参照の直書き禁止（Range("A1") など）
'     → Hard-coded cell references are prohibited; make the range with the range-setting component.
'
'   ・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：転記元の表を、転記先へコピーする / Example 1: copy a source table to a destination＞
'   Dim src As Range
'   Dim dst As Range
'
'   Set src = 部品_範囲設定_行可変(ThisWorkbook, "転記元", 3, 1, 4, 1)   '3行目から、1列目の最終行まで（A-D列）
'   If src Is Nothing Then
'       MsgBox "データがありません"
'       Exit Sub
'   End If
'   Set dst = 部品_範囲設定_固定(ThisWorkbook, "転記先", 3, 1, 3, 1)    '左上の1セル（A3） / the top-left cell (A3)
'
'   If 部品_範囲コピー_値(src, dst) = False Then
'       MsgBox "コピーに失敗しました（シートの保護などを確認してください）"
'       Exit Sub
'   End If
'
'   ＜例2：開いたファイルへコピーする / Example 2: copy into an opened file＞
'   Dim wbDst As Workbook
'
'   If 部品_ファイルを開く("E:\TEST\テンプレート.xlsx") = False Then Exit Sub
'   Set wbDst = ActiveWorkbook                               '開いた直後に控える / keep it right after opening
'
'   Set src = 部品_範囲設定_固定(ThisWorkbook, "入力", 2, 1, 10, 4)
'   Set dst = 部品_範囲設定_固定(wbDst, "帳票", 3, 1, 3, 1)
'   If 部品_範囲コピー_値(src, dst) = False Then MsgBox "コピーに失敗しました": Exit Sub
'
'   ＜例3：数式が入った範囲の、結果だけをコピーする / Example 3: copy only the results of formulas＞
'   数式は、結果の値になって入る（書式は、コピー先のまま変わらない）
'
'   ※ コピー元・コピー先が Nothing の場合や、コピー先がシートの上限を超える場合は、
'      False ではなく、原因を示すエラーで止まる（起点の On Error で受けて、Err.Description を表示する）
'===========================================================

'===========================================================
' ■ラッパー関数（日本語名） / 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 vSrcRng As Range, _
        ByVal vDstTopLeft As Range) As Boolean

    '本体処理（英語名）を呼び出し、結果をそのまま返す / Call core function and return its result
    部品_範囲コピー_値 = f_CopyRange_Values(vSrcRng, vDstTopLeft)

End Function

'===========================================================
' ■本体処理（英語名） / Core Function
'   ・コピー元の範囲を、コピー先の左上セルを起点にして、値だけをコピーする
'     → Copies the source range, starting at the top-left cell of the destination, values only.
'
'   ・コピーできた場合：True、実行時にできなかった場合：False を返す
'     → Returns True if copied and False if it failed at run time.
'===========================================================
Function f_CopyRange_Values( _
        ByVal vSrcRng As Range, _
        ByVal vDstTopLeft As Range) As Boolean

    Dim dstLastRow As Long
    Dim dstLastCol As Long
    Dim wsDst As Worksheet

    f_CopyRange_Values = False

    '---------------------------------------------
    ' ■範囲が設定されているかを確認（Nothing の場合はエラーで止める）
    '   ※ On Error GoTo より前に置く（Err.Raise を False に変えず、呼び出し側へ届けるため）
    '   / Check that the ranges are set (stop with an error if Nothing);
    '     placed before On Error GoTo so that Err.Raise reaches the caller
    '---------------------------------------------
    If vSrcRng Is Nothing Then
        Err.Raise vbObjectError + 1014, "f_CopyRange_Values", _
                  "コピー元（vSrcRng）が設定されていません（Nothing）。"
    End If

    If vDstTopLeft Is Nothing Then
        Err.Raise vbObjectError + 1014, "f_CopyRange_Values", _
                  "コピー先（vDstTopLeft）が設定されていません（Nothing）。"
    End If

    '---------------------------------------------
    ' ■コピー先が、シートの上限を超えないかを確認（超える場合はエラーで止める）
    '   / Check that the destination does not exceed the sheet limit (stop with an error if it does)
    '---------------------------------------------
    dstLastRow = vDstTopLeft.Row + vSrcRng.Rows.Count - 1
    dstLastCol = vDstTopLeft.Column + vSrcRng.Columns.Count - 1

    If dstLastRow > vDstTopLeft.Worksheet.Rows.Count Or dstLastCol > vDstTopLeft.Worksheet.Columns.Count Then
        Err.Raise vbObjectError + 1009, "f_CopyRange_Values", _
                  "コピー先が、シートの上限（" & vDstTopLeft.Worksheet.Rows.Count & "行・" & _
                  vDstTopLeft.Worksheet.Columns.Count & "列）を超えます" & _
                  "（コピー先の終了行=" & dstLastRow & "、終了列=" & dstLastCol & "）。"
    End If

    '---------------------------------------------
    ' ■エラー時は ErrHandler へ（False を返す） / On error, jump to ErrHandler (returns False)
    '---------------------------------------------
    On Error GoTo ErrHandler

    '---------------------------------------------
    ' ■コピー / Copy
    '---------------------------------------------
    Set wsDst = vDstTopLeft.Worksheet
    wsDst.Range(wsDst.Cells(vDstTopLeft.Row, vDstTopLeft.Column), _
                wsDst.Cells(dstLastRow, dstLastCol)).Value = vSrcRng.Value

    f_CopyRange_Values = True
    Exit Function

ErrHandler:
    Debug.Print "f_CopyRange_Values: " & Err.Number & " " & Err.Description
    f_CopyRange_Values = False

End Function
