Подтвердить что ты не робот

Как получить позицию ячейки в пределах диапазона?

Как мне получить относительное положение ячейки внутри диапазона? Поиск позиции ячейки на листе тривиально, используя Row - и Column -properties, но я не уверен, как сделать то же самое в пределах диапазона.

Я рассмотрел возможность использования позиции верхней левой ячейки в диапазоне, в котором я хочу найти позицию ячейки, и просто вычитаю ее (-1) из положения ячейки на листе, но она получает немного громоздким. Есть ли более элегантный способ сделать это?

Моя лучшая попытка, включая тест, до сих пор такова:

Option Explicit

Sub test()
  Dim r As Range: Set r = Sheet1.Range("B2:E10")
  Dim c As Range: Set c = Sheet1.Range("C2")

  Debug.Print "Column in sheet: " & c.Column
  Debug.Print "Row in sheet: " & c.Row
  Debug.Print "Column in range: " & column_in_range(r, c)
  Debug.Print "Row in range: " & row_in_range(r, c)
End Sub

Function column_in_range(r As Range, c As Range) As Long
  column_in_range = c.Column - (r.Cells(1, 1).Column - 1)
End Function

Function row_in_range(r As Range, c As Range) As Long
  row_in_range = c.Row - (r.Cells(1, 1).Row - 1)
End Function

Это дает желаемый результат:

Column in sheet: 3
Row in sheet: 2
Column in range: 2
Row in range: 1

Но мне интересно, есть ли какие-то собственные функции, которые я могу использовать вместо этого?

4b9b3361

Ответ 1

обновлен с использованием варианта, предоставленного lori_m

Но мне интересно, есть ли какие-нибудь нативные функции...

используйте этот

Sub test()
    Dim r As Range, c As Range
    With Sheet1
        Set r = .[B2:E10]
        Set c = .[C2]
    End With
    If Not Intersect(r, c) Is Nothing Then
        Debug.Print "Column in sheet: " & c.Column
        Debug.Print "Row in sheet: " & c.Row
        Debug.Print "Column in range: " & Range(r(1), c).Columns.Count
        Debug.Print "Row in range: " & Range(r(1), c).Rows.Count
    End If
End Sub

Выход

Column in sheet: 3
Row in sheet: 2
Column in range: 2
Row in range: 1

Ответ 2

Не существует собственного способа сделать это. Я также делаю то, что вы упомянули в приведенном выше коде. Однако я добавил несколько дополнительных проверок.

Sub test1()
    Dim r As Range: Set r = Sheet1.Range("B2:E10")
    Dim c As Range: Set c = Sheet2.Range("C2") '<~~ Changed Sheet1 to sheet2
    Dim rng As Range

    On Error Resume Next
    Set rng = Intersect(c, r)
    On Error GoTo 0

    '~~> Check if the range is in main range
    If Not rng Is Nothing Then
        '
        '~~> Rest of your code
        '
    Else
        MsgBox c.Address & " in " & c.Parent.Name & _
               " is not a part of " & _
               r.Address & " in " & r.Parent.Name
    End If
End Sub

Ответ 3

Посмотрите на MSDN, чтобы увидеть больше.

Вы можете использовать что-то вроде:

MsgBox ActiveCell.Address(RowAbsolute:=True, _
                          ColumnAbsolute:=True, _
                          ReferenceStyle:=xlR1C1, _
                          External:=False, _
                          RelativeTo:=Range("B2"))

'Or shorter version :
MsgBox ActiveCell.Address(, , xlR1C1, False, Range("B2"))

Но у вас будет информация о строке и столбце в диапазоне, но не отдельно.

Итак, вам все равно нужно извлечь эти значения из ответа (посмотрите: R18C20) в две функции, поэтому почти та же проблема...

Ответ 4

По-моему, есть почти собственный способ проверить это, но результат - строка, требующая некоторых дополнительных манипуляций. Все, что вам нужно использовать, - это правильная конструкция .Address property (согласно MSDN). Некоторые примеры:

Dim r As Range: Set r = Sheet1.Range("B2:E10")

Dim c As Range: Set c = Sheet1.Range("c2")
Debug.Print c.Address(False, False, xlR1C1, , r.Cells(0, 0))
        '>>result: R[1]C[2]
'-----------------------------------------------------

Set c = Sheet1.Range("e2")
Debug.Print c.Address(False, False, xlR1C1, , r.Cells(0, 0))
        '>>result: R[1]C[4]
'-----------------------------------------------------

Set c = Sheet1.Range("e5")
Debug.Print c.Address(False, False, xlR1C1, , r.Cells(0, 0))
        '>>result: R[4]C[4]
'-----------------------------------------------------

Ответ 5

Я не совсем уверен, что это то, что вам нужно. Но вот оно:

Sub ts2()

    Dim test As Range
    Set test = Range("B2:E10")

    Dim topcorner As Range
    Dim testcell As Range

    Set topcorner = Cells(test.Row, test.Column)
    Set testcell = Range("D7")
    rel_row = testcell.Row - topcorner.Row
    rel_col = testcell.Column - topcorner.Column

End Sub

Таким образом, вы найдете относительную позицию. Но, может быть, вы искали какую-то встроенную функцию? Если это не то, что вам нужно, отредактируйте свой пост...