VBA_転記処理

### やること
VBAにて、パラメータシートから取得した転記情報を使用し、ワークブック間で転記を行う関数を作成します。

### 転記方法について
#### Paste／PasteSpecial
セルB1:B3の内容をセルD1に貼り付ける場合、転記方法は下記の(1)と(2)の方法があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552400/b11f148d-50ae-b9fd-f8a9-bdc1932f3f29.png)

```vb:(1)
    Range("B1:B3").Copy '対象範囲をコピー
    Range("D1").Select  '貼り付け先を選択
    ActiveSheet.Paste   'アクティブシートに貼り付け（セルD1）
```
```vb:(2)
    Range("B1:B3").Copy       '対象範囲をコピー
    Range("D1").PasteSpecial  '指定セルに貼り付け
```
実行結果は(1)と(2)それぞれ同じで、書式や数式を含む全貼付けされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552400/6a5eecc4-21fe-dbbc-2915-651af005c48f.png)

<b>異なる点</b>
(1)ではPasteメソッド、(2)ではPasteSpecialメソッドを使用しています。
また、RangeオブジェクトにはPasteメソッドが無いため、下記のコードではエラーとなります。
Rangeオブジェクトを使用する時はPasteSpecialメソッドである必要があります。（Cellsも同様）
```vb:(1)*
    Range("B1:B3").Copy
    Range("D1").Paste
```

<b>PasteSpecialメソッドについて</b>
PasteSpecialメソッドでは、先程のように何も指定しないと全貼付けになります。
任意オプションを指定することで、貼り付ける際の細かい操作が可能です。
（形式を選択して貼り付け（Ctrl + Alt + V）のようなもの）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552400/d85273b3-e4e3-53e5-c385-9876d41b2dbe.png)
<b>オプションについて</b>
・Paste：貼り付け形式の指定（参照：[XlPasteType](https://learn.microsoft.com/ja-jp/office/vba/api/excel.xlpastetype)）

|名称|値|説明|
|----|----|----|
|xlPasteAll|-4104|すべて貼り付け|
|xlPasteFormats|-4122|書式を貼り付け|
|xlPasteFormulas|-4123|数式を貼り付け|
|xlPasteValues|-4163|値のみ貼り付け　　　|

<b>xlPasteValues（-4163）</b>と指定した場合の結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552400/4bcf2834-e514-2a1d-6505-a258ba457497.png)
・Operation：貼り付け対象セルに対して、コピーした値と演算する場合に指定。
・SkipBlanks：コピー範囲に含まれる空白セルを貼り付けずにスキップする場合、Trueを指定。
・Transpose：貼り付ける際、行と列を入れ替える場合はTrueを指定。

#### 同ブック、別シート間での転記
コピー時、貼付け時はワークブックオブジェクトを指定しない場合、アクティブシートを操作対象とします。
```vb
    Dim wks1 As Worksheet
    Dim wks2 As Worksheet
    
    Set wks1 = ThisWorkbook.Worksheets("test1")
    Set wks2 = ThisWorkbook.Worksheets("test2")
    
    wks1.Range("B1:B3").Copy
    wks2.Range("A1").PasteSpecial
```

### サンプル
#### 関数_fncCopyAndPaste
パラメータシートの内容を配列に格納したものを使用し、関数にしました。
受け取ったワークシートオブジェクト間で転記をします。
下図はパラメータシートのイメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3552400/7fa1a8fb-c12c-5713-f965-dcd5084ca95c.png)

