Viime viikon kirjoituksessa esiteltiin, miten Power Appsilla rakennetaan muokattava taulukko. Jujuna oli taulukon rivi- ja saraketietojen tallentaminen omiin tauluihin/listoihin/entiteetteihin. Näin voidaan muokata n kappaletta sarakkeita.
Esimerkkinä toimi projektivarausten tekeminen.

Tällä kertaa viedään ratkaisua hieman eteenpäin. Toteutetaan:
- Hierarkinen projektin rakenne
- Syötettyjen tietojen tallennus
Tästä tulee hauskaa!
Projektihierarkia
Alkuperäisessä toteutuksesssa varauksia tehtiin projektitasolla. Haluamme syventää ratkaisua siten, että voimme tehdä varauksia
- projektille kuukausittain
- projektin loogisille vaiheille (plan, design, implementation, testing..) kuukausittain
- Projektin vaiheiden alla tehtäville töille kuukausittain
Pahoittelut, meni ihan vesiputousmalliksi. Voit korvata loogiset vaiheet vaikka sprinteillä. Esimerkissä pääasia on, että lukujen syöttö tehdään hierarkiaan.
Projektihierarkia voidaan toteuttaa kahdella tavalla.
- Jokaista hierarkiatasoa vastaa oma lista/taulu/entiteetti
- Kaikki hierarkiatasot tallennetaan yhteen ja samaan listaan/tauluun/entiteettiin
Valitsemme jälkimmäisen vaihtoehdon. Projektit, niiden vaiheet ja alivaiheet tallennetaan kaikki Project phases -listaan.

Hierarkiaa varten lisätään uusia sarakkeita.
- Level – Hierarkiataso, jota rivi vastaa. Projektia vastaa taso 1.
- ParentID – Minkä rivin alitaso kyseinen rivi on.
- ProjectID – Mihin projektiin rivi liittyy. Tieto tallennetaan, jotta Power Appsissa voidaan helposti hakea kaikki yhteen projektiin liittyvät vaiheet.
Power Appsisa käsittelemme kerrallaan ain yhden projekin varauksia. Lisätään näytön yläosaan projektivalinta.
Items: Filter('Project phases', Level = 1)

Mutta miten ihmeessä saamme projektin vaiheet ja alivaiheet esitettyä oikeassa järjestyksessä?
Projektiin liittyvät rivit ovat tietovarastossa niiden luontijärjestyksessä. Haluaisimme näyttää ne tyylikkäästi hierarkiassa tähän tapaan.
- Projekti
- Vaihe 1
- Alivaihe 1
- Alivaihe 2
- Vaihe 2
- Alivaihe 1
- Alivaihe 2
- Vaihe 3
- Alivaihe 1
- Alivaihe 2
- Vaihe 1
Power Apps ei tarjoa kehittynyttä tapaa tehdä kyselyjä tietovarastoon, joten muodostamme itse kokoelman, jossa projektiin liittyvät rivit ovat oikeassa järjestyksessä.
Tämä tehdään käyttäjän valittua tarkasteltavan projektin (projekti-ComboBox’in OnChange-tapahtumassa).

Ensin luodaan kokoelma, joka sisältää valitun projektin vaiheet (colProjectPhases).
ClearCollect( colProjectPhases, Filter( 'Project phases', ProjectID = Self.Selected.ID ) )
Tämän jälkeen luodaan kokoelma projekti-galleriaa varten (colForProjectGallery) ja lisätään siihen ensimmäiseksi riviksi itse projekti.
ClearCollect( colForProjectGallery, LookUp( colProjectPhases, Level = 1 ) )
Lopuksi käymme läpi seuraavan tason vaiheet ja
- lisäämme vaiheen colForProjectGallery-kokoelmaan
- käymme läpi kaikki vaiheen alivaiheet, ja lisäämme myös ne colForProjectGallery-kokoelmaan
ForAll(Filter(colProjectPhases,Level = 2), Collect(colForProjectGallery,ThisRecord); With({varCurrentItem: ThisRecord}, ForAll( Filter( colProjectPhases, ParentID = varCurrentItem.ID), Collect(colForProjectGallery,ThisRecord) ) ) )
Lopputuloksena meillä on kokoelma, jossa vaiheet ja alivaiheet ovat oikeassa järjestyksessä.

Vaihdetaan päägalleriamme tietolähteeksi muodostamamme kokoelma (colForProjectGallery) ja lisätään vaiheen nimen eteen sisennys, jonka määrä riippuu rivin hierarkiatasosta (Level).
X = ThisItem.Level * 15
Tämähän näyttää jo aika selkeältä!

Korostetaan vielä väreillä eri tasoja.

