0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

正規表現による検索

Last updated at Posted at 2025-03-23

正規表現による検索2しゅるい

Sub 文字列検索()

  Dim wb As Workbook
  Dim ws As Worksheet

  Set wb = ThisWorkbook
  Set ws = wb.Worksheets("sheet1")

'  汎用変数
  Dim i As Long, k As Long
  Dim rng As Range

'  サーチ用変数(正規表現を使用)

  Dim rg As New RegExp
  Const rgPtn1 As String = "信号"
  Const rgPtn2 As String = "IDコード"
  Const rgPtn3 As String = "削除予定"
  Const rgPtn4 As String = "脅威分析"
  
  Dim topRng_sig As Range
  Dim topRng_id As Range
  Dim topRng_tblOnly As Range
  Dim topRng_q As Range
  
  Dim clm_sig As Long
  Dim clm_id As Long
  Dim clm_tbl As Long
  Dim clm_q As Long
  Dim topRow_sig As Long
  Dim btmRow_sig As Long
  
  Dim ary_for_cmpr() As Variant
  
  Dim sig As String
  Dim sig_k As String
  Dim sig_rp As String
  Dim id_k As String
  
  Dim fst_flg As Boolean
  
'  各対象列、行を検索
  Set topRng_sig = CellSearchByKeyword(rgPtn1, ws)  'wsからrgPtn1を探してrangeを返す
  Do
    Set topRng_sig = topRng_sig.Offset(1)
  Loop While topRng_sig.Value = ""
  topRow_sig = topRng_sig.Row
  clm_sig = topRng_sig.Column
  btmRow_sig = ws.Cells(ws.Rows.Count, clm_sig).End(xlUp).Row

  Set rng = ws.Range(ws.Cells(1, 1), ws.Cells(500, 200))
  Set topRng_id = CellSearchByKeywordVerRange(rgPtn2, rng)  'rngからrgPtn2を探してrangeを返す
  clm_id = topRng_id.Column
  
  Set topRng_tblOnly = CellSearchByKeyword(rgPtn3, ws)  'wsからrgPtn3を探してrangeを返す
  clm_tbl = topRng_tblOnly.Column
  
  Set topRng_q = CellSearchByKeyword(rgPtn4, ws)  'wsからrgPtn4を探してrangeを返す
  clm_q = topRng_q.Column
  
  ReDim ary_for_cmpr(btmRow_sig - topRow_sig, 5)
  For i = 0 To UBound(ary_for_cmpr, 1)
    ary_for_cmpr(i, 0) = ws.Cells(topRow_sig + i, clm_sig)  '信号名格納
    ary_for_cmpr(i, 1) = ws.Cells(topRow_sig + i, clm_id)  'ID格納
    ary_for_cmpr(i, 2) = ws.Cells(topRow_sig + i, clm_tbl)  '削除予定符号格納
    ary_for_cmpr(i, 3) = ws.Cells(topRow_sig + i, clm_q)  '脅威分析格納
'    ary_for_cmpr(,4) 消去行フラグ
'    ary_for_cmpr(,5) CANtableに記載の信号名
  Next i
  
  
  rg.Global = True
  rg.IgnoreCase = False
  
  For i = 0 To UBound(ary_for_cmpr, 1)
    sig = ary_for_cmpr(i, 0)

    For k = 0 To UBound(ary_for_cmpr, 1)
  
      sig_k = ary_for_cmpr(k, 0)
      id_k = ary_for_cmpr(k, 1)
      rg.Pattern = sig & ".+"
      If rg.test(sig_k) Then
        If Right("0000000" & ary_for_cmpr(i, 1), 8) = Right("0000000" & id_k, 8) Then
        
          rg.Pattern = "^0+"
          id_k = rg.Replace(id_k, "")
          If Len(sig_k) - InStr(sig_k, id_k) + 1 = Len(id_k) Then
            sig_rp = ""
            If ary_for_cmpr(i, 2) <> "" Then
              sig_rp = sig
            ElseIf ary_for_cmpr(k, 2) <> "" Then
              sig_rp = sig_k
            End If
            
            If ary_for_cmpr(k, 3) = "" Then
              ary_for_cmpr(k, 4) = True
              ary_for_cmpr(i, 5) = sig_rp
            ElseIf ary_for_cmpr(i, 3) = "" Then
              ary_for_cmpr(i, 4) = True
              ary_for_cmpr(k, 5) = sig_rp
            End If
          End If
          
        End If
      End If
      
    Next k
  Next i
  
  fst_flg = False
