我在 excel 中有一个 2 变量 100x100 数据表。
我需要一个函数来返回产生给定目标值的所有可能变量集。我正在看的是某种递归二维查找函数。有人可以指出我正确的方向吗?
没有内置功能可以满足您的需求,我对此有 99% 的把握。
可以构建一个返回数组的 VBA 函数,沿着已经显示的快速和肮脏的 Sub 的行。创建一个 Variant 来保存输出,可能 Redimed 到最大可能的结果数量,Redim Preserve-d 到最后的实际数量。然后将其作为函数的结果返回,然后需要将其作为数组函数(Control-Shift-Enter)调用。
一个缺点是您必须确保目标范围足够大以容纳整个结果:Excel 不会自动执行此操作。
它可以在没有 VBA 的情况下完成,相当紧凑,就像这样。
假设您的 100x100 表在 B2:CW101 中,我们将数字列表从 A2 到 A101 的左侧从 1 到 100 放在从 B1 到 CW1 的顶部的 1 到 100 的列表中
在下面创建一列单元格,从(比如)B104 开始
B104=MAX(($A$2:$A$101*100+$B$1:$CW$1<B103)*($B$2:$CW$101=TargetValue)*($A$2:$A$101*100+$B$1:$CW$1))
这是一个“数组”公式,因此请按Ctrl- Shift-Enter而不是Enter,并且大括号 {} 应该出现在公式周围。
然后根据需要复制尽可能多的行。您还需要在您的第一个公式上方放置一个较大的数字,即在 B103 中,例如 999999。
公式的作用是计算Rowx100+Column,但只针对每个成功的单元格,MAX函数查找最大的结果,排除之前找到的所有结果,即一次找到一个目标结果,从右下角开始工作到左上角。(只需稍加努力,您就可以让它以另一种方式搜索)。
这将为您提供类似 9922 的结果,即第 99 行第 22 列,您可以轻松地从数字中提取这些值。
我在不使用 VBA 的情况下尝试了很多,但没有它似乎是不可能的。为了解决这个问题,我需要遍历整个数组并找到最接近的值。然后使用调用和范围属性取消引用这些值,并在每次有效匹配时递增的范围内生成输出。
快速而肮脏的实现如下:
Dim arr As Range
Dim tempval As Range
Dim op As Integer
Set arr = Worksheets("sheet1").Range("b2:ao41")
op = 1
Range("B53:D153").ClearContents
For Each tempval In arr
If Round(tempval.Value, 0) = Round(Range("b50").Value, 0) Then
Range("b52").Offset(op, 0).Value = Range("a" & tempval.Row).Value
Range("b52").Offset(op, 1).Value = Cells(tempval.Column, 1).Value
Range("b52").Offset(op, 2).Value = tempval.Value
op = op + 1
End If
Next
Range("b50").Select
我仍在寻找一种没有 VBA 的方法。
我有一个不使用 VBA 的解决方案,但它相当混乱。它涉及在 Excel 中创建另一个一维表并对其进行查找。对于 100x100 的数据表,新表需要 10,000 行。
抱歉,如果这不符合您的需求。
总结如下 - 如果您需要更多详细信息,请告诉我。N = 数据的维度,例如在您的示例中为 100。
首先,创建一个包含五列和 NxN 行的新表。在每种情况下,将我的列名替换为适当的 Excel 参考
第一列(称为 INDEX)仅列出 1、2...NxN。
第二列 (DATAROW) 包含一个循环遍历 1, 2... N, 1, 2...N... 的公式,这可以使用类似 =MOD(INDEX-1, N)+1 的方法来完成
第三列 (DATACOL) 包含 1, 1, 1... 2, 2, 2... (每个 N 次)。这可以通过 =INT((INDEX-1)/N)+1 来完成
第四列 (VALUE) 包含数据表中的值,使用类似:=OFFSET($A$1, DATAROW, DATACOL),假设您的数据表从 $A$1 开始
我们现在有一个包含所有数据的一维表。
第五列 (LOOKUP) 包含公式:=MATCH(target, OFFSET(VALUERANGE, [LOOKUP-1], 0),0)+ [LOOKUP-1]
其中 [LOOKUP-1] 指的是紧邻上方的单元格(例如,在单元格 F4 中,这指的是 F3)。在 LOOKUP 列的第一个单元格上方需要一个 0。
VALUERANGE 应该是对整个 VALUE 列的固定(命名或使用 $ 符号)引用。
然后 LOOKUP 列保存 INDEX 编号,可用于查找 DATAROW 和 DATACOL 以查找数据中匹配项的位置。
这通过在 VALUERANGE 中搜索匹配项,然后在前一个匹配项之后开始在调整后的范围内搜索匹配项来实现。
在电子表格中比通过上面的解释要容易得多,但这是我目前能做的最好的......