La notion de pagination est fondamentale, il est important de savoir que l’API Sage 100 renvoie à chaque demande un maximum de 100 enregistrements.

Pourquoi limiter à 100 enregistrements ?

Les données requêtées par l’API Sage 100 vont transiter entre le serveur local Sage 100 et Microsoft 365. Si une table de votre base de données contient des milliers d’enregistrements, vous ne pouvez pas les envoyer en une seule demande à la fois pour des raisons de volumétrie et de sécurité.
Pour éviter ce problème, le serveur peut limiter le nombre d’enregistrements qu’il envoie à chaque demande.
Pour l’API Sage 100 cette limite a été fixée à 100.

Note : cette limite s’applique pour les requêtes sur les ressources, les appels de fonction pour récupérer des données telles que les statistiques clients ou statistiques articles ne sont pas concernées par cette limite.

Notion de pagination

Exemple

Imaginons que votre app Power Apps souhaite afficher une liste de clients selon des critères de filtres :

  • Votre dossier contient 6500 clients,
  • le filtre actuellement défini par l’utilisateur a été transmis à travers votre requête au serveur, le serveur a trouvé localement 175 clients répondant aux critères de filtre,
  • côté app Power Apps, la requête va retourner 100 enregistrements et non 175,
  • pour que l’utilisateur puisse consulter les 175 résultats, il est nécessaire que vous définissiez une pagination,
  • vous pourrez pour cela prévoir un bouton Suivant pour que votre utilisateur puisse consulter les 100 premiers résultats puis les 75 suivants.


L’application d’exemple Vision Clients exploite la pagination lors de la recherche des clients,
voir : Exemples / Vision Clients.

Utilisation de $count et $skip

Pour gérer la pagination vous devez connaître le nombre total d’enregistrements répondant aux critères de filtre de votre requête et le nombre d’enregistrements renvoyés à chaque appel afin de définir le nombre d’enregistrements à sauter en utilisant $skip.

Paramètre Type Description
$skip integer Jeton de pagination pour obtenir l’ensemble des résultats suivants
$count boolean Nombre total d’éléments répondants à la requête
Exemple

Depuis Power Apps, récupérer le nombre de comptes de charge du plan comptable (comptes de classe 6) :

  • $count est forcé à true pour que le total d’enregistrements répondant au filtre $filter soit disponible dans '@odata.count'
  • Dans cet appel $top est forcé à 0 puisqu’on ne souhaite pas récupérer les enregistrements mais juste le total, inutile donc que le serveur renvoie des données autre que ce total.
  • '@odata.count' renvoie le total réel calculé côté serveur, ce total peut donc être supérieur à la limite des 100 enregistrements que l’API renverra à chaque appel.


Set(currentCompanyId;"{datasetId}");;
 Sage100cloud.ComptesGetByDatasetid(
      currentCompanyId;
      {
        '$filter': "startswith(numero,'6') and type eq 'Detail'";
        '$top': 0;
        '$count': true
      }   
  ).'@odata.count';;

Maintenant que nous connaissons le total d’enregistrements ('@odata.count') et le nombre d’enregistrements (par défaut 100), nous pouvons gérer la pagination.
Il suffira d’incrémenter à chaque appel $skip avec le nombre total d’enregistrements déjà lus.

Exemple
  • Le total est de 257 enregistrements,
  • le maximum par appel est 100 enregistrements,
  • le premier appel se fait avec $skip:0, les enregistrements de 1 à 100 sont retournés,
  • le second appel se fait avec $skip:100, les enregistrements de 101 à 200 sont retournés,
  • le troisième se fait avec $skip:200, les enregistrements de 201 à 257 sont retournés,
  • pas d’appels supplémentaires nécessaires, $skip+100 étant maintenant supérieur au total 257.
    En comparant le total récupéré via '@odata.count' et la valeur courante affectée à $skip il est facilement possible de désactiver ou activer des boutons Précédent et Suivant et d’associer à chacun de ces boutons un traitement pour augmenter le compteur passé à $skip ou le diminuer puis appeler de nouveau la requête.
Notes importantes
  • Si $orderby est défini pour trier le résultat, il s’applique toujours côté serveur et donc s’applique à la totalité du résultat et non aux 100 premiers enregistrements.
  • Par contre si vous appliquez dans Power Apps un tri Sort ou SortBYColumns ce tri sera local à la collection.
    Si par exemple vous récupérez les 100 factures les plus récentes en estimant que ce nombre est suffisant pour l’utilisateur, si ensuite côté PowerApps vous appliquez un Sort sur la collection, vous ne triez que les 100 enregistrements récupérés à l’inverse du $orderby qui s’applique à la totalité du résultat côté serveur.
  • Remarque identique si vous appliquez un Filter ou Search ou LookUp , le filtre ne s’appliquera qu’au 100 enregistrements à l’inverse de $filter qui s’applique à la totalité des données côté serveur.

Recommandations

Dossier de tests avec suffisamment de données