'  For i = 0 To UBound(ary_for_cmpr, 1)
'    If ary_for_cmpr(i, 5) <> "" Then
'      ws.Cells(i + topRow_sig, clm_sig) = ary_for_cmpr(i, 5)
'    End If
'  Next i
  For i = 0 To UBound(ary_for_cmpr, 1)
    If ary_for_cmpr(i, 4) = True And fst_flg = False Then
      Set rng = ws.Rows(topRow_sig + i)
      fst_flg = True
    ElseIf ary_for_cmpr(i, 4) = True Then
      Set rng = Application.Union(rng, ws.Rows(topRow_sig + i))
    End If
  Next i
  
'  Selection.Delete
  rng.Select
  
  
End Sub


'検索したいワード、検索の対象範囲となるworksheetを引数にして、検索ワードが存在するrangeを返す
Function CellSearchByKeyword(ByVal srchWrd As String, ByVal ws As Object) As Range

'  引数として受け取るwsをそのまま使用して配列変数にrangeを入れようとするとエラーとなるため定義し直す
  Dim ws_cnv As Worksheet
  Set ws_cnv = ws.Parent.Worksheets(ws.Name)
  
  Dim i As Long
  Dim lp_ary As Variant
  Dim ary_srchRng() As Variant
  Const row_srchRng As Long = 500
  Const clm_srchRng As Long = 200
  Dim multiFindFlag As Boolean
  
  Dim rg As New RegExp
  rg.Global = True
  rg.IgnoreCase = False
  rg.Pattern = srchWrd
  
  ary_srchRng = ws_cnv.Range(ws_cnv.Cells(1, 1), ws_cnv.Cells(row_srchRng, clm_srchRng))
  i = 0
  multiFindFlag = False
  For Each lp_ary In ary_srchRng
    i = i + 1
    If rg.test(lp_ary) = True Then
      If multiFindFlag = True Then
        MsgBox srchWrd & " で検索した結果、複数のセルがヒットしました"
        End
      End If
      Set CellSearchByKeyword = ws_cnv.Cells(i Mod row_srchRng, Int(i / row_srchRng) + 1)
      multiFindFlag = True
    End If
  Next lp_ary
  If CellSearchByKeyword Is Nothing Then
    MsgBox srchWrd & " で検索しましたがヒットしませんでした"
    End
  End If

End Function


'検索したいワード、検索の対象範囲となるrangeを引数にして、検索ワードが存在するrangeを返す
Function CellSearchByKeywordVerRange(ByVal srchWrd As String, ByVal srchRng As Object) As Range
  
  Dim i As Long
  Dim lp_ary As Variant
  Dim ary_srchRng() As Variant
  Dim rows_srchRng As Long
  Dim topRow As Long
  Dim leftClm As Long
  Dim multiFindFlag As Boolean
  
  Dim rg As New RegExp
  rg.Global = True
  rg.IgnoreCase = False
  rg.Pattern = srchWrd
  
  rows_srchRng = srchRng.Rows.Count
  topRow = srchRng.Row
  leftClm = srchRng.Column
  
  ary_srchRng = srchRng
  i = 0
  multiFindFlag = False
  For Each lp_ary In ary_srchRng
    i = i + 1
    If rg.test(lp_ary) = True Then
      If multiFindFlag = True Then
        MsgBox srchWrd & " で検索した結果、複数のセルがヒットしました"
        End
      End If
      Set CellSearchByKeywordVerRange = srchRng.Worksheet.Cells((i Mod rows_srchRng) + topRow - 1, Int(i / rows_srchRng) + leftClm)
      multiFindFlag = True
    End If
  Next lp_ary
  If CellSearchByKeywordVerRange Is Nothing Then
    MsgBox srchWrd & " で検索しましたがヒットしませんでした"
    End
  End If

End Function

Option Explicit

Private wb As Workbook
Private ws As Worksheet

Sub 列単位の配列存在チェック()

  Set wb = ThisWorkbook
  Set ws = wb.Worksheets("存在チェック")
  
  
  Dim i As Long, k As Long
  Dim rng As Range
  
  Dim ary() As Variant
  
  Dim clm_cData As Variant
  Dim rng_lp As Variant
  Dim ary_lp As Variant
  
  Dim ary_chkData() As Variant
  Dim ary_existenceData() As Variant

  Set rng = ws.Range("_配列基準セル1").CurrentRegion
  
  i = 0
  For Each clm_cData In rng.Columns
    k = 0
    For Each rng_lp In clm_cData.Cells
      ReDim Preserve ary(k)
      ary(k) = rng_lp
      k = k + 1
    Next rng_lp
  
    ReDim Preserve ary_chkData(i)
    ary_chkData(i) = ary
    i = i + 1
  
  Next clm_cData
  
  Set rng = ws.Range("_配列基準セル2").CurrentRegion
  i = 0
  For Each clm_cData In rng.Columns
    k = 0
    For Each rng_lp In clm_cData.Cells
      If rng_lp <> "" Then
        ReDim Preserve ary(k)
        ary(k) = rng_lp
        k = k + 1
      End If
    Next rng_lp
  
    ReDim Preserve ary_existenceData(i)
    ary_existenceData(i) = ary
    i = i + 1
  
  Next clm_cData
  
'  For Each ary_lp In ary_chkData
'    For Each rng_lp In ary_lp
'
'    Debug.Print rng_lp
'
'    Next rng_lp
'
'  Next ary_lp
  Dim arytest As Variant
  arytest = PresenceCheck(ary_chkData, ary_existenceData)




End Sub




Function PresenceCheck(ByVal ary_chkData, ByVal ary_existenceData)

  Dim i As Long, k As Long
  Dim flg As Boolean
  Dim ary() As Variant
  
  Dim ary_prsenceCheck(1) As Variant

  Dim chD As Variant
  Dim exD As Variant
  Dim chkRslt As Boolean
  
  i = 0
  k = 0
  For Each chD In ary_chkData
  
    flg = False
    For Each exD In ary_existenceData
      chkRslt = CheckArraysEquality(chD, exD)
      If chkRslt = True Then
        flg = True
        Exit For
      End If
    Next exD
    If flg = False Then
      ReDim Preserve ary(i)
      ary(i) = k
      i = i + 1
    End If
  
    k = k + 1
  Next chD

  If Not Not ary Then
    ary_prsenceCheck(0) = False
    ary_prsenceCheck(1) = ary

  Else
    ary_prsenceCheck(0) = True
  End If
  
  PresenceCheck = ary_prsenceCheck
  


End Function


Function CheckArraysEquality(ByVal ary1, ByVal ary2)

  Dim lp1 As Variant
  Dim lp2 As Variant
  Dim flg As Boolean
  
  If LBound(ary1, 1) <> LBound(ary2, 1) Or UBound(ary1, 1) <> UBound(ary2, 1) Then
    CheckArraysEquality = False
    Exit Function
  End If

  For Each lp1 In ary1
    flg = False
    For Each lp2 In ary2
      If lp1 = lp2 Then
        flg = True
        Exit For
      End If
    Next lp2
    If flg = False Then
      CheckArraysEquality = False
      Exit Function
    End If
  Next lp1
  
  CheckArraysEquality = True



End Function
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?