Vue lecture

Il y a de nouveaux articles disponibles, cliquez pour rafraîchir la page.
✇Blog Microsoft Power Apps

Exécuter un Flow sous condition après enregistrement d’un formulaire

Difficulté 1/5

À la soumission d’un formulaire, vous souhaitez lancer un flow en fonction d’une condition. Le problème est que si vous liez votre flow au Onsuccess, il se déclenchera même si la condition n’est pas remplie.

Exemple :

Votre application gère des demandes d’accès à un site.

À la validation d’une demande, vous souhaitez en informer le demandeur via Teams, lui envoyer un plan d’accès par email et ajouter une tâche dans Planner aux équipes en charge de configurer les badges.

Si vous déclenchez votre Flow directement sur le OnSuccess de votre formulaire, même si vous l’avez placé dans une condition, les différentes actions se réaliseront même en cas de refus.

Pour contourner le problème, créez un bouton et liez le flow sur sa propriété OnSelect. Changez le OnSuccess de votre formulaire en passant de :

If( FormulaireDeDemande.LastSubmit.Statut.Value = "Acceptée"; Run.FlowDeValidation( FormulaireDeDemande.LastSubmit.Statut .ID))

à :

 If( FormulaireDeDemande.LastSubmit.Statut.Value = "Acceptée";  Select(BoutonFlow))

Puis masquez votre bouton. Ainsi le flow est déporté et ne s’executera que si la condition est remplie.

Note 1 : ne placez pas votre bouton dans le formulaire mais directement dans le Screen.

Note 2 : utilisez les fonctions RestForm ou NewForm après l’utilisation de LastSubmit.

Note 3 : si vous souhaitez revenir sur l’écran précédent après enregistrement, placez la fonction Back après l’exécution du Flow. La fonction Select interagie uniquement avec les contrôles présents dans son écran.

free-to-use-sounds-zxn-zuztohu-unsplash

g2i365

✇Blog Microsoft Power Apps

Set ou UpdateContext ?

Résumé en bas de page

Difficulté : 1/5

Ces deux fonctions permettent de stocker provisoirement des données dans Power Apps.

Vous pourrez vous en servir pour garder en mémoire du texte, des chiffres, des dates, des objets et tout autre type de données présent dans votre application.

Il est important de souligner que les valeurs qu’elles contiennent sont supprimées une fois l’application fermée.

Si vous souhaitez les conserver, vous devrez utiliser un formulaire ou la fonction Patch pour les enregistrer sur votre base de données ou SaveData pour les sauvegarder localement sur votre téléphone ou tablette.

Une mauvaise utilisation de ces variables peut engendrer des calculs inutiles et impacter la performance de votre application.

SET

Cette fonction permet de définir une variable que vous pourrez utiliser sur l’intégralité des écrans de votre application.

Dans l’idéal, il faudrait qu’un set soit initialisé et jamais modifié. Etant présent dans l’intégralité des pages, un changement pourra avoir une répercussion sur tous les contrôles qui en font l’usage. En fonction de la complexité de votre app, cela peut générer beaucoup de calculs et impacter sérieusement ses performances.

Exemple :

Vous souhaitez gérer l’accès à différents espaces ou fonctionnalités de votre app en fonction de la personne connectée.
Créez la variable _RoleUtilisateurActuel sur la propriété OnStart de votre application et définissez-la par le rôle de la personne enregistrée dans une table de droit.

Set(_RoleUtilisateurActuel ; LookUp( BaseDeDroits; User().Email = EmailDeLaBaseDeDroit ).Role)

Vous pourrez ainsi modifier la propriété Visible d’un bouton pour l’afficher uniquement aux utilisateurs qui ont un rôle de gestionnaire.

_RoleUtilisateurActuel = "Gestionnaire"

Cette variable est initialisée une seul fois, elle ne sera pas modifiée et pourra être utilisée sur tous les écrans.


UpdateContext

A l’inverse du set, cette variable est exploitable dans un écran à la fois.

Ainsi, même si vous utilisez cette variables sur l’intégralité de votre app, aucun calcul ne sera réalisé sur les écrans non visibles.

Elle peut également stocker des tables cependant Collect ou Table sont plus adaptés.