Nous vous recommandons d’utiliser un dossier avec suffisamment de données pour ne pas être piégés si pour certaines requêtes le seuil des 100 enregistrements n’est pas atteint.
Par exemple, si vous testez avec la société BIJOU de démonstration Sage 100, comme ce dossier a un nombre de clients, de devis, de factures inférieur à 100, vous pourriez croire, si vous avez omis de gérer la pagination, que votre développement est correct.
Mais une fois mise en production, votre application utilisée avec un dossier contenant des données réelles avec plus de 100 clients, ou devis ou factures, empêcherait l’utilisateur d’accéder aux données au delà des 100 premiers enregistrements.

Ou simuler la limite à moins de 100 enregistrements

Une astuce consiste aussi à définir un paramètre global nommé par exemple maxPaginate avec une valeur inférieure au nombre d’enregistrements moyens de votre dossier de tests.
Par exemple vous pouvez affecter maxPaginate avec la valeur 10. Puis lors de vos requêtes, affectez toujours le paramètre $top avec maxPaginate, ainsi vos requêtes ne renverront que le nombre maximal mentionné dans maxPaginate.
Vous serez alors plus rapidement alertés lors de la conception de votre application que vous devez gérer la pagination pour permettre à l’utilisateur d’accéder à l’ensemble des données et non à une vue tronquée des données.
Une fois la pagination testée et votre développement opérationnel, vous pourrez affecter maxPaginate avec la valeur 100 et votre développement continuera à fonctionner.

Paramètre Type Description
$top integer Nombre d’éléments à retourner dans la réponse
Exemple

L’exemple ci-dessous permet de simuler que l’API va renvoyer un maximum de 10 enregistrements au lieu de la limite standard de 100 enregistrements.
Bien évidemment, pour tester la pagination dans ce contexte, il faudra que $skip soit aussi incrémenté par pas de 10 et non par pas de 100.
L’exemple illustre l’appel à la première page avec $skip affecté à 0. Pour les pages suivantes, il faudra incrémenter cptPage de 1 à chaque fois pour que $skip contienne 10 puis 20, etc. et non 100 puis 200, etc.


Set (maxPaginate;10);;  // Valeur max du $top pour les tests
Set (cptPage;0);;       // Compteur de pages pour affecter $skip

...

Set(currentCompanyId;"{datasetId}");;
 Sage100cloud.ComptesGetByDatasetid(
      currentCompanyId;
      {
        '$expand': Blank();
        '$select': "intitule,numero";
        '$filter': Blank();
        '$orderby':"numero";
        '$top': maxPaginate;
        '$skip': cptPage*maxPaginate;
        '$count': Blank()
      }   
  ).value;;

Note : Bien que la valeur maximale du nombre d’enregistrements retournés par l’API soit 100, rien ne vous oblige à afficher une pagination de 100 enregistrements à la fois.
Vous pouvez par exemple décider que chaque page contiendra 50 enregistrements, c’est le cas des exemples Vision Clients et Catalogues et Stocks qui gèrent une liste de 50 clients ou 50 articles par page.

Boucler sur la pagination pour récupérer tous les enregistrements

Pour certains usages, il peut être nécessaire de récupérer la totalité des enregistrements.
Ce peut être le cas lorsque l’on sait que le nombre total d’enregistrements restera faible mais néanmoins risque de dépasser 100.
A l’exemple des familles de produits que l’on souhaiterait choisir dans une liste déroulante, s’il y a 130 familles il faut que ces 130 familles apparaissent dans la liste de choix.

En appliquant la logique de pagination, il est possible de boucler pour récupérer la totalité des enregistrements.

L’exemple Power Apps ci-dessous montre :

//utilisé itérer au prorata du nombre de pages de familles
Set(colIterate;"||||||||||||||||||||||||||||||||||||");;  
 //Nombre maxi d'enregistrements renvoyés par l'API
Set(apiPagesize;100);;

//Initialisation collection familles
ClearCollect(familles;{code:"";intitule:""});;Clear(familles);;
 // Ajout en premier du choix <Tous>  
ClearCollect(familles;{code:"<Tous>";intitule:"<Tous>"});;      
With (
  {
    // Nb de pages = @odata.count / apiPagesize
    MaxIterate:RoundUp(
         Sage100cloud.FamillesGetByDatasetid(currentCompanyId;{'$top':0;'$count':true;'$filter':"type eq 'Detail'"}).'@odata.count'/apiPagesize
         ;0);
    // Nb enregistrements collection famille avant ajout des données famille     
    RowsInit:CountRows(familles)
   };
   //On utilise les MaxIterate car. de la chaîne colIterate pour provoquer une boucle car pas de for i dans Power Apps.
   ForAll(
       Split(Left(colIterate;MaxIterate);"|");
       Collect(familles;AddColumns(Sage100cloud.FamillesGetByDatasetid(currentCompanyId;
               {
                 '$select':"intitule,code";
                 '$top':apiPagesize;
                 '$skip':CountRows(familles)-RowsInit;
                 '$filter':"type eq 'Detail'"
               }).value;
               "intituleComplet";intitule&" ("&code&")")
       )
   )
);;

Vous trouverez un exemple similaire dans l’application d’exemple Exemples / Catalogues et stocks
dans le code OnSelect de l’objet Choix sociétés.