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

Power Query M代码实现管道合同容量优先级分配计算需求

Power Query M Code for Efficient Pipeline Capacity Allocation by Contract Priority

Problem Overview

  • Handle capacity allocation across 30+ pipeline systems with 200+ contracts (each tied to a system and assigned a priority ranking)
  • For each year up to 2030, allocate system capacity to contracts:
    • If total contract demand ≤ system maximum capacity: full demand is allocated to all contracts
    • If total demand exceeds capacity: allocate capacity to contracts in priority order until the system's maximum capacity is exhausted
  • Replace inefficient Excel boolean logic with optimized M code to handle large datasets, outputting a ready-to-use table for downstream scheduling modules

Solution Approach

We'll use grouping by pipeline system and year, combined with efficient list operations to calculate cumulative demand and prioritize allocation. Here's the step-by-step M code implementation:

Step 1: Load and Prepare Source Data

Assume your source tables are named Contracts (contains System, Contract ID, Priority, Year, Demand) and SystemCapacities (contains System, Year, MaxCapacity):

let
    // Load source tables (adjust references to match your workbook)
    SourceContracts = Excel.CurrentWorkbook(){[Name="Contracts"]}[Content],
    SourceCapacities = Excel.CurrentWorkbook(){[Name="SystemCapacities"]}[Content],
    
    // Set correct data types to avoid calculation errors
    Contracts = Table.TransformColumnTypes(SourceContracts, {
        {"System", type text},
        {"Contract ID", type text},
        {"Priority", Int64.Type},
        {"Year", Int64.Type},
        {"Demand", Currency.Type}
    }),
    SystemCapacities = Table.TransformColumnTypes(SourceCapacities, {
        {"System", type text},
        {"Year", Int64.Type},
        {"MaxCapacity", Currency.Type}
    })

Step 2: Join Data and Group by System + Year

Join contracts with their corresponding system capacity data, then group to process each system-year combination independently:

// Join contracts with their system's yearly maximum capacity
    JoinedData = Table.NestedJoin(Contracts, {"System", "Year"}, SystemCapacities, {"System", "Year"}, "SystemCapacity", JoinKind.Inner),
    ExpandCapacity = Table.ExpandTableColumn(JoinedData, "SystemCapacity", {"MaxCapacity"}, {"MaxCapacity"}),
    
    // Group by System and Year, sort contracts in each group by priority (lowest number = highest priority)
    Grouped = Table.Group(ExpandCapacity, {"System", "Year", "MaxCapacity"}, {
        {"SortedContracts", each Table.Sort(_, {{"Priority", Order.Ascending}}), type table}
    })

Step 3: Calculate Allocated Capacity

For each grouped system-year, compute cumulative demand and determine allocated capacity using efficient list operations:

// Add allocation logic to each group
    AddAllocation = Table.AddColumn(Grouped, "AllocatedContracts", (group) =>
        let
            ContractsSorted = group[SortedContracts],
            DemandList = ContractsSorted[Demand],
            // Calculate cumulative demand for sorted contracts
            CumulativeDemand = List.Accumulate(DemandList, {}, (state, current) => state & {List.Sum(state) + current}),
            // Compute allocated capacity per contract
            AllocatedList = List.Generate(
                () => [Idx=0, PrevCumul=0, Allocated=if CumulativeDemand{0} <= group[MaxCapacity] then DemandList{0} else group[MaxCapacity]],
                each [Idx] < Table.RowCount(ContractsSorted),
                each [
                    Idx = [Idx] + 1,
                    PrevCumul = CumulativeDemand{[Idx]-1},
                    CurrentCumul = CumulativeDemand{[Idx]},
                    Allocated = if PrevCumul >= group[MaxCapacity] then 0 
                               else if CurrentCumul <= group[MaxCapacity] then DemandList{[Idx]} 
                               else group[MaxCapacity] - PrevCumul
                ],
                each [Allocated]
            ),
            // Append allocated capacity column to contracts table
            WithAllocation = Table.AddColumn(ContractsSorted, "AllocatedCapacity", each AllocatedList{Table.PositionOf(ContractsSorted, _)})
        in
            WithAllocation
    ),
    
    // Expand the allocated contracts table and clean up
    ExpandAllocated = Table.ExpandTableColumn(AddAllocation, "AllocatedContracts", {"Contract ID", "Priority", "Demand", "AllocatedCapacity"}, {"Contract ID", "Priority", "Demand", "AllocatedCapacity"}),
    FinalTable = Table.RemoveColumns(ExpandAllocated, {"SortedContracts"})
in
    FinalTable

Key Optimizations

  • Grouped Processing: Isolates each system-year combination to minimize redundant calculations
  • Sorted Priority: Contracts are sorted once per group, avoiding repeated sorting operations
  • List Operations: Uses List.Accumulate and List.Generate instead of row-by-row checks, drastically improving performance for large datasets
  • Early Termination: Contracts after the capacity threshold automatically get 0 allocation without extra computations

Notes

  • If your priority ranking uses higher numbers for higher priority, adjust the sort order in Table.Sort to Order.Descending
  • Validate with a small subset of data first to ensure allocation matches your Excel formula results
  • The code assumes one capacity entry per system per year; modify the join logic if your capacity data has different granularity

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 15:55:13