Die Mailbox sauber halten mit Powerautomate und MS Graph

Wir haben heute wieder was gelernt. Grundsätzlich war meine Erfahrung schon früher die, dass man ziemliche Schwierigkeiten hat wenn man mit Powerautomate E-Mails abrufen will.

Im Standard werden 10 Mails abgerufen, aber selbst wenn man das erhöht und Filter ansetzt wirds kompliziert, denn trotz korrekter Daten findet der Outlookconnector einfach keine Mails.

Also greifen wir hier auf den HTTP Request und MS Graph zurück.

Was ist unser Usecase?

Unser Kunde möchte das alle E-Mails die älter als 6 Monate sind automatisch gelöscht werden.

Nun werden wir zum Start natürlich die Mails manuell löschen doch danach soll sich der Kunde darum nicht mehr kümmern müssen, insbesondere da je nach Einstellung im Client nur 3 Monate angezeigt werden.

Was machen wir also:

Unser Trigger ist eine Wiederholung, ob man den Flow nun täglich laufen lässt und somit eine geringe Anzahl Mails löschen muss oder monatlich hängt natürlich in erster Linie davon ab wie viele Mails pro Tag eingehen und versandt werden.

Wir gehen von einer hohen Anzahl aus und nämlich daher einen Trigger der täglich läuft.

Nun initialisieren wir 3 Variablen.

Ein Integer, ein String und ein Array.

Den String befüllen wir direkt. Er ist nur für unseren Filter erforderlich. Selbstverständlich könnte man den Flow auch in eine App einbinden um die Variable individuell zu befüllen, da wir aber nur filtern wollen welche Mails älter als 6 Monate sind.

Wir schreiben folgendes also in unseren String:

addDays(utcNow(), -180, ‘yyyy-MM-dd’)

Wir könnte auch getPastTime verwenden. Der Effekt ist der gleiche.

Die Integer Variable brauchen wir um die Zeilen zu zählen die wir raus bekommen.

Und das Array um das Ergebnis der Graphabfrage zu verarbeiten.

Nun kommen wir zur HTTP-Anforderung:

GET https://graph.microsoft.com/v1.0/me/messages?$filter=(receivedDateTime le variables(‘6monatezurück’))

Natürlich könnten wir das Datum auch direkt in der Abfrage berechnen aber mit der Variable ist es einfach sauberer.

Im nächsten Schritt wandeln wir das Ergebnis mithilfe einer Composeaction in einen String um.

string(body(‘HTTP-Anforderung_senden’))

Diesen teilen wir nun bei jedem Vorkommen eines Commas

split(outputs(‘Verfassen’),’,’)

Und packen das in unserer Array

Das Array filtern wir nun nach allen Zeilen die mit “id”: starten um die Nachrichten IDs zu bekommen. Das gefilterte Array enthält also nun bereits nur noch die IDs allerdings mit mehrere ” und dem Start mit “id”:. Da wir nur die reine ID wollen machen wirs uns einfach. Wir wissen dass die ID definitiv zwischen 2 ” liegt also zählen wir einfach nach und stellen fest das die ID somit an 4 Stelle in der Zeile liegt wenn wir sie erneut bei jedem Vorkommen von ” splitten.

split(item(), ‘”‘)[3]

Wir haben nun also die reine Nachrichten ID. Damit können wir im nächsten Schritt die E-Mail mit dem Outlook Connector löschen.

Nun stellen wir fest dass auch Graph nur 10 Zeilen abruft. Da wir die genaue Anzahl der zu löschenden Mails nicht kennen. Nutzen wir jetzt noch eine “Wiederholen bis” Aktion. Dafür brauchen wir die Integer Variable. Jedes Mal wenn wir das Array filtern schreiben wir die Länge des Array in die Variable.
length(body(‘Array_filtern’))

Es wird die ersten Durchläufe immer 1-10 Zeilen haben bis wir ans Ende kommen und keine Mails mehr zu löschen sind. Wir beenden also unsere Schleife sobald die Länge 0 ist.

“type”: “Until”, “expression”: “@less(variables(‘Zeilenzählen’),5)”,

Damit läuft unser Flow unabhängig der Anzahl Mails einfach solange durch bis es nichts mehr gibt was älter als 6 Monate ist.

Und somit wird unsere Mailbox nicht mehr zum Datenfriedhof.

Danke wie immer fürs lesen.

LG Elli

Zeilen zählen in Powerautomate

Ich nutze ja oft ChatGPT um Ideen zu bekommen wie ich eine
Anforderung in Powerautomate umsetze. Doch diesmal war das wenig
hilfreich, die Lösung von ChatGPT war umständlich und nicht vollständig.
Die KI muss eben auch noch lernen.

Daher nun zu meiner Lösung.

Das war die Anforderung.

Wir betreiben eine Art Dropshipping. Dazu sammeln wir die
Bestellungen in einer Sharepointliste und wollen einmal pro Woche eine
Auswertung was und wieviel Stück pro Artikel bestellt wurde.

Erst dachte ich das geht nicht und hab mich erstmal nur auf eine
sortierte Liste geeinigt bei der nachzählen einfacher ist. Aber dann kam
ich auf die Lösung.

Für unseren Flow brauchen wir genau 2 Array Variablen.

Im ersten Schritt rufen wir die Bestellungen der letzten 7 Tage aus der Sharepointliste ab:

Also “Get Items” und filtern die Abfrage hiermit:

Created ge ‘@{getPastTime(7, ‘day’)}’

Nun gehen wir die Liste in einer For each Aktion durch mit folgender Bedingung:

“contains”: [“@variables(‘uniqueArray’)”,”@item()?[‘Title’]”

Das heißt wir schauen in jeder Schleife ob der Titel des Elements
bereits in unserer Arrayvariable gespeichert ist. Falls nicht fügen wir
den Titel hinzu, falls ja machen wir nichts.

Nun haben wir alle bestellten Artikel genau einmal im neuen Array gespeichert.

Im nächsten Schritt machen wir also eine “For each” Aktion für unser neues Array.

Nun rufen wir erneut die Sharepointliste ab. Allerdings mit einem angepassten Filter.

“Title eq ‘@{item()}’ andnCreated ge ‘@{getPastTime(7, ‘day’)}'”

Wir filtern wie zuvor die letzten 7 Tage und den Titel.

Als Ausgabe bekommen wir also in jeder Schleife nur alle Bestellungen mit diesem einen Artikel.

Die Anzahl Zeilen erhalten wir mit einer Compose Action.

length(outputs(‘Elemente_abrufen_1’)?[‘body/value’])

Das schreiben wir nun in die 2. Arrayvariable:

“value”: “@{item()}; @{outputs(‘Anzahl’)}”

Damit ist unsere 2. Arrayvariable nun mit den korrekten Daten gefüttert.

Im Abschluss erstellen wir eine HTML Tabelle oder eine CSV Tabelle
um das Ergebnis unseres Flows sichtbar zu machen. Das hängt von der
weiteren Verarbeitung ab.

CSV Dateien unabhängig ihrer Größe in Powerautomate verarbeiten

 

Nun gehen wir also eine Flow CSVs unbekannter Größe an.

Dafür brauchen wir 3 Variablen.

Integer, Array und Boolean.


Integer ist unser Skip Counter, Array ist unser initiales CSV Array und Boolean dient zur Prüfung ob das Array leer ist.

Wir bekommen also wieder unser CSV File und verarbeiten es als erstes mit 3 Compose und 1 Array filtern Aktion.

base64ToString(triggerBody()?[‘file’]?[‘contentBytes’])


split(outputs(‘Get_CSV’),outputs(‘Absatztrenner’))


Dann befüllen wir unsere Arrayvariable mit dem gefilterten Array.

Nun gehts in die “Do until” Aktion. Die “Do until” läuft bis die Boolean Variable true ist.

Im “Do until” nehmen wir uns nun die ersten 5000 Zeilen unserer Variable:

take(skip(variables(‘csv array’), variables(‘skipcounter’)), 5000)

Dann prüfen wir ob das Ergebnis dieser Aktion ein leeres Array ist.

empty(outputs(‘Nimm_5000_Zeilen,_überspringe_Skip_Counter_Zeilen’))

Und erhöhen im Anschluss den Skip Counter um 5000

Danach bauen wir eine Bedingung ein, dass die Folgeaktion nur ausgeführt wird, wenn das Array nicht leer ist.

Damit ist der Flow auch schon fertig.




Große CSVs mit Powerautomate in Sharepoint oder Excel übertragen

 

Nachdem ich im April 2022 bei BDO Austria als
Backoffice Assistant in der IT gestartet habe, habe ich viel Freiraum
und Gelegenheit erhalten mich mit den Neuerungen von Microsoft
auseinander zu setzen. Schließlich war meine Ausbildung zur IT
Technikerin schon schon mehr als 10 Jahre her und ich habe nur in
relativ einfachen Call Center Support Jobs gearbeitet.

Insbesondere angetan hat es mir Powerautomate. Und zuletzt die
Erfassung von CSV Files aus E-Mails in Sharepoint und Excel. Da BMD beim
Export zwar auch .xlsx anbietet allerdings ohne Tabellenformatierung,
war der Export als .csv sinnvoller.

Kommen wir nun also zu meinem Beispielflow und wie ich .csv mit mehr als 5000 Zeilen verarbeite.

Unser Triggerevent ist der Eingang der E-Mail mit dem
Betreff: Ressourcenverleih IT: Ressourcenart Geräte alle Kategorien
Verleih

Direkt im Anschluss initialisieren wir mehrere Array Variablen (wie viele hängt auch von der erwarteten Größe der CSV ab.

Wir erwarten knapp über 5000 Zeilen. Daher brauchen wir 3
Variablen. Eine für das gesamte Array dass wir nachher definieren und 2
weitere um diese Array zu teilen.

Diese E-Mail enthält unser .csv File. Den Inhalt erfassen wir mit einer Compose Action:

base64ToString(item()?[‘contentBytes’])

Gefolgt von einer weiteren Compose Action, die die neue Zeile
definiert. Dafür einfach nur in der Compose Action einmal Enter drücken.

Nun befüllen wir unsere Variablen.

Unsere erstes Array bekommt die Information mit wie sie die CSV erfassen muss:

skip(split(outputs(‘Verfassen’),outputs(‘Verfassen_1’)),1)

Wobei Verfassen hier die vorhin konvertierte CSV ist und Verfassen1 die neue Zeile.

So sagen wir dem Array überspringe die erste Zeile (da es sich
hier um die Spaltennamen handelt) und nutze als Trenner die neue Zeile.

Nun weiß ich aus Erfahrung, dass mein Array häufig mehr als 5000
Zeilen haben wird und die folgende For each Aktion die meine CSV in
meinem Fall in eine Sharepointliste schreiben soll, erlaubt nicht mehr
als 5000 Durchläufe.

Daher teilen wir das Array nun auf.

Für meinen Fall empfiehlt sich die Teilung in ungefähr gleich große Teile. Daher teilen wir bei 3000 Zeilen.

Dafür brauchen wir die beiden anderen Variablen.

Wir befüllen die Variable “Teil1” mit dem folgenden Inhalt:

take(variables(‘Test’), 3000)

Damit nehmen wir uns die ersten 3000 Zeilen.

Und nun schreiben wir in die Variable “Teil2” folgendes:

skip(variables(‘Test’),3000)

Damit überspringen wir die ersten 3000 Zeilen.

Nun haben wir also statt einem Array mit bis zu 6000 Zeilen 2 Arrays mit jeweils 3000 Zeilen.

Diese können wir nun in je einer For each Action in unsere
Sharepointliste oder in ein Excel schreiben bzw. was immer wir noch
damit anstellen wollen.

Um den Grenzwert von 10000 Aktionen pro Flow nicht zu
überschreiben kann man diese Variante auch nutzen und 2 oder mehr Flows
schreiben in der jeder Flow einen Teil der Daten verarbeitet.

Ist die Anzahl der zu erwarteten Zeilen unbekannt, könnt ihr
natürlich noch mehr Variablen initialisieren und die Teilung immer bei
5000 vornehmen. Variablen die keinen Inhalt mehr liefern werden im Flow
einfach übersprungen.

So das war mein erster Beitrag zu dem Thema.

Beim nächsten Mal schauen wir uns an wie wir damit umgehen wenn
das Ergebnis der Zeilen unbekannt ist und wir daher mit verschachtelten
“For each” Aktionen arbeiten müssen sowie der “Repeat until” Aktion.