Вот вид дикой идеей, вдохновленный диаграмме. Создайте следующие, казалось бы, бессмысленные функции в VBA:
Function Owns(Owner As String, ParamArray assets() As Variant) As String
Owns = Owner
End Function
The - написать макрос для замены строк в столбце А по формулам в соответствии с логикой, проявленный:
(очевидно - - вводятся только формулы в A2-A6 - текст в A8-A12 - это только мой комментарий). Чтобы получить их, пропустите столбец A - посмотрите, что они собой представляют, перейдя к столбцу C. Если строка в столбце C также находится в столбце A - поместите весь столбец A (но без столбца C) ссылки на этот актив в качестве аргументов to Owns(). Это относится к первым трем элементам в столбце A. Если актив находится только в столбце C - поместите ссылку на столбец C для этой строки. Это относится к последним двум записям в A.
Зачем вам это нужно ?. Хорошо - выберите ячейку, содержащую Билла Гейтса, перейдите на вкладку «Формула» и повторно вызывайте Trace Precedents
. Вы должны увидеть:
Изюминка: VBA Range объекты имеют метод .Precedents()
, которые дают эти клетки в качестве объекта диапазона. Ключами-предшественниками в столбце C являются листья дерева-прецедента. Существует также метод .DirectPrecedents()
, который может использоваться для обработки уровня дерева по уровню. Независимо от того, полезно ли мне в этом случае, я честно не знаю, но это похоже на хороший способ получить древовидную структуру для ваших данных, которую можно манипулировать в VBA.
On edit: Отслеживание иждивенцев может вернуть вас обратно от T-Bonds к Биллу Гейтсу. Есть два метода VBA, которые соответствуют этому. Кроме того, существуют такие методы, как .ShowPrecedents
, которые можно использовать для анимации стрелок, чтобы пользователь мог видеть поток иждивенцев. Я также экспериментировал с методом (используя вторую фиктивную функцию в некоторых ячейках в C), которая будет иметь ячейки в столбце A, непосредственно связанные с ячейками в столбце C, которые, в свою очередь, связаны с ячейками в столбце A таким образом, что ShowPrecedents
будет отображать обратный и четвертый поток данных - но я думаю, что это добавило бы лишние уровни в дерево.
Я написал макрос, который берет таблицу, созданную как исходную, и добавляет формулы фиктивного кода. Для его использования вам необходимо:
1) Создайте два именованных диапазона. «Владелец», который является столбцом имен владельцев (A2: A6 в этом примере игрушек) и «Asset», который является соответствующей частью столбца активов (C2: C6 здесь).
2) Включите ссылку на Microsoft Scripting Runtime (Инструменты/Ссылки в редакторе VBA), чтобы словари могли использоваться.
Для полноты ради я добавляю код «владеет» снова, а также к югу под названием «восстановить», который заменит добавленные формулы струнами, которые отображаются (которые должны быть оригинальные строки):
Функция владеет (Владелец As String, ParamArray активы() As Variant) As String владеет = Владелец End Function
Sub tag()
Dim Owner As Range, Asset As Range
Dim OwnerAddress As New Dictionary
Dim OwnerFormula As New Dictionary
Dim OwnerRange As Range
Dim ocell As Range, acell As Range
Dim owner_name As Variant, asset_name As String
Dim formula As String
Dim shift As Long
Set Owner = Range("Owner")
Set Asset = Range("Asset")
shift = Asset.Column - Owner.Column '2 now, but user might move columns around
For Each ocell In Owner
owner_name = LCase(Trim(ocell.Value))
If OwnerAddress.Exists(owner_name) Then
OwnerAddress(owner_name) = OwnerAddress(owner_name) & ", " & ocell.Address
Else
OwnerAddress(owner_name) = ocell.Address
End If
Next ocell
For Each owner_name In OwnerAddress.Keys
Set OwnerRange = Range(OwnerAddress(owner_name)) 'e.g. all ocells containing "Bill's Fund"
formula = "=Owns(" & """" & OwnerRange.Cells(1).Value & """"
For Each ocell In OwnerRange
Set acell = ocell.Offset(0, shift)
asset_name = LCase(Trim(acell.Value))
If OwnerAddress.Exists(asset_name) Then
formula = formula & "," & OwnerAddress(asset_name)
Else
formula = formula & "," & acell.Address
End If
Next ocell
formula = formula & ")"
OwnerFormula.Add owner_name, formula
Next owner_name
For Each ocell In Owner
ocell.formula = OwnerFormula(LCase(Trim(ocell.Value)))
Next ocell
End Sub
вы ищете решение VBA? –
Я потерял @JohnColeman, поэтому любое решение приветствуется. Я могу обрабатывать любой язык. –
Просто, чтобы сказать что-то о SQL, так как вы упомянули об этом, вы бы использовали рекурсивный CTE, и это было бы очень просто сделать. (смотря на превосходство сейчас) –