忍者ブログ

splitしてタイトルをつけるマクロ②

2020年04月29日
前回作ったマクロが、うまく動作しなかったので修正版。

データ項目が同じとは限らないなんて。。。


開発着手したら工数かかるからこういうのは事前につぶしておきたいですな。


タイトル行が一致しない場合は、全部のタイトル行を舐めて
一致した列にデータを出力する仕様を考えた。

Loopを組んで、一致したセルを探すならいっそのことDic配列でよくね?

で、組んでみたらエラー検出用のタイトルアレーも不要に。


まずInputBoxで行を指定。その行のタイトル列を基準にする。

チェックしている行にタイトル文字列があれば=以降のデータをその列に格納。
なければエラー出力。

以下、ソース。


Option Explicit
Sub RA_Split()
   
    Dim Col As Long:        Col = Selection.Column
    Dim Egyo As Long:     Egyo = Cells(Rows.Count, Col).End(xlUp).Row
    Dim Tgyo As Long:       Tgyo = Col2Tgyo(Col)
    Dim i As Long '配列格納用変数
    Dim iMax As Long: iMax = Egyo - Tgyo
    
    If Egyo = 1 Then
        MsgBox "データがありません"
        Exit Sub
    End If
    
    Dim Tcell As Range: Set Tcell = Cells(Tgyo, Columns.Count).End(xlToLeft).Offset(0, 1)
'    If MsgBox("「" & Cells(Tgyo, Col).Value & "」列の内容を「" & Tcell.Address & "」セルに出力します", vbOKCancel) = vbCancel Then
'        Exit Sub
'    End If
    
    Dim TargetGyo   '★
    TargetGyo = InputBox("「" & Cells(Tgyo, Col).Value & "」列の内容を「" & Tcell.Address & "」セルに出力します。一般行を指定してください。")
    
    If TargetGyo = "" Then Exit Sub
    If TargetGyo < Tgyo + 1 Then Exit Sub
    If TargetGyo > Egyo Then Exit Sub   '文字列もここに入る
    
Dim tictoc As Double
tictoc = Timer
    
    Dim Gyo As Long: Gyo = TargetGyo 'タイトル列数が行によって違うので指定を可変に
'    Dim Gyo As Long: Gyo = Tgyo + 1 '行を定義して、2行目を実行してサイズ検証
        Dim buf, mbuf, k As Long    '「(」と「=」でsplit用のバッファと配列ループ用変数
        buf = Split(Replace(Cells(Gyo, Col).Value, ")", ""), "(")   ' 「)」を消して、「(」でsplit
        
        Dim Arr()   '2配列
        ReDim Arr(iMax, UBound(buf))    '2次元出力配列
            Arr(0, 0) = "Text" 'メッセージテキストのタイトルは決め打ち
            
        Dim t As Long, tDic  'ループ変数とタイトルDic配列
        Set tDic = CreateObject("scripting.dictionary") 'これを宣言しないと使えない★
    
        For k = 1 To UBound(buf)
            mbuf = Split(buf(k), "=")
            Arr(0, k) = mbuf(0)    '先にタイトルを確定させる
            tDic.Add mbuf(0), k     'タイトルLookup用にDicを作っておく  ★
        Next k
    
    For i = 0 To iMax  'タイトル行から最終行まで
        Gyo = i + Tgyo
        buf = Split(Replace(Cells(Gyo, Col).Value, ")", ""), "(")   ' 「)」を消して、「(」でsplit
        For k = 1 To UBound(buf)
            mbuf = Split(buf(k), "=")
            
            If Not tDic.exists(mbuf(0)) Then
                Debug.Print "タイトル行エラー i=" & i & "、k=" & k & "、タイトル=" & mbuf(0)
            Else
                t = tDic(mbuf(0))
                Arr(i, t) = mbuf(1)
            End If
            Arr(i, 0) = buf(0)  'メッセージ部
        Next k
    Next i
    
    ''出力
    Call 配列貼り付け_2d(Tcell, Arr)
    
Debug.Print "[" & Now & "] "; Format(Timer - tictoc, "0.00秒")
End Sub
Sub 配列貼り付け_2d(Target As Range, oArr, Optional ColCnt As Long = 0) '配列貼り付け便利モジュール
    Dim iRowMax:    iRowMax = UBound(oArr, 1) - LBound(oArr, 1) + 1 '// 1次元目の要素数を取得 '// 二次元配列の最大行数
    Dim iColMax:    iColMax = UBound(oArr, 2) - LBound(oArr, 2) + 1 '// 2次元目の要素数を取得'// 二次元配列の最大列数
    
    '// Rangeオブジェクトで開始セルから貼り付けるセル範囲を拡張する場合
    If ColCnt > 0 And ColCnt <= iColMax Then
        Target.Resize(iRowMax, ColCnt).Value = oArr
    Else
        Target.Resize(iRowMax, iColMax).Value = oArr
    End If
End Sub
Function Col2Tgyo(Col As Long) As Long
    If Cells(1, Col) <> "" Then
        Col2Tgyo = 1
    Else
        Col2Tgyo = Cells(1, Col).End(xlDown).Row
    End If
End Function

PR
Comment
  Vodafone絵文字 i-mode絵文字 Ezweb絵文字