Excel中查找匹配付款金额的采购项组合:随机数求和匹配问题
采购记录匹配付款金额的解决方法
你碰到的是典型的子集和问题,Excel自带的数据透视表、普通公式确实搞不定,得用VBA或者Power Query来实现,下面给你两个实用方案:
方案一:VBA宏代码批量查找
这个方法直接在Excel里运行代码,能找出对应付款金额的采购组合:
- 按
Alt + F11打开VBA编辑器,插入一个新模块 - 粘贴以下代码(记得根据你的实际单元格范围修改):
Sub FindPurchaseMatches() Dim purchaseRange As Range, paymentRange As Range Dim purchaseVals As Variant, paymentVals As Variant Dim i As Long, j As Long, targetAmt As Double Dim comboText As String, resultRow As Long ' 替换成你的采购金额区域(比如A列第2行到第58行,共57条) Set purchaseRange = ThisWorkbook.Sheets("Sheet1").Range("A2:A58") ' 替换成你的付款金额区域(比如B列第2行到第19行,共18条) Set paymentRange = ThisWorkbook.Sheets("Sheet1").Range("B2:B19") purchaseVals = purchaseRange.Value paymentVals = paymentRange.Value resultRow = 2 ' 结果输出到C、D列,从第2行开始 ' 遍历每一笔付款 For i = 1 To UBound(paymentVals) targetAmt = paymentVals(i, 1) ' 先筛选出小于等于目标付款的采购项,减少计算量 Dim filteredList As Variant, filterCount As Long filterCount = 0 ReDim filteredList(1 To UBound(purchaseVals), 1 To 1) For k = 1 To UBound(purchaseVals) If purchaseVals(k, 1) <= targetAmt Then filterCount = filterCount + 1 filteredList(filterCount, 1) = purchaseVals(k, 1) End If Next k ReDim Preserve filteredList(1 To filterCount, 1 To 1) ' 枚举所有可能的采购组合 For j = 1 To 2 ^ filterCount - 1 Dim tempSum As Double, m As Long tempSum = 0 comboText = "" For m = 1 To filterCount If (j And 2 ^ (m - 1)) <> 0 Then tempSum = tempSum + filteredList(m, 1) comboText = comboText & "$" & filteredList(m, 1) & ", " End If Next m ' 匹配成功就输出结果(用小误差避免浮点精度问题) If Abs(tempSum - targetAmt) < 0.0001 Then ThisWorkbook.Sheets("Sheet1").Cells(resultRow, "C").Value = "付款金额: $" & targetAmt ThisWorkbook.Sheets("Sheet1").Cells(resultRow, "D").Value = Left(comboText, Len(comboText) - 2) resultRow = resultRow + 1 End If Next j Next i End Sub
- 调整代码里的单元格范围(比如你的采购记录不在A2:A58,就改成你实际的区域)
- 运行宏,结果会显示在C、D列,每一行对应一笔付款的匹配采购组合
方案二:Power Query自定义函数(无VBA)
如果不想用宏,也可以用Power Query来实现:
- 把采购和付款记录分别导入Power Query
- 新建自定义函数,生成所有采购组合并计算总和
- 对每笔付款,调用函数筛选出总和匹配的组合
不过要注意,57条记录的组合数极大,必须先筛选掉大于目标付款的采购项,否则计算会非常慢甚至崩溃。
实用小提示
- 先手动预处理:对每笔付款,先删掉采购记录里比它大的金额,大幅减少需要计算的组合数
- 处理小数精度:比较金额时一定要留小误差(比如
Abs(总和 - 付款) < 0.0001),避免因为Excel的浮点精度问题漏匹配
内容的提问来源于stack exchange,提问作者Richard K.
相关产品推荐
相关产品推荐

