Формула поиска для ссылок на ячейки в VBA - PullRequest
0 голосов
/ 12 ноября 2018

В VBA я хочу найти формулу Excel (String), чтобы найти ссылки на ячейки.

В частности, я хочу найти позицию (и) в строке, где есть относительная ссылка на ячейку (ANY)относительная ссылка на ячейку, а не конкретная), или ссылка на смешанную ячейку.

  • Мне не нужно находить абсолютные ссылки на ячейки, хотя я могу просто проверить и проигнорировать их.
  • Я не против, если ссылка находится на другом листе, я рад найти бит после!символ.
  • Мне нужно убедиться, что он не находит вещи, которые выглядят как ссылки на ячейки в строках или именах листов или имен данных.

Как я могусделать это? (Это главный вопрос)

Мои мысли:

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

Но как найти любые относительные ссылки на ячейки?Единственная идея, которая у меня есть, похожа на вышеизложенную.Помимо ссылок на ячейки, есть ли какие-либо моменты в формулах Excel (вне имен листов или внутри строк), где после буквы стоит число?Любые имена формул или что-нибудь?Единственное, о чем я могу думать, - это определенное имя данных, но я не уверен, что вы можете использовать их в формуле, особенно в формуле условного форматирования).Кто-нибудь может вспомнить другие времена?

У кого-нибудь есть идеи?

1 Ответ

0 голосов
/ 13 ноября 2018

Я не был уверен, каков ваш вариант использования, но вы могли бы попробовать что-то вроде этой функции:

В этом проекте используется Раннее связывание - вы должны установить ссылку на:

Microsoft VBScript Regular Expressions 5.5
Function findCellReferences(vTestVal As Variant) As Variant

    'Check if vTestVal is a range, if so, convert to string
    If TypeName(vTestVal) = "Range" Then
        vTestVal = vTestVal.Formula
    ElseIf TypeName(vTestVal) <> "String" Then
        findCellReferences = "Type-Err!"
        Exit Function
    End If

    Dim oMatches As MatchCollection

    With New RegExp
        .Pattern = "(?:^|[,!(=\s])((?:\$?[A-Z]{1,3}\$?\d+(?::\$?[A-Z]{1,3}\$?\d+)?|" & _
                "\$?[a-z]{1,3}:\$?[a-z]{1,3}|\$?\d+:\$?\d+))(?:$|[\s,)])"
        .IgnoreCase = True
        .Global = True
        If .test(vTestVal) Then
            Dim i As Long, retArr()
            Set oMatches = .Execute(vTestVal)
            With oMatches
                ReDim retArr(.Count - 1)
                For i = 0 To .Count - 1
                    retArr(i) = .Item(i).SubMatches(0)
                Next
            End With
            findCellReferences = Join(retArr, ",")
        Else
            findCellReferences = False
        End If
    End With

End Function

Эта функция может принимать два разных типа данных:

  1. Диапазон
  2. String

Это позволяет использовать эту функцию в качестве функции рабочего листа для проверки текстового значения формулы или использовать ее для непосредственного тестирования входной строки.

ВотВозврат, проверяющий ячейку:

enter image description here

А вот как выглядят формулы для приведенного выше:

enter image description here

Это также можно использовать в VBA:

Sub Test()

    Rem: Passing a string argument
    Debug.Print findCellReferences("A1:B1, $C1")
    ' Prints: A1:B1,$C1

End Sub

Разбивка регулярного выражения: Regex101

(?:^|[,!(=\s])((?:\$?[A-Z]{1,3}\$?\d+(?::\$?[A-Z]{1,3}\$?\d+)?|\$?[a-z]{1,3}:\$?
[a-z]{1,3}|\$?\d+:\$?\d+))(?:$|[\s,)])
  • (?:^|[,(=\s]) Требуется одно из следующих действий до вашего матча
    • ^ Начало строки;или
    • Одиночный символ, представляющий собой
      • , запятую (полезно в формулах)
      • ! восклицательный знак (для Sheet! ссылки)
      • ( открывающая скобка (полезно в формулах)
      • = буквенный знак равенства (полезно в формулах)
      • \s пробельный символ
  • (...) группа захвата, которая будет возвращать ваше значение (один из трех вариантов)
    • \$?[A-Z]{1,3}\$?\d+(?::\$?[A-Z]{1,3}\$?\d+)? не вся строка / столбец
      • \$ дляабсолютная ссылка (столбец), за которой следует ?, что делает его необязательным
      • [A-Z] класс символов для любой буквы, + один или несколько раз
      • \$ для абсолютной ссылки(строка), за которой следует ?, что делает его необязательным
      • \d любая цифра, + один или несколько раз
      • (?:...) группа без захвата для соответствия диапазону диапазонов (например A1:B1)
        • При этом используются те же методы, что и выше
        • , за которыми следует ?, что делает необязательной всю группу захвата
    • \$?[a-z]{1,3}:\$?[a-z]{1,3} Целые столбцы, например A:C
    • \$?\d+:\$?\d+ Целые строки, например 1:3
  • (?:$|[\s,)]) Требуется одно из следующих действий после вашего совпадения
    • $ конец строки;или
    • Один символ, который является одним из
      • \s символ пробела
      • , запятая
      • ) закрывающая скобка

Кредиты:

Предложения tripleee :
- Использовать класс символов[xyz] вместо OR операторов (?:x|y|z)
- лучший отступ для разбивки
- использование грамматики

предложения от Makyen :
- поддержкадля целых строк 1:4 и столбцов A:C
- Ограничить FP путем проверки максимального ограничения столбца в Excel [a-z]{1,3} (вместо [a-z]+)

...