You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于预算上限的产品选择问题求助(VBA/M Query)

基于预算筛选所有有效产品组合的解决方案

VBA 实现方案

利用二进制位枚举所有非空产品组合(6个产品对应6位二进制,每一位代表是否选择该产品),计算每个组合的总价后筛选出符合预算的结果并输出到工作表:

Sub GetValidProductCombinations()
    Dim products As Variant
    Dim prices As Variant
    Dim budget As Double
    Dim totalCombinations As Long
    Dim i As Long
    Dim j As Long
    Dim currentTotal As Double
    Dim combination As String
    Dim outputRow As Long
    
    ' 初始化产品和价格数据
    products = Array("Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6")
    prices = Array(1, 3, 0.5, 40, 20, 5)
    budget = 50
    totalCombinations = 2 ^ UBound(products) - 1 ' 排除空组合
    outputRow = 2 ' 从第2行开始输出(第1行放表头)
    
    ' 写入表头
    Cells(1, 1).Value = "产品组合"
    Cells(1, 2).Value = "总价(美元)"
    
    ' 遍历所有组合
    For i = 1 To totalCombinations
        currentTotal = 0
        combination = ""
        For j = 0 To UBound(products)
            ' 检查第j位是否为1(是否选择该产品)
            If (i And 2 ^ j) <> 0 Then
                currentTotal = currentTotal + prices(j)
                combination = combination & products(j) & ", "
            End If
        Next j
        
        ' 筛选符合预算的组合
        If currentTotal <= budget Then
            ' 移除末尾的逗号和空格
            combination = Left(combination, Len(combination) - 2)
            Cells(outputRow, 1).Value = combination
            Cells(outputRow, 2).Value = currentTotal
            outputRow = outputRow + 1
        End If
    Next i
    
    ' 格式化输出列
    Columns("A:B").AutoFit
End Sub

代码说明

  • 定义产品名称和价格数组,设置预算值;
  • 通过2^6-1计算所有非空组合数(共63种);
  • 外层循环遍历每个组合的二进制编码,内层循环检查每个产品是否被选中,累加总价并拼接组合文本;
  • 筛选出总价≤50美元的组合,去除末尾多余符号后写入工作表,最后自动调整列宽。

M Query(Power Query)实现方案

在Power Query中生成所有非空产品子集,计算总价后筛选符合预算的组合:

  1. 新建空白查询,打开高级编辑器,替换为以下M代码:
let
    // 初始化产品数据
    Source = Table.FromRecords({
        [产品 = "Item 1", 价格 = 1.0],
        [产品 = "Item 2", 价格 = 3.0],
        [产品 = "Item 3", 价格 = 0.5],
        [产品 = "Item 4", 价格 = 40.0],
        [产品 = "Item 5", 价格 = 20.0],
        [产品 = "Item 6", 价格 = 5.0]
    }),
    // 添加索引列(用于生成子集)
    AddIndex = Table.AddIndexColumn(Source, "索引", 0, 1, Int64.Type),
    // 获取产品列表和价格列表
    ProductsList = AddIndex[产品],
    PricesList = AddIndex[价格],
    // 生成所有非空子集的索引集合
    AllSubsets = List.RemoveItems(List.Generate(
        () => 1,
        each _ < 2 ^ List.Count(ProductsList),
        each _ + 1
    ), {0}),
    // 转换每个子集索引为产品组合和总价
    ConvertToCombinations = List.Transform(AllSubsets, (subset) =>
        let
            SelectedIndices = List.PositionOf(List.Transform({0..List.Count(ProductsList)-1}, (i) => Number.Mod(Number.IntegerDivide(subset, 2^i), 2)), 1),
            SelectedProducts = List.Select(ProductsList, (p, idx) => List.Contains(SelectedIndices, idx)),
            TotalPrice = List.Sum(List.Select(PricesList, (pr, idx) => List.Contains(SelectedIndices, idx)))
        in
            [产品组合 = Text.Combine(SelectedProducts, ", "), 总价 = TotalPrice]
    ),
    // 转换为表
    ConvertToTable = Table.FromRecords(ConvertToCombinations),
    // 筛选总价≤50的组合
    FilterByBudget = Table.SelectRows(ConvertToTable, each [总价] <= 50),
    // 排序(可选)
    Sorted = Table.Sort(FilterByBudget,{{"总价", Order.Ascending}, {"产品组合", Order.Ascending}})
in
    Sorted

代码说明

  • 通过Table.FromRecords创建产品数据表;
  • 添加索引列方便后续生成子集时定位产品;
  • 用List.Generate生成所有非空子集的二进制编码(从1到63);
  • 对每个编码,解析出选中的产品索引,提取对应的产品名称和价格,计算总价并拼接组合文本;
  • 将转换后的列表转为表,筛选出总价≤50美元的组合,最后可选择按总价和组合名称排序。

内容的提问来源于stack exchange,提问作者Yassine Erraihani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 18:10:47