```vb:fncCopyAndPaste
Function fncCopyAndPaste( _
    ByVal wksInp As Worksheet, _
    ByVal strInpColMin As String, _
    ByVal lngInpRowMin As Long, _
    ByVal strInpColMax As String, _
    ByVal lngInpRowMax As Long, _
    ByVal wksOut As Worksheet, _
    ByVal strOutCol As String, _
    ByVal lngOutRow As Long, _
    ByVal intPasteOption As Integer, _
    ByRef strMsgPrompt As String _
    )
    
    '変数定義
    Dim intRet As Integer
    Dim rngInp As Range
    Dim rngOut As Range
    
    '初期設定
    On Error GoTo Err01
    
    '最下行取得
    If 0 = lngInpRowMax Then
        lngInpRowMax = wksInp.Cells(Rows.Count, 1).End(xlUp).Row
    End If
    
    '入力範囲取得
    Set rngInp = wksInp.Range(strInpColMin & lngInpRowMin, strInpColMax & lngInpRowMax)
    
    '出力範囲取得
    Set rngOut = wksOut.Range(strOutCol & lngOutRow)
    
    '転記
    rngInp.Copy
    rngOut.PasteSpecial Paste:=intPasteOption
    Application.CutCopyMode = False
    
    '終了
    fncCopyAndPaste = 0
    Exit Function
    
Err01:
    intRet = Err.Number
    fncCopyAndPaste = intRet
    strMsgPrompt = "エラー番号：" & intRet & vbCrLf & _
                   "エラー内容：" & Err.Description
                    
End Function
```
#### 呼び出し元
前回作成した配列作成関数の戻り値と組み合わせ、ループ処理にしました。
```vb:呼び出し元
    '配列「入力ファイル一覧」ループ
    For intInpCnt = 0 To UBound(arrInp, 1)
    
        '入力ファイル設定
        strInpID = arrInp(intInpCnt, 0)
        strInpWkb = arrInp(intInpCnt, 3)
        strInpWks = arrInp(intInpCnt, 4)
        
        '入力ファイルを開く
        Set wkbInp = Workbooks.Open(strInpWkb)
        Set wksInp = wkbInp.Worksheets(strInpWks)
        
        '出力ファイルを開く
        Set wkbOut = Workbooks.Open(strOutWkb)
        Set wksOut = wkbOut.Worksheets(strOutWks)
        
        '配列「転記」ループ
        For intCopyCnt = 0 To UBound(GvarListCopy, 1)
        
            If strInpID = GvarListCopy(intCopyCnt, 0) Then
                
                '転記情報取得
                strInpCopyColMin = GvarListCopy(intCopyCnt, 5)
                strInpCopyColMax = GvarListCopy(intCopyCnt, 6)
                lngInpCopyRowMin = GvarListCopy(intCopyCnt, 7)
                lngInpCopyRowMax = GvarListCopy(intCopyCnt, 8)
                strOutCopyColMin = GvarListCopy(intCopyCnt, 14)
                lngOutCopyRowMin = GvarListCopy(intCopyCnt, 15)
                intPasteOption = GvarListCopy(intCopyCnt, 16)
                
                '転記
                RintRet = fncCopyAndPaste(wksInp, _
                                          strInpCopyColMin, _
                                          lngInpCopyRowMin, _
                                          strInpCopyColMax, _
                                          lngInpCopyRowMax, _
                                          wksOut, _
                                          strOutCopyColMin, _
                                          lngOutCopyRowMin, _
                                          intPasteOption, _
                                          RstrMsgPrompt)
                '処理結果確認
                If 0 <> RintRet Then
                    Exit Function
                End If
                
            End If
        Next intCopyCnt
        
        '入力ファイルを保存せずに閉じる
        Application.DisplayAlerts = False
        wkbInp.Close savechanges:=False
        Application.DisplayAlerts = True
        
        '出力ファイルを保存して閉じる
        wksOut.Cells(1, 1).Select
        wkbOut.Close savechanges:=True
        
    Next intInpCnt
```

参考：
https://learn.microsoft.com/ja-jp/office/vba/api/excel.range.pastespecial?f1url=%3FappId%3DDev11IDEF1%26l%3Dja-JP%26k%3Dk(vbaxl10.chm144238)%3Bk(TargetFrameworkMoniker-Office.Version%3Dv16)%26rd%3Dtrue

エンジニアファーストの会社 [株式会社CRE-CO](https://www.cre-co.jp/)　S.K