Kelpaa.
Varausten tallennus
Varausten tallentamista kannattaa hetki miettiä ennen toteutusta. Esimerkkiprojektimme kohdalla näytöllä on 120 kuukausivarausta. Jos yksittäisen varauksen tallenntaminen kestää keskimäärin sekunnin, vie kaikkien varausten tallentamien aikaa 2 minuuttia.
Ei käy.
Haluamme ensinnäkin tallentaa ainoastaan uudet/muuttuneet tiedot. Ja nekin mahdollisimman tehokkaasti.
Tähän löytyy lukuisia eri tapoja.
Matthed Devany esittelee blogissaan mielenkiintoisen lähestymisen, jossa toggle-kontrollin avulla ylläpidetään tieto kunkin sarakkeen päivityksestä. Togglen arvoja hyödynnetään tallennuksen yhteydessä.
Lopullisesta ratkaisusta ne luonnollisesti piilotetaan.

Vaihtoehtoisesti voimme ylläpitää erillisessä kokoelmassa tietoa siitä, mitä soluja on muokattu. Tehdään näin.
Lisätään seuraava koodi yksittäisen varauksen (inpAllocationValue) onChange-tapahtumaan.
With({varUpdate: LookUp(colChangedAndUpdatedItems, FirstDayOfPeriod = ThisItem.periodStartDate And ProjectPhaseID = lblProjectID.Text) },If(IsBlank(varUpdate), With({varCurrentAllocationItem: LookUp(colAllocations, FirstDayOfPeriod = ThisItem.periodStartDate And Title = lblProjectID.Text) }, Collect(colChangedAndUpdatedItems, { FirstDayOfPeriod: ThisItem.periodStartDate, ProjectPhaseid: lblProjectID.Text, Allocation: Value(Self.Text), ID: If(!IsBlank(varCurrentAllocationItem), varCurrentAllocationItem.ID, -1) } ) ), Patch(colChangedAndUpdatedItems, varUpdate, {Allocation: Value(Self.Text)}) ) )
Eli aina kun taulukon solua muokataan, lisätään colChangedAndUpdatedItems-kokoelmaan seuraavat tiedot
- Arvo (newValue)
- Varausjakson ensimmäinen päivä (FirstDayOfPeriod)
- Projektin vaihe, johon varuas liittyy (ProjectPhaseID)
- Varausta vastaavan tallennetun tietueen tunniste (ID). Arvoksi asetetaan -1, mikäli kyseessä on uusi rivi.
Näin meillä on yhdessä kokoelmassa kaikki varaukset, jotka meidän tulee tallentaa.
Uuden rivin lisääminen vs vanhan muokkaus
Miksi näimme vaivaa selvittää colChangedAndUpdatedItems-kokoelmaan riviä lisättäesssä onko kyseessä rivi, joka löytyy jo tietovarastosta?
Koska tallennamme muokkaukset ja lisäykset eri tavalla.
Muokkausten tallenntaminen
Lisätään näytölle Save-painike, jota painettaessa, tallennetaan kaikki muutokset yhdellä Patch-komennolla.
Patch( 'Project allocations', ShowColumns( Filter(colChangedAndUpdatedItems, ID > -1), "ID", "Allocation" ) )

Patchille voi siis antaa parametriksi kokoelman! Kunhan kokoelmasta löytyy päivitettävän rivin tunniste ja kokoelman sarakkeiden nimet vastaavat tietolähteen sarakkeita. Tämän takia välitimme ShowColumns -toiminnon avulla Patch-komennolle ainoastaan ID ja Allocation -sarakkeet.
Näin tallennus on huomattavasti nopeampaa kuin jokaisen rivin päivittäminen yksitellen (ForAll -> Patch).
Mutta uusia rivejä ei pysty luomaan näin.
Uusien rivien luominen
Usean rivin luominen on tehokkainta luoda Flow’lla. Ratkaisun perusperiaate löytyy vanhasta jutusta.
Tarvitsemme ensiksi Flow’n, jota kutsutaan Power Appsista. Flow saa parametrinaan tallennettavat tiedot JSON-muodossa. Saatu JSON parsitaan, jonka jälkeen sen sisältämät tietueet tallennetaan yksi kerrallaan.
Lisäämällä Apply to each -simukkaan lisää rinnakkaisuutta (Settings -> Concurrency Control), saadaan tallennuksesta nopea.

Flow’ta kutsutaan Save-painikkeesta.
'PA-Createnewallocations'.Run( JSON(Filter(colChangedAndUpdatedItems,ID = -1)), cmbProjects.Selected.ID )
Asetetaan lopuksi tallennukset suorittumaan rinnakkain (Concurrent).

Yhteenveto
Meillä on valmiina muokattava taulukko, jonka rivit tallentuvat tietovarastoon. Pienen siistimisen jälkeen se näyttää tältä.
Seuraavassa kirjoituksessa selvitetään miten taulukkoon saa luotua uusia rivejä ja miten vaihdetaan niiden järjestystä.