EXCEL VBA Rangeオブジェクトのアクセスを簡単にする。<clsRange>
Addressで返すオブジェクト(Selectなどなど)が、A1などの形式で、R1C1形式で取得するの難しくありませんか?
特に複数範囲選択されていると、目が回ります。
そんなときに、このclsRangeを利用すると、Address値を入れるだけで、R1C1形式での取得や、選択範囲全体の列番号を取得できます。
イメージ
サンプル
Dim cRange As New clsRange cRange.Address = "B2:C2,D4:D5" Debug.Print cRange.Address Debug.Print cRange.SubAddress_count Debug.Print cRange.FirstRow Debug.Print cRange.LastRow Debug.Print cRange.Right Debug.Print cRange.Left Debug.Print cRange.SubAddress_address(1) Debug.Print cRange.SubAddress_address(2) Debug.Print cRange.SubAddress_address_FirstRow(1) Debug.Print cRange.SubAddress_address_LastRow(1) Debug.Print cRange.SubAddress_address_Left(1) Debug.Print cRange.SubAddress_address_Right(1) cRange.Debug用_新しいシートでSubAddress指定状況を表示する
EXCEL VBA クラスモジュールの利用方法 - pgbigorokuのブログ
クラス1つめ
'オブジェクト名は「clsRangeOneItem」にしてください。 ' クラス「clsRange」を利用するために必要なクラスです。 ' ' '機能 選択セル1つの、「行番号」・「列番号」および「SubRange番号」の値を保持する。 ' 'URL https://pgbigoroku.hatenablog.com/entry/2022/08/25/232622 '2022/8/23 Option Explicit Public lng行番号 As Long Public int列番号 As Integer Public intSubAddress番号 As Integer ' '機能 このセルで指定した位置「行番号、列番号、SubRange番号」と ' このセルで指定する位置「行番号、列番号、SubRange番号」 ' が一致するか? ' '引数 'ByVal plng行番号 As Long この行番号と一致するか?(-1の場合すべての数を受け入れ) 'ByVal pint列番号 As Integer この列番号と一致するか?(-1の場合すべての数を受け入れ) 'ByVal pintSubRange番号 As Integer このSubRange番号と一致するか?(-1の場合すべての数を受け入れ) ' '戻り値 ' TRUE 一致する ' FALSE 一致しない ' Public Function is自信の位置情報と一致するか(ByVal plng行番号 As Long, _ ByVal pint列番号 As Integer, _ ByVal pintSubRange番号 As Integer) As Boolean If plng行番号 = -1 Then 'OK is自信の位置情報と一致するか = is自信の位置情報と一致するか_Sub(pint列番号, pintSubRange番号) ElseIf plng行番号 = lng行番号 Then 'OK is自信の位置情報と一致するか = is自信の位置情報と一致するか_Sub(pint列番号, pintSubRange番号) Else is自信の位置情報と一致するか = False End If End Function ' 上の関数「is自信の位置情報と一致するか」のサブルーチン Private Function is自信の位置情報と一致するか_Sub(ByVal pint列番号 As Integer, _ ByVal pintSubRange番号 As Integer) As Boolean If pint列番号 = -1 Then 'OK is自信の位置情報と一致するか_Sub = is自信の位置情報と一致するか_Sub_Sub(pintSubRange番号) ElseIf pint列番号 = int列番号 Then 'OK is自信の位置情報と一致するか_Sub = is自信の位置情報と一致するか_Sub_Sub(pintSubRange番号) Else is自信の位置情報と一致するか_Sub = False End If End Function ' 上の関数「is自信の位置情報と一致するか_Sub」のサブルーチン Private Function is自信の位置情報と一致するか_Sub_Sub(ByVal pintSubRange番号 As Integer) As Boolean If pintSubRange番号 = -1 Then 'OK is自信の位置情報と一致するか_Sub_Sub = True ElseIf pintSubRange番号 = intSubAddress番号 Then 'OK is自信の位置情報と一致するか_Sub_Sub = True Else is自信の位置情報と一致するか_Sub_Sub = False End If End Function
クラス2つめ
'オブジェクト名は「clsRange」にしてください。 ' ' クラス機能 : Rangeオブジェクトのアクセスを簡単にするクラス ' ' 'URL https://pgbigoroku.hatenablog.com/entry/2022/08/25/232622 '2022/8/23 Option Explicit Public mcll1つの選択セル As New Collection Public mcllSubAddress As New Collection Private Const pclng行最大値 As Long = 1048576 '_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ ' Addressプロパティ '_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Property Let Address(pstrAddress As String) Dim cRangeOneItem As clsRangeOneItem Dim varFor As Variant Call nisubCollectionClear(mcll1つの選択セル) Call nisubCollectionClear(mcllSubAddress) For Each varFor In Range(pstrAddress) Set cRangeOneItem = New clsRangeOneItem cRangeOneItem.int列番号 = varFor.Column cRangeOneItem.lng行番号 = varFor.Row cRangeOneItem.intSubAddress番号 = 0 mcll1つの選択セル.Add cRangeOneItem Next Call psubSubAddressを計算し代入するメイン End Property Property Get Address() As String Address = nistrコレクションが文字列の場合結合する(mcllSubAddress, ",") End Property '_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ ' SubAddress取得関連 '_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ ' ' SubAddressの数を取得 ' Property Get SubAddress_count() As Integer SubAddress_count = mcllSubAddress.Count End Property ' ' SubAddressの値を取得 ' Property Get SubAddress_address(ByVal pintNo As Integer) As String SubAddress_address = mcllSubAddress(pintNo) End Property Public Function SubAddress_address_FirstRow(ByVal pintNo As Integer) As Long Dim cRange As New clsRange cRange.Address = Me.SubAddress_address(pintNo) SubAddress_address_FirstRow = cRange.FirstRow End Function Public Function SubAddress_address_LastRow(ByVal pintNo As Integer) As Long Dim cRange As New clsRange cRange.Address = Me.SubAddress_address(pintNo) SubAddress_address_LastRow = cRange.LastRow End Function Public Function SubAddress_address_Right(ByVal pintNo As Integer) As Integer Dim cRange As New clsRange cRange.Address = Me.SubAddress_address(pintNo) SubAddress_address_Right = cRange.Right End Function Public Function SubAddress_address_Left(ByVal pintNo As Integer) As Integer Dim cRange As New clsRange cRange.Address = Me.SubAddress_address(pintNo) SubAddress_address_Left = cRange.Left End Function '_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ ' デバッグ用特殊関数関連 '_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Public Sub Debug用_新しいシートでSubAddress指定状況を表示する() Dim wkb出力先 As Workbook Set wkb出力先 = Workbooks.Add Dim intFor1つのSubAddress As Integer For intFor1つのSubAddress = 1 To mcllSubAddress.Count Dim cRange As New clsRange cRange.Address = mcllSubAddress(intFor1つのSubAddress) Call 指定シートの指定範囲に同じ値を入力する(cRange, wkb出力先.Worksheets(1), intFor1つのSubAddress) Next End Sub ' 指定シートの指定範囲に同じ値を入力します。 ' '引数 'ByRef pcRange情報 As clsRange 挿入するRangeAddressが入ったclsRangeクラス 'ByVal pwks挿入先シート As Worksheet 挿入先のWorksheet 'ByVal pstr挿入する値 As String 挿入するデータ Private Sub 指定シートの指定範囲に同じ値を入力する(ByRef pcRange情報 As clsRange, _ ByVal pwks挿入先シート As Worksheet, _ ByVal pstr挿入する値 As String) Dim rng対象 As Range Dim varForセル As Variant Set rng対象 = pwks挿入先シート.Range(pcRange情報.Address) For Each varForセル In rng対象 varForセル.Value = pstr挿入する値 Next End Sub '_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ ' SubAddressを計算し代入する。 '_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ ' ' SubAddressを計算し代入するメイン ' Private Sub psubSubAddressを計算し代入するメイン() Dim intSubAddressCount As Integer Dim strTemp As String intSubAddressCount = 1 strTemp = "-" Do Until strTemp = "" strTemp = pstrSerchSqure(intSubAddressCount) If strTemp = "" Then Exit Do mcllSubAddress.Add strTemp intSubAddressCount = intSubAddressCount + 1 Loop End Sub Private Function pstrSerchSqure(ByVal pintSubAddressCount As Integer) As String Dim lng1FirstRow As Long Dim int2FirstCol As Integer Dim lng3LastRow As Long Dim int4LastCol As Integer '1. lng1FirstRow = pintSubAddressを振っていない一番初めの行を探す() If lng1FirstRow = 0 Then pstrSerchSqure = "" Exit Function End If '2 int2FirstCol = pint指定行の最初にSqureフラグがない列を戻す(lng1FirstRow) '3 lng3LastRow = plng何行目までデータが続くか(lng1FirstRow, int2FirstCol) '4 int4LastCol = pint何列目までデータが続くか(lng1FirstRow, lng3LastRow, int2FirstCol) Call pbln指定したSubbAddressの1つの選択せるのSubAddressを設定する(lng1FirstRow, int2FirstCol, lng3LastRow, int4LastCol, pintSubAddressCount) pstrSerchSqure = nistrA1形式FromR1C1形式(lng1FirstRow, int2FirstCol, lng3LastRow, int4LastCol) End Function '_____________________(1)________________________________________________ ' 選択セル全体の一番初めの行 ' '戻り値 ' 1以上 一番初めの行 ' 0 すべてSubAddress番号がふられているとき Private Function pintSubAddressを振っていない一番初めの行を探す() As Long Dim lngRet As Long Dim oneitem As clsRangeOneItem lngRet = pclng行最大値 For Each oneitem In mcll1つの選択セル If oneitem.lng行番号 < lngRet Then If oneitem.intSubAddress番号 = 0 Then lngRet = oneitem.lng行番号 End If End If Next If lngRet = pclng行最大値 Then pintSubAddressを振っていない一番初めの行を探す = 0 Else pintSubAddressを振っていない一番初めの行を探す = lngRet End If End Function Private Sub pbln指定したSubbAddressの1つの選択せるのSubAddressを設定する _ (ByVal plngFirstRow As Long, _ ByVal pintFirstCol As Integer, _ ByVal plngLastRow As Long, _ ByVal pintLastCol As Integer, _ ByVal pintSubAddressCount As Integer) Dim lngForRow As Long Dim intForCol As Integer For lngForRow = plngFirstRow To plngLastRow For intForCol = pintFirstCol To pintLastCol Call pbln指定したSubbAddressの1つの選択せるのSubAddressを設定するSub(lngForRow, intForCol, pintSubAddressCount) Next Next End Sub Private Sub pbln指定したSubbAddressの1つの選択せるのSubAddressを設定するSub(ByVal plngFirstRow As Long, ByVal pintFirstCol As Integer, ByVal pintSubAddressCount As Integer) Dim oneitem As clsRangeOneItem For Each oneitem In mcll1つの選択セル If oneitem.is自信の位置情報と一致するか(plngFirstRow, pintFirstCol, 0) Then oneitem.intSubAddress番号 = pintSubAddressCount End If Next End Sub '_____________________(2)________________________________________________ Private Function pint指定行の最初にSqureフラグがない列を戻す(ByVal plngRow As Long) As Integer Dim intRet As Integer Dim oneitem As clsRangeOneItem For Each oneitem In mcll1つの選択セル If oneitem.lng行番号 = plngRow Then If oneitem.intSubAddress番号 = 0 Then If intRet = 0 Then intRet = oneitem.int列番号 Else If intRet > oneitem.int列番号 Then intRet = oneitem.int列番号 End If End If End If End If Next pint指定行の最初にSqureフラグがない列を戻す = intRet End Function '_____________________(3)________________________________________________ Private Function plng何行目までデータが続くか(ByVal plngRow As Long, ByVal pintCol As Integer) As Long Dim lngForRow As Long lngForRow = plngRow + 1 Do While pblnExsit(lngForRow, pintCol, 0) = True lngForRow = lngForRow + 1 Loop plng何行目までデータが続くか = lngForRow - 1 End Function '_____________________(4)________________________________________________ Private Function pint何列目までデータが続くか(ByVal lngRowStart As Long, ByVal lngRowEnd As Long, ByVal intCol As Integer) As Long Dim intForCol As Integer intForCol = intCol + 1 Do While pint何列目までデータが続くかSub(lngRowStart, lngRowEnd, intForCol) = True intForCol = intForCol + 1 Loop pint何列目までデータが続くか = intForCol - 1 End Function Private Function pint何列目までデータが続くかSub(ByVal lngRowStart As Long, ByVal lngRowEnd As Long, ByVal intCol As Integer) As Boolean Dim lngRow As Long For lngRow = lngRowStart To lngRowEnd If pblnExsit(lngRow, intCol, 0) = True Then Else pint何列目までデータが続くかSub = False Exit Function End If Next pint何列目までデータが続くかSub = True End Function '---------------- Private Function pblnExsit(ByVal plngRow As Long, ByVal pintCol As Integer, ByVal intSquareNo As Integer) As Boolean Dim oneitem As clsRangeOneItem For Each oneitem In mcll1つの選択セル If oneitem.is自信の位置情報と一致するか(plngRow, pintCol, intSquareNo) = True Then pblnExsit = True Exit Function End If Next pblnExsit = False End Function ' 選択セル全体の一番初めの行 Public Function FirstRow(Optional ByVal plngStart As Long = 0) As Long Dim lngRet As Long Dim oneitem As clsRangeOneItem If plngStart = 0 Then plngStart = 0 End If If mcll1つの選択セル.Count = 0 Then FirstRow = 0 Else lngRet = pclng行最大値 For Each oneitem In mcll1つの選択セル If oneitem.lng行番号 < lngRet Then If oneitem.lng行番号 >= plngStart Then lngRet = oneitem.lng行番号 End If End If Next FirstRow = lngRet End If End Function Public Function LastRow(Optional ByVal plngEnd As Long = 0) As Long Dim lngRet As Long Dim oneitem As clsRangeOneItem If plngEnd = 0 Then plngEnd = pclng行最大値 End If If mcll1つの選択セル.Count = 0 Then LastRow = 0 Else lngRet = 0 For Each oneitem In mcll1つの選択セル If oneitem.lng行番号 > lngRet Then If oneitem.lng行番号 <= plngEnd Then lngRet = oneitem.lng行番号 End If End If Next LastRow = lngRet End If End Function Public Function Left(Optional ByVal pintStart As Long = 0) As Integer Dim lngRet As Integer Dim oneitem As clsRangeOneItem If pintStart = 0 Then pintStart = 0 End If If mcll1つの選択セル.Count = 0 Then Left = 0 Else lngRet = 16384 For Each oneitem In mcll1つの選択セル If oneitem.int列番号 < lngRet Then If oneitem.int列番号 >= pintStart Then lngRet = oneitem.int列番号 End If End If Next Left = lngRet End If End Function ' Public Function Right(Optional ByVal pintEnd As Integer = 0) As Integer Dim intRet As Integer Dim oneitem As clsRangeOneItem If pintEnd = 0 Then pintEnd = 16384 End If If mcll1つの選択セル.Count = 0 Then Right = 0 Else intRet = 0 For Each oneitem In mcll1つの選択セル If oneitem.int列番号 > intRet Then If oneitem.int列番号 <= pintEnd Then intRet = oneitem.int列番号 End If End If Next Right = intRet End If End Function ' ------------------ 共通関数(https://pgbigoroku.hatenablog.com掲載分)-------------------- ' ' セルの場所指定をA1の文字列形式で取得する。 'https://pgbigoroku.hatenablog.com/entry/2022/08/25/001634 '2021/8/23 Private Function nistrA1形式FromR1C1形式(ByVal plngFirstRow As Long, _ ByVal pintFirstCol As Integer, _ ByVal plngLastRow As Long, _ ByVal pintLastCol As Integer) As String nistrA1形式FromR1C1形式 = Range(Cells(plngFirstRow, pintFirstCol), Cells(plngLastRow, pintLastCol)).Address End Function ' ' コレクションが文字列の場合結合する。 'https://pgbigoroku.hatenablog.com/entry/2022/08/25/094908 '2021/8/21 Private Function nistrコレクションが文字列の場合結合する(ByRef pcll As Collection, ByVal pstrDivide As String) As String Dim strRet As String Dim varFor As Variant On Error GoTo Errnisubコレクションが文字列の場合結合する For Each varFor In pcll strRet = strRet & pstrDivide & varFor Next nistrコレクションが文字列の場合結合する = Mid(strRet, Len(pstrDivide) + 1) Exit Function Errnisubコレクションが文字列の場合結合する: nistrコレクションが文字列の場合結合する = "" Exit Function Resume Next End Function ' ' コレクションのすべてのアイテムを削除する。 ' 'https://pgbigoroku.hatenablog.com/entry/2022/08/25/094125 '2021/8/21 Private Sub nisubCollectionClear(ByRef pcll As Collection) Do Until pcll.Count = 0 pcll.Remove (1) Loop End Sub