[PR]
2025年11月04日
×
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
splitしてタイトルをつけるマクロ①
2020年04月25日
よく出てくるクソデータとして、
1セルの中に長いメッセージがあって、「○○=xxx」って
毎行にタイトル項目を記載するデータ。
見づらさの極み。
今回は、上記のタイトル項目が全行に記載されているテキストを整理する。
整理対象の列のデータは以下の形式
タイトル
メッセージ。(○○=XXX)(○×=YYY)(×○=ZZZ)
メッセージ。(○○=XXX)(○×=BBB)(×○=XYZ)
メッセージ。(○○=XXX)(○×=AAA)(×○=XYX)
やりたいことは、メッセージと各タイトル、各値にsplitすること。
まず、「)」は不要なので置換。replace関数で消す。
次に「(」でsplit
2列目から最終列については、タイトルと値に分割
これは、「=」でsplit
出力先は、データベースの右側にアペンドする形。
タイトル行の最終列に対してoffsetで指定。
いきなりぶっこむマクロなので、確認メッセージを追加。
if msg( ,vbOKCancel) then の形にすると変数を定義しなくていける。
一応、大量データも想定して、配列に格納してからドカンと出力。
配列を出力するモジュールがあれば、結構簡単。
以下、ソース。
   
    
    
    
    
        
            
    
    
    
    
4/26 追記
動かしてみたら、整理対象データの項目数がまちまちで、
タイトル数が行によって違うことが判明。
残念。
不一致の場合は、全体タイトル行を舐めて、一致した列に出力する必要があるなぁ。
お試しの1行処理も、行を選択できるようにしなきゃか。
1セルの中に長いメッセージがあって、「○○=xxx」って
毎行にタイトル項目を記載するデータ。
見づらさの極み。
今回は、上記のタイトル項目が全行に記載されているテキストを整理する。
整理対象の列のデータは以下の形式
タイトル
メッセージ。(○○=XXX)(○×=YYY)(×○=ZZZ)
メッセージ。(○○=XXX)(○×=BBB)(×○=XYZ)
メッセージ。(○○=XXX)(○×=AAA)(×○=XYX)
やりたいことは、メッセージと各タイトル、各値にsplitすること。
まず、「)」は不要なので置換。replace関数で消す。
次に「(」でsplit
2列目から最終列については、タイトルと値に分割
これは、「=」でsplit
出力先は、データベースの右側にアペンドする形。
タイトル行の最終列に対してoffsetで指定。
いきなりぶっこむマクロなので、確認メッセージを追加。
if msg( ,vbOKCancel) then の形にすると変数を定義しなくていける。
一応、大量データも想定して、配列に格納してからドカンと出力。
配列を出力するモジュールがあれば、結構簡単。
以下、ソース。
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 tictoc As Double
tictoc = Timer
    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(), tArr()    '2配列
        ReDim Arr(iMax, UBound(buf))    '2次元出力配列
        ReDim tArr(iMax, UBound(buf))   '2次元タイトル配列(エラーチェック用)
            Arr(0, 0) = "Text" 'メッセージテキストのタイトルは決め打ち
        For k = 1 To UBound(buf)
            mbuf = Split(buf(k), "=")
            Arr(0, k) = mbuf(0)    '先にタイトルを確定させる
        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), "=")
            tArr(i, k) = mbuf(0)
            If UBound(mbuf) = 1 Then
                Arr(i, k) = mbuf(1) '=が入ってないかも
            End If
            If tArr(i, k) <> Arr(0, k) Then
                Debug.Print "タイトル行エラー i=" & i & "k=" & k
            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
4/26 追記
動かしてみたら、整理対象データの項目数がまちまちで、
タイトル数が行によって違うことが判明。
残念。
不一致の場合は、全体タイトル行を舐めて、一致した列に出力する必要があるなぁ。
お試しの1行処理も、行を選択できるようにしなきゃか。
PR
Comment