Excel-VBA, 2 个变量的树模拟
Excel-VBA, Tree simulation with 2 variables
我正在尝试为一个城市的人口出生率建模,在该城市中,每年 T+0 到 T+n,其中 n 是节点数。因此,每 +1 年,城市中可能会剩下 101%、100% 或 99% 的人口。
更复杂的是,城市中的人数必须随时变化。因此,例如,我们知道在第 5 年我们每年获得 +1% 人口的路径。所以在第 5 年我们应该有 (1.01)^5 个人。但是,由于这个城市是动态的,可能会有人离开或进入城市,因此需要对城市人口进行手动调整。
第5年,5000人离开城市到另一个地方。所以 spreadsheet 必须足够动态,以将第 5 级节点从 (1.01)^5 调整到 (1.01)^5 - 5000。第 6 级节点从那里继续......再次分支。
不确定我是否解释得足够清楚。但这似乎真的很难用我的 vba 业余技能编写代码。这可能吗?
我考虑了一下并遇到了以下问题,想知道这是否有意义或者它是否可行:
1) 构建 "tree" 的行插入在计算上是昂贵的,没有办法绕过它。虽然这对于少量节点来说很好,但更大的树只需点击一下宏就需要几个小时! (我打算最多使用 11/12 个节点,这会花费太长时间!)
- 是否可以构建一个解决方案,其中宏计算一旦生成一次就使用相同的 "tree",而不是每次单击都重新生成树。即为了溢出进程,我会 运行 一棵开始时有 12 个节点的树。之后,输入值的调整只会生成在树中显示的值,而不是清理 sheet 并再次插入新行。
2) 让我尽我所能说明这里发生了什么。
用于此测试的初始值 100 将被替换为公式。让我们称这个公式为 (ABSqrt(C) + 6/X),其中 A、B 是常量,X 是 sheet 中的初始移动百分比输入树枝基于哪个。 C 是棘手的一点 - 在手动干预进入之前,这被认为是不变的。
让我们暂时假设一个简单的树模型,有 5 个节点 - 给出以下结构。 1, 3, 9, 27, 81 ,243 ... 3^n,其中 n 是节点数。
运行 此公式的初始输入为 2%,其中 X = 2%。
此时我们得到了一棵漂亮的小树,它有值。
我想在这里建立一个更动态的树,我可以介入例如在节点 3 的第二个值上,调整 C 的输入并查看依赖节点如何变化。所有这些都不会影响先前假定的节点 1 和 2 上的 C 值,并且节点不会直接受此特定值的前向路径影响。
因此在下图中,只有蓝色路径会受到新 C 值输入的影响。这可能吗?我被困住了...
Option Explicit
Public Sub test()
Dim startvalue As Double, levels As Integer, levelchange As Double
Dim counterforlevel As Double, j As Long, i As Long, k As Long
Application.ScreenUpdating = False
startvalue = Sheets("Sheet1").Range("A2")
levels = Sheets("Sheet1").Range("B2")
levelchange = Sheets("Sheet1").Range("c2")
Sheets("Sheet2").Activate
Cells.ClearContents
Range("A1") = startvalue
For j = 2 To levels
counterforlevel = 3 ^ (j - 2)
For k = Cells(Rows.Count, j - 1).End(xlUp).Row To 1 Step -1
If k Mod 10 = 0 Then Application.StatusBar = "Level: " & j & Space(5) & "Processing " & Format(1 - k / counterforlevel, "#0.0%")
If Cells(k, j - 1) <> "" Then
Rows(k + 1).Insert shift:=xlDown
Cells(k + 1, j).Formula = "=" & Cells(k, j - 1).Address(False, False) & "*" & Format(1 - levelchange, "0%")
Cells(k, j).Formula = "=" & Cells(k, j - 1).Address(False, False)
Rows(k).Insert shift:=xlDown
Cells(k, j).Formula = "=" & Cells(k + 1, j - 1).Address(False, False) & "*" & Format(1 + levelchange, "0%")
End If
DoEvents
Next k
Next j
Application.StatusBar = False
End Sub
我有点明白你想做什么。目前还不清楚你打算如何使用最后一个节点中的数据(你将如何可视化结果)
也许你需要使用这样的东西
110 121 132 143 154 10% increase per year
100 100 100 100 100 100 these 3 rows are a reference dataset
90 81 73 66 59 10% decline per year
+10% +10% +10% +10% +10% this can be manually adjusted
upper bound 110 125 136 147 158
100 100 105 105 105 105 scenario
lower bound 90 86 76 69 62
-10% -10% -10% -10% -10%
manual adjust +5
have multiple scenarios on worksheet
could use VBA to fill in the percentage values and transfer the result into another worksheet
我正在尝试为一个城市的人口出生率建模,在该城市中,每年 T+0 到 T+n,其中 n 是节点数。因此,每 +1 年,城市中可能会剩下 101%、100% 或 99% 的人口。
更复杂的是,城市中的人数必须随时变化。因此,例如,我们知道在第 5 年我们每年获得 +1% 人口的路径。所以在第 5 年我们应该有 (1.01)^5 个人。但是,由于这个城市是动态的,可能会有人离开或进入城市,因此需要对城市人口进行手动调整。
第5年,5000人离开城市到另一个地方。所以 spreadsheet 必须足够动态,以将第 5 级节点从 (1.01)^5 调整到 (1.01)^5 - 5000。第 6 级节点从那里继续......再次分支。
不确定我是否解释得足够清楚。但这似乎真的很难用我的 vba 业余技能编写代码。这可能吗?
我考虑了一下并遇到了以下问题,想知道这是否有意义或者它是否可行:
1) 构建 "tree" 的行插入在计算上是昂贵的,没有办法绕过它。虽然这对于少量节点来说很好,但更大的树只需点击一下宏就需要几个小时! (我打算最多使用 11/12 个节点,这会花费太长时间!) - 是否可以构建一个解决方案,其中宏计算一旦生成一次就使用相同的 "tree",而不是每次单击都重新生成树。即为了溢出进程,我会 运行 一棵开始时有 12 个节点的树。之后,输入值的调整只会生成在树中显示的值,而不是清理 sheet 并再次插入新行。
2) 让我尽我所能说明这里发生了什么。 用于此测试的初始值 100 将被替换为公式。让我们称这个公式为 (ABSqrt(C) + 6/X),其中 A、B 是常量,X 是 sheet 中的初始移动百分比输入树枝基于哪个。 C 是棘手的一点 - 在手动干预进入之前,这被认为是不变的。
让我们暂时假设一个简单的树模型,有 5 个节点 - 给出以下结构。 1, 3, 9, 27, 81 ,243 ... 3^n,其中 n 是节点数。 运行 此公式的初始输入为 2%,其中 X = 2%。 此时我们得到了一棵漂亮的小树,它有值。 我想在这里建立一个更动态的树,我可以介入例如在节点 3 的第二个值上,调整 C 的输入并查看依赖节点如何变化。所有这些都不会影响先前假定的节点 1 和 2 上的 C 值,并且节点不会直接受此特定值的前向路径影响。
因此在下图中,只有蓝色路径会受到新 C 值输入的影响。这可能吗?我被困住了...
Option Explicit
Public Sub test()
Dim startvalue As Double, levels As Integer, levelchange As Double
Dim counterforlevel As Double, j As Long, i As Long, k As Long
Application.ScreenUpdating = False
startvalue = Sheets("Sheet1").Range("A2")
levels = Sheets("Sheet1").Range("B2")
levelchange = Sheets("Sheet1").Range("c2")
Sheets("Sheet2").Activate
Cells.ClearContents
Range("A1") = startvalue
For j = 2 To levels
counterforlevel = 3 ^ (j - 2)
For k = Cells(Rows.Count, j - 1).End(xlUp).Row To 1 Step -1
If k Mod 10 = 0 Then Application.StatusBar = "Level: " & j & Space(5) & "Processing " & Format(1 - k / counterforlevel, "#0.0%")
If Cells(k, j - 1) <> "" Then
Rows(k + 1).Insert shift:=xlDown
Cells(k + 1, j).Formula = "=" & Cells(k, j - 1).Address(False, False) & "*" & Format(1 - levelchange, "0%")
Cells(k, j).Formula = "=" & Cells(k, j - 1).Address(False, False)
Rows(k).Insert shift:=xlDown
Cells(k, j).Formula = "=" & Cells(k + 1, j - 1).Address(False, False) & "*" & Format(1 + levelchange, "0%")
End If
DoEvents
Next k
Next j
Application.StatusBar = False
End Sub
我有点明白你想做什么。目前还不清楚你打算如何使用最后一个节点中的数据(你将如何可视化结果)
也许你需要使用这样的东西
110 121 132 143 154 10% increase per year
100 100 100 100 100 100 these 3 rows are a reference dataset
90 81 73 66 59 10% decline per year
+10% +10% +10% +10% +10% this can be manually adjusted
upper bound 110 125 136 147 158
100 100 105 105 105 105 scenario
lower bound 90 86 76 69 62
-10% -10% -10% -10% -10%
manual adjust +5
have multiple scenarios on worksheet
could use VBA to fill in the percentage values and transfer the result into another worksheet