Есть ли в Excel встроенный метод анализа формул? (т.е.: получить список включенных ссылок RANGE)
Для данной формулы Excel в ячейке я хотел бы иметь возможность проанализировать формулу, чтобы получить список ссылок на диапазон Excel, содержащихся в формуле.
Например, если у меня есть ячейка с этой формулой:
= A + 25 + B
.... Я хотел бы иметь возможность получить массив диапазонов Excel, содержащихся в формуле, поэтому в этом случае он будет содержать [A] и [B]
"Почему ты вообще хочешь это сделать?", Я слышу, как ты спрашиваешь:
Просто один из примеров того, почему я хочу это сделать, - искать "метки" для диапазонов в формулах..... так что, в отличие от простого нажатия клавиш CTRL+~, чтобы просмотреть формулы на моем листе, я бы хотел вариант программного доступа к диапазонным ссылкам в формуле для поиска метки рядом с целевым диапазоном.
Итак, в моем примере выше, я мог бы написать формулы что-то вроде:
=Offset(CellFormulaRanges('TheAddressMyFormulaIsIn',1),0,-1)
=Offset(CellFormulaRanges('TheAddressMyFormulaIsIn',2),0,-1)
... что даст мне метку слева от 1-го и 2-го диапазонов в формуле.
Выполнение этого потребовало бы использования некоторых функций уже в самом Excel, так как написание парсера формул является сложной задачей:
http://ewbi.blogs.com/develops/2004/12/excel_formula_p.html
3 ответа
Спасибо @TimWilliams и @brettdj за то, что они указали мне правильное направление к предыдущим дискуссиям по этой теме, я могу с уверенностью сказать:
НЕТ, EXCEL НЕ ИМЕЕТ МЕТОДА ДЛЯ ПАРСИНГА.
Тем не менее, для моих довольно минимальных целей я придумал что-то, что работает, работает с перекрестными ссылками на листы и может вызываться из UDF.
Тем не менее, он чрезвычайно хрупкий, и есть множество совершенно законных формул, которые, я уверен, не справятся должным образом.
Код является беспорядком и может быть значительно улучшен, но я просто хотел показать его здесь, пока я перехожу к чему-то еще...
РЕДАКТИРОВАТЬ
Также нашел это, что выглядит очень интересно:
http://www.dailydoseofexcel.com/archives/2009/12/05/formula-tokenizer/
Public Function CellPrecedents(cell As Range) As Variant()
Dim resultRanges As New Collection
If cell.Cells.count <> 1 Then GoTo exit_CellPrecedents
If cell.HasFormula = False Then GoTo exit_CellPrecedents
Dim formula As String
formula = Mid(cell.formula, 2, Len(cell.formula) - 1)
If IsRange(formula) Then
resultRanges.Add Range(formula), 1
Else
Dim elements() As String
'Debug.Print formula & " --> "
formula = Replace(formula, "(", "")
formula = Replace(formula, ")", "")
'Debug.Print formula & " --> "
elements() = SplitMultiDelims(formula, "+-*/\^")
Dim n As Long, count As Integer
For n = LBound(elements) To UBound(elements)
If IsRange(elements(n)) Then
'ACTUALLY JUST DO A REDIM PRESERVE HERE!!!!
count = count + 1
'resultRanges.Add Range(Trim(elements(n))) '<--- Do **NOT** store as a range, as that gets automatically Eval()'d
resultRanges.Add Trim(elements(n))
End If
Next
End If
Dim resultRangeArray() As Variant
ReDim resultRangeArray(resultRanges.count)
Dim i As Integer
For i = 1 To resultRanges.count
resultRangeArray(i) = CStr(resultRanges(i)) '// have to store as a string so Eval() doesn't get invoked (I think??)
Next
CellPrecedents = resultRangeArray
exit_CellPrecedents:
Exit Function
End Function
Public Function IsRange(var As Variant) As Boolean
On Error Resume Next
Dim rng As Range: Set rng = Range(var)
If err.Number = 0 Then IsRange = True
End Function
(просто Google SplitMultiDelims для этой функции)
Tbone, еще один вариант, который не совсем то, что вы просили, но может работать как альтернативное решение.
Вместо того, чтобы использовать формулу, чтобы попытаться найти соответствующий ярлык, попробуйте настроить свои формулы так, чтобы они работали на вас. Вот несколько вариантов в зависимости от формулы, которую вы пытались проанализировать. 1. Если ваша формула поиска, вы можете просто сместить, чтобы посмотреть влево. 2. В качестве альтернативы вы можете использовать функцию "Косвенный" в обеих формулах, чтобы убедиться, что они ссылаются на правильное местоположение.
Короче говоря, я думаю, вы хотите сделать часть: Use VBA to generate code to reproduce basic calculations on an Excel worksheet
и использование функции для возврата n-го адреса или имени элемента коллекции DirectPrecedents.
источник: http://www.vb-helper.com/howto_vba_excel_formulas.html
Однако этот вариант использования устарел. По состоянию на Excel 2007 таблицы позволяют гораздо лучшее решение.