Gegeven: taken die elk een bepaalde hoeveelheid werk zijn, die van een bepaalde datum tot een bepaalde datum lopen, en die aan één of meer personen zijn toegewezen. Ook gegeven: wat mensen al ingepland hebben per dag — wat gemakkelijk om te zetten is in hoeveel tijd mensen nog beschikbaar hebben op weekbasis.

Gevraagd: hoeveel tijd hebben die mensen nog over, per week, als ze alle taken moeten uitvoeren die aan hen toegewezen zijn? (Ja, ‘t heeft met deze resource planning te maken.)

Ik doe allemaal veronderstellingen om het eenvoudiger te maken, zoals daar bijvoorbeeld zijn:

  • Als iets aan twee mensen is toegekend, gaan we er voorlopig van uit dat ze elk de helft van het werk zullen doen.
  • Er zijn allerlei manieren bedenkbaar om het werk over de tijd te verdelen, maar we gaan er voorlopig van uit dat al het werk dat nog te doen is gelijkmatig verdeeld wordt over de nu nog beschikbare tijd, in de tijdsperiode van de taak. Andere manieren om het te bekijken zouden bijvoorbeeld zijn: alles zo snel mogelijk uitvoeren, alles zo laat mogelijk uitvoeren, op de één of andere manier een prioriteit in de verschillende taken steken, etc, etc.

Het eerste dat ik wil doen, is deze input:

omzetten naar deze output:

Weeknummer vinden van de begindatum en de einddatum, en dan evenveel rijen aanmaken als er weken zijn, met het aantal dagen gedeeld door het aantal weken. Dat is natuurlijk zo simpel als iets in allerlei mogelijke omgevingen (Excel met wat manueel werk, een script in Uw Programmeertaal Naar Keuze) — maar het moest in Power BI gebeuren.

Ik had er met een half oog naar gekeken, mijn hoop wat gesteld op pandas, dan gezien dat het blijkbaar niet mogelijk is om met pandas in een visualisatie in Power BI nieuwe rijen of nieuwe dataframes te maken, en dan een zeer luid gezucht.

En dan zei een fijne ex-collega hoe hij het in sql-pseudocode zou doen, wat niet aan de orde was in Power BI, maar het deed er mij wel aan denken dat een lijst een datatype zoals een ander is in Power Query. En zo kwam ik alsnog aan de oplossing: als ik een lijst van dagen tussen begin en eind heb, en ik verander elke dag in die lijst naar het weeknummer van die dag, en ik houd dan alleen de unieke waarden over, dan ben ik er bijna.

Dus ik maak een nieuwe kolom aan, weeks. Daarin steek ik de lijst van de dagen tussen start en end. Ik kan niet zomaar

weeks = {[start]..[end]}

doen, want dat zijn twee data en geen getallen. Dus eerst omzetten naar een cijfer en dán een lijst van maken:

weeks = {Number.From([start])..Number.From([end])}

Dat geeft mij voor de eerste rij, taak A van 3/1 tot 22/1, een propere lijst van 20 dagnummers: 44564 tot en met 44583. Dan kan ik met List.Transform() de lijst overlopen en bepotelen:

weeks = List.Transform(
            {Number.From([start])..Number.From([end])}, 
            each _
        )

Dat geeft mij gewoon dezelfde lijst terug als waar ik mee begon, natuurlijk. ‘t Is op die _, die staat voor elk element van de lijst, dat er geprutst moet worden. Eerst maak ik er weer een datum van met Date.From(), en dan pak ik van die datum het nummer van de week in het jaar met Date.WeekOfYear().

weeks = List.Transform(
            {Number.From([start])..Number.From([end])}, 
            each Date.WeekOfYear(Date.From(_))
        )

Daar krijg ik dan voor die eerste taak een lijst van 20 getallen: 7 keer 2, dan 7 keer 3 en dan 6 keer 4. Ik wil alleen de unieke getallen overhouden, en da’s gewoon List.Distinct() — dus alles samen geeft dat:

weeks = List.Distinct(
            List.Transform(
                {Number.From([start])..Number.From([end])}, 
                each Date.WeekOfYear(Date.From(_))
            )
        )

Voor elke taak heb ik nu een veld weeks dat een lijst van weeknummers bevat (jaja, ik weet het, het zou eigenlijk jaar en week moeten zijn, I know). De volgende stap is simpelweg Expand to new rows doen op dat veld en hopsa Table.ExpandListColumn() maakt alle nodige rijen aan.

Een groot gemak.