Cette fonction peut s’utiliser de deux façons :

– Stocker une information dans une page : UpdateContext({ _NomDeLaVariable : Valeur })
– Conserver une information en changeant d’écran : Navigate(Ecran2 ; ScreenTransition.Cover ; { _NomDeLaVariable : Valeur })

Résumé

SetUpdateContext
DisponibilitéToute l’applicationUne page
Point fortDisponible partout et initiable dans OnStartSa modification n’engendre pas de calculs sur d’autres écrans
Point faiblePeut ralentir le fonctionnement de l’applicationDoit être initialisé sur chaque écran
Bonne pratiqueStoker des informations légères et ne pas les modifierEmbarquer d’un écran à un autre uniquement les informations utiles

Aller plus loin dans la compréhension des variables : https://docs.microsoft.com/fr-fr/powerapps/maker/canvas-apps/working-with-variables

Pour en savoir plus sur l’optimisation des performances de votre application : https://docs.microsoft.com/fr-fr/powerapps/maker/canvas-apps/performance-tips


J’espère vous avoir aidé à y voir plus clair. Si vous avez des contre-exemples ou d’autres précisions à apporter, partagez-les en commentaire 🙂

burst-aoN3HWLbhdI-unsplash

g2i365

✇Blog Microsoft Power Apps

Comprendre et adapter l’écran calendrier au format français

Niveau de difficulté : 3/5

Ressource disponible en fin d’article

Nombreux sont les cas où l’on a besoin d’un calendrier. Celui proposé dans le bouton « Nouvel écran » est un très bon début mais n’est pas au format français, c’est selon moi l’un des éléments les plus complexes à prendre en main.

Voici son fonctionnement et comment l’adapter.

  1. Son fonctionnement

Une liste déroulante permet de sélectionner un de nos calendriers. Dans sa propriété « OnSelect », des variables sont définies pour afficher les évènements dans une gallery. Voici le détail et les explications de chacune des variables.

If(IsBlank(_userDomain); // Permet de définir les variables suivantes si elles ne l'ont pas déjà été.
         
	UpdateContext({_showLoading: true});; // Permet d'afficher un loader ou autre élément permettant d'afficher un message de chargement.
         
	Set(_userDomain; Right(User().Email; Len(User().Email) - Find("@"; User().Email)));; // Ajoute dans une variable le domaine de l'utilisateur connecté.
        
	Set(_dateSelected; Today());; // Ajoute dans une variable la date du jour 
         
	Set(_firstDayOfMonth; DateAdd(Today(); 1 - Day(Today()); Days));; // Ajoute dans une variable le premier jour du mois    

	Set(_firstDayInView; DateAdd(_firstDayOfMonth; -(Weekday(_firstDayOfMonth) - 2 + 1); Days));; // Définit dans une variable le premier jour à afficher dans la gallery de date 
        
	Set(_lastDayOfMonth; DateAdd(DateAdd(_firstDayOfMonth; 1; Months); -1; Days)));;   // Définit dans une variable le dernier jour à afficher dans la gallery de date 
        
       
Set(_calendarVisible; false);;  // Permet de masquer la gallery calendrier pendant le chargement.  
     
UpdateContext({_showLoading: true});; // Affiche l'élément de chargement et masque la gallery de date
     
Set(_myCalendar; Self.Selected);;   // Place le choix effectué dans la liste  
     
Set(_minDate; DateAdd(_firstDayOfMonth; -(Weekday(_firstDayOfMonth) - 2 + 1); Days));; // Sert de mémoire tampon en définissant la date de début pour éviter les doublons

Set(_maxDate; DateAdd(DateAdd(_firstDayOfMonth; -(Weekday(_firstDayOfMonth) - 2 + 1); Days); 40; Days));;  // Sert de mémoire tampon en définissant la date de fin pour éviter les doublons       

ClearCollect(MyCalendarEvents; Office365Outlook.GetEventsCalendarViewV2(_myCalendar.Name; Text(_minDate; UTC); Text(_maxDate; UTC)).value);; // Place dans une collection les évènements du mois en cours du calendrier sélectionné     
   
UpdateContext({_showLoading: false});; // Masque l'élément de chargement pour afficher la gallery de date
      
Set(_calendarVisible; true) // Permet d'afficher la gallery calendrier une fois le chargement terminé

Le calendrier est composé de 5 éléments :

  • Un texte affichant le mois et l’année
  • Un bouton pour charger le mois précédent
  • Un bouton pour charger le mois suivant
  • Une gallery de semaine
  • Une gallery de date

Les deux boutons modifient les variables initialisées dans la liste déroulante pour charger les éléments du mois suivant ou précédent.

La gallery de date a pour « Items » un tableau de chiffres allants de 0 à 41, soit 42 éléments, soit 6 semaines. Divisée en 7 colonnes, elle permet d’afficher une ligne par semaine et se compose de 3 éléments :

  • Un label affichant le numéro du jour. Sa propriété « OnSelect » définit la variable _dateSelected avec le jour sélectionné. Le numéro affiché est l’adition de la variable _firstDayInView et de la valeur de l’élément. Ainsi on aurait pour un début de mois commençant en début de semaine :
    Lundi : 1 + 0 = 1
    Mardi : 1 + 1 = 2
    Mercredi 1 + 2 = 3 etc…
    Sa propriété « Visible » permet d’être masquée si la semaine complète n’est pas dans le mois en cours. On évite ainsi du « bruit ».
  • Un cercle permettant d’afficher la sélection de l’utilisateur (Subcircle). Il se rend visible lorsque la date sélectionnée est égale au jour de la gallery.
  • Un cercle signalant qu’un évènement est présent dans le calendrier (Circle). Il se rend visible quand un élément dans la collection MyCalendarEvents correspond au jour de la gallery.

2) L’adapter au format français

Le principe sera de positionner le lundi en première colonne de la gallery et d’indiquer dans les différentes variables que le premier jour de la semaine n’est pas le dimanche mais le lundi.

Voici les différents espaces à configurer et le code à remplacer :

  • La propriété « Items » de la gallery de semaine :
["lun";"mar";"mer";"jeu";"ven";"sam";"dim"]
  • La propriété « OnSelect » du menu déroulant :
If(IsBlank(_userDomain);         
	UpdateContext({_showLoading: true});;         
	Set(_userDomain; Right(User().Email; Len(User().Email) - Find("@"; User().Email)));;         
    Set(_dateSelected;Today());;
    Set(_firstDayOfMonth;DateAdd(Today();1-Day(Today());Days));;
    Set(_firstDayInView;DateAdd(_firstDayOfMonth;-(Weekday(_firstDayOfMonth;StartOfWeek.Monday)-2+1);Days));;
    Set(_lastDayOfMonth;DateAdd(DateAdd(_firstDayOfMonth;1;Months);-1;Days));;   
);;   
      
Set(_calendarVisible; false);;         
UpdateContext({_showLoading: true});;         
Set(_myCalendar; Self.Selected);;         
Set(_minDate;DateAdd(_firstDayOfMonth;-(Weekday(_firstDayOfMonth)-2+1);Days));;
Set(_maxDate;DateAdd(DateAdd(_firstDayOfMonth;-(Weekday(_firstDayOfMonth)-2+1);Days);40;Days));;        
ClearCollect(MyCalendarEvents; Office365Outlook.GetEventsCalendarViewV2(_myCalendar.Name; Text(_minDate; UTC); Text(_maxDate; UTC)).value);;         
UpdateContext({_showLoading: false});;         
Set(_calendarVisible; true)
  • La propriété « OnSelect » du bouton de gauche
/*Change les variables avec le mois précédant*/
Set(_firstDayOfMonth; DateAdd(_firstDayOfMonth; -1; Months));;
Set(_firstDayInView; DateAdd(_firstDayOfMonth; -(Weekday(_firstDayOfMonth;Monday) - 2 + 1); Days));;
Set(_lastDayOfMonth; DateAdd(DateAdd(_firstDayOfMonth; 1; Months); -1; Days));;

/*Collecte les évènnement du calendrier du mois précédent. Met à jour _minDate pour éviter les doublons si l'utilisateur reviens sur ce mois*/
If(_lastDayOfMonth > _maxDate; Set(_maxDate; _lastDayOfMonth);; 
Collect(MyCalendarEvents; Office365Outlook.GetEventsCalendarViewV2(_myCalendar.Name; Text(_minDate; UTC); Text(_lastDayOfMonth; UTC)).value))
  • La propriété « OnSelect » du bouton de droite
/*Modifie les variables pour afficher le mois précedant*/
Set(_firstDayOfMonth; DateAdd(_firstDayOfMonth; 1; Months));;
Set(_firstDayInView; DateAdd(_firstDayOfMonth; -(Weekday(_firstDayOfMonth;Monday) - 2 + 1); Days));;
/*Collecte les évènement du calendrier du mois suivant. Met à jour _maxDate pour éviter les doublons si 'utilisateur reviens sur ce mois.*/
Set(_lastDayOfMonth; DateAdd(DateAdd(_firstDayOfMonth; 1; Months); -1; Days));;
If(_lastDayOfMonth > _maxDate; Set(_maxDate; _lastDayOfMonth);;
 Collect(MyCalendarEvents; Office365Outlook.GetEventsCalendarViewV2(_myCalendar.Name; Text(_firstDayOfMonth; UTC); Text(_maxDate; UTC)).value))
  • La propriété « Visible » du label de la gallery de date
 !(DateAdd(_firstDayInView;ThisItem.Value;Days) - Weekday(DateAdd(_firstDayInView;ThisItem.Value;Days);StartOfWeek.Monday) +1  > _lastDayOfMonth)

Vous pouvez télécharger une application via ce lien dont les changements ci-dessus ont déjà été réalisés.


Bonus

Griser les évènements antérieur à aujourd’hui. Dans la propriété « Fill » du cercle d’évènement :

If(DateAdd(_firstDayInView;ThisItem.Value;Days)>=Today();RGBA(186; 202; 226; 1);
RGBA(128; 128; 128; 1))

J’espère que cet article vous aidera à y voir plus clair et vous aidera dans votre développement.

Si vous avez des idées d’optimisation, n’hésitez pas à les partager en commentaire.

whatsapp-video-2021-03-07-at-20.42.47-1

g2i365

✇Blog Microsoft Power Apps

Les 4 étapes à ne pas oublier à la création d’une app Power Apps

Certaines choses simples sont à faire dès la création de l’application pour s’éviter des problèmes plus tard. Avant même de placer un bouton ou le logo de votre entreprise, voici les étapes à ne pas manquer :

1) Créer l’application au format tablette (ou paysage)

Créer l’application dans ce format vous permettra de basculer vers le format téléphone (portrait). Alors que ce n’est pas possible en mode téléphone.

2) Augmenter la délégation à 2000

Si vous utilisez des listes SharePoint ou des tableaux Excel (ce que je déconseille) comme base de données, vous allez vous confronter à la délégation de Power Apps.
Même si l’idéal est d’arriver à contourner cette délégation, il est préférable de placer ce paramètre au maximum. Notamment si vous réalisez des collections à partir de jeux de données importants.

Pour ce faire, allez dans Fichier / Paramètre / Paramètre avancé et passez le paramètre à 2 000

3) Changer la tailler de l’app au format full HD

Comme tout le monde n’a pas forcément la chance de travailler sur un UltraWild en 4K, le full HD est le compromis idéal pour que tous les utilisateurs puissent avoir une bonne expérience sur votre application.

Allez dans Fichier / Paramètre / Taille et orientation de l’écran, placez le paramètre à « Personnalisé » et changez les hauteur et largeur avec 1920 / 1080.

Si votre application est destinée à un usage mobile et que par chance votre flotte est uniforme, n’hésitez pas à reprendre le même format.

Si vous décidez de faire ce changement en cours de route, tous vos items garderont la même proportion qu’ils prenaient dans votre app avant le changement. Vous devrez donc reprendre chacun des éléments pour lui attribuer une taille convenable. Bonne chance.

4) Enregistrez l’application

Nombreuses sont les fois où j’ai commencé à travailler sur une application sans l’avoir enregistrée une première fois. Et, avec l’habitude de l’enregistrement automatique, je ferme le navigateur. Jusqu’au moment où je cherche à l’ouvrir de nouveau et que … Elle n’existe pas. S’il vous plait, évitez-vous ça : ça fait mal !


J’espère que cette liste vous sera utile et que vous ne tomberez pas dans les mêmes pièges que moi.

N’hésitez pas à placer en commentaire une autre habitude que vous avez.

sigmund-By-tZImt0Ms-unsplash

g2i365

✇SharePoint Trenches

Build TreeView with XML data in PowerShell [Tip]

In one of my recent scripts I worked on, I had to visualize XML data in a tree view manor.
I achieved this by using the TreeView Windows Forms control and I think that the result is good and can be used as an example if you have to do something similar.
I tweaked the function and made it a standalone "XML Browser" script that is visualizing the XML document and if you double click on the element you will copy the Outer XML text to the clipboard.

PowerShell XML Browser

In order to visualize xml you need to supply the path to it and the starting element. On the screenshot above I have a web.config file loaded and the starting element I want to visualize is "configuration". You can find the code and the example below. I hope you find it helpful!


✇SharePoint Trenches

Troubleshoot PowerShell Add-Type Load Error [Tip]

In the last couple of days I am working with a client that has a DMS solution based on SharePoint Server 2010. We inherited the solution so it has it's specifics. One of those little things (that make life exciting) is that they have fields with custom data types. 
I had to do a powershell script that will edit some document metadata. I had to update standard SharePoint native data type fields, but after updating the item in powershell I lost the values of the custom data type fields. I realized that I need the custom data type loaded in the powershell session. So I started to import some DLLs, in the order that I thought it makes sense as we do not have the source code of the solutions.This was fine until I received the error below:

Add-Type : Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.

This error is completely generic and the only useful thing is that it tells us where we can find more useful information.
This simple error handling script turned out to be life saver for me as it showed exactly what the load error is and which dependent assembly I need to load first :)


The nice blue text is our LoaderExceptions property of the exception. I hope that you find it useful!
LoaderExceptions Powershell

✇SharePoint Trenches

Get a quick report of the SharePoint Databases with PowerShell [Tip]

Here comes another useful PowerShell one-liner I often use.
It will give you a quick overview of the SharePoint databases with properties like: Name, Server(Alias), TypeName, Web application name, Web application URL, Site collection count and the Size.
The size is actually the amount of disk space required for uncompressed backup. It might look something like a script, but actually it is a long and simple one-liner. You can see it below, I have used grave-accent(`) escape characters to fit it better in the blog. You can see it in one line here. Instead of piping to Format-Table you can generate CSV by piping to Export-CSV and later work with it in Excel.

Get-SPDatabase | Select-Object Name,@{Expression={$_.Server};Label="Server"},TypeName,@{Expression=`
{$_.WebApplication.Name};Label="WebAppLication"},@{Expression={$_.WebApplication.Url};Label="WebAppLicationUrl"}`
,@{Expression={($_.WebApplication.Sites | Measure).Count};Label="SC Count"},@{Label ="Size in MB";`
 Expression ={$_.disksizerequired/1024/1024}} |  Format-Table -AutoSize

Get SharePoint database report

✇SharePoint Trenches

Get Application Pool Identity credentials[Tip]

In this short tip I am going to post a PowerShell one-liner from my list of extremely useful one-liners. It can get the the credentials of the IIS application pools identity.
I use it mainly in two scenarios:
  1. Imagine that you will do a remote work on customer where you have only temporary access and credentials. Many times the account that is provided is Farm Admin, has local admin permissions on the SharePoint boxes, however it does not have permission to use PowerShell against SharePoint(no Shell Admin). You can use this short PowerShell script and get the Farm account(STS is running under it), many times it is left in the local admin group and you can log in with it and do what you need to do. Not a best practice, but it is a massive time saver.
  2. Imagine that you are working on issue where you need to restart the User Profile Synchronization Service instance and you need the Farm account password. You can get it with this script.

In order to use it you will need to have local admin permission. I can confirm that it is working on IIS 7.5,8.0 and 8.5.

Get-WmiObject -Namespace "root\MicrosoftIISV2" -Class "IIsApplicationPoolSetting" | Select WAMUserName, WAMUserPass

Get IIS Application pool credentials

❌