BA-IT
Tous les articles
Power Automate 22 octobre 2026 13 minAhmed Bouchaala, Power Platform Solution Architect et président de BA-ITPar Ahmed Bouchaala

Synchroniser un Excel vers une liste SharePoint sans dépasser les 6 000 appels par jour

BA-IT utilise un Office Script pour comparer un fichier Excel à une liste SharePoint et n'écrire que les lignes réellement modifiées. Sur un fichier de 5 000 lignes dont 50 changent dans la journée, la méthode classique consomme plus de 15 000 requêtes Power Platform et dépasse le quota de 6 000 d'une licence Microsoft 365. La méthode décrite ici en consomme une quinzaine, sans aucune licence premium.

Résumer cet article avec une IA

Le lien ouvre l'assistant choisi avec une question pré-remplie pointant vers cette page.

La réponse courte

Un utilisateur sous licence Microsoft 365 dispose de 6 000 requêtes Power Platform par période de 24 heures (Microsoft Learn - Requests limits and allocations). Un flux qui boucle sur 5 000 lignes Excel pour les comparer une à une à SharePoint en consomme plus de 15 000. Il dépasse donc le quota dès la première exécution.

La solution tient en une phrase : chaque action Power Automate coûte une requête, le code exécuté dans un Office Script n'en coûte aucune. On déplace la comparaison dans le script, et on n'écrit dans SharePoint que les lignes réellement modifiées, par lots de 100 via $batch.

Résultat sur le même fichier : une quinzaine de requêtes au lieu de plus de 15 000, sans licence premium.

Le problème : la boucle qui vide votre quota

Le réflexe, quand on veut synchroniser un Excel vers SharePoint, c'est un flux Power Automate qui lit le tableau et boucle sur chaque ligne.

Dans la boucle : chercher la ligne correspondante dans SharePoint, comparer, mettre à jour si besoin.

Ça marche. Et ça vous coûte très cher.

Microsoft est explicite sur ce point : chaque action génère une requête, et une action dans une boucle « Appliquer à chacun » en génère autant qu'il y a d'éléments à traiter (Microsoft Learn - Understand platform limits). Les actions intégrées comptent aussi : initialiser une variable, un Compose, une condition. Les tentatives de reprise et la pagination également.

Voici l'addition sur 5 000 lignes :

Action Requêtes
Déclencheur 1
Lire le tableau Excel (avec pagination) ~10
Dans la boucle : obtenir les éléments SharePoint 5 000
Dans la boucle : condition de comparaison 5 000
Dans la boucle : créer ou mettre à jour 5 000
Total plus de 15 000

Le quota de 6 000 est celui des licences dites « seeded » : Microsoft 365, Power Apps par application, Dynamics 365 Team Member. Pour atteindre 40 000, il faut une licence Power Apps Premium ou Power Automate Premium.

Deux précisions que la plupart des tutoriels passent sous silence.

La fenêtre est glissante, pas calendaire. À chaque exécution, le système regarde les requêtes des 24 dernières heures. Un flux qui tourne la nuit ne repart pas d'un compteur à zéro le matin.

Les quotas ne se reportent pas. Ce que vous ne consommez pas aujourd'hui est perdu.

Nous sommes par ailleurs dans une période de transition pendant laquelle Microsoft applique les limites par flux plutôt que par utilisateur, avec un plafond plus généreux. Cette tolérance a une fin annoncée. Concevoir un flux en s'appuyant dessus, c'est signer pour une panne à retardement.

Le principe : déplacer le calcul là où il est gratuit

Un Office Script s'exécute dans Excel, pas dans Power Automate. Qu'il traite 10 lignes ou 50 000, l'action « Exécuter le script » compte pour une seule requête.

La comparaison de 5 000 lignes ne doit donc pas se faire dans une boucle Power Automate. Elle doit se faire dans le script.

Le flux devient :

  1. Lire la liste SharePoint, en ne récupérant que la clé, la signature et l'identifiant
  2. Passer cet instantané au script
  3. Le script lit le tableau Excel, calcule une empreinte par ligne, compare, et renvoie uniquement les écarts
  4. Écrire ces écarts dans SharePoint par paquets de 100, en une requête par paquet

Ce qu'un Office Script peut faire, et ce qu'il ne peut pas

Avant d'écrire la moindre ligne, quatre contraintes documentées par Microsoft qui déterminent toute l'architecture (Platform limits and requirements with Office Scripts).

Aucun appel réseau. fetch n'existe pas dans un script exécuté par Power Automate. Le script ne peut pas joindre SharePoint lui-même. Il reçoit des données en paramètre, il en renvoie. C'est tout.

Ni Crypto ni TextEncoder. Ces API web ne sont pas disponibles (Troubleshoot Office Scripts running in Power Automate). Oubliez SHA-256 : il faut un hachage écrit en JavaScript pur. C'est le point qui fait échouer la plupart des tentatives trouvées en ligne.

1 600 exécutions par utilisateur et par jour. Le compteur se remet à zéro à minuit UTC. Confortable pour une synchronisation, mais ce n'est pas illimité.

120 secondes, 5 Mo de données Excel, 28,6 Mo de paramètres. Le délai est la contrainte la plus serrée. En pratique on en est loin : la comparaison de 5 000 lignes présentée ici s'exécute en moins de 20 millisecondes.

Le script

Trois fonctions. La normalisation, l'empreinte, la comparaison.

La normalisation, étape qu'on oublie toujours

Sans elle, " Dupont " et "Dupont" produisent deux empreintes différentes. Résultat : une mise à jour déclenchée à chaque exécution, sur une ligne qui n'a pas changé. Le quota repart à la hausse et on ne comprend pas pourquoi.

Même chose pour les nombres. Excel stocke parfois 10.0000000001 là où l'utilisateur a saisi 10. On arrondit à six décimales : au-delà, c'est du bruit de virgule flottante, pas une donnée.

function normaliser(valeur: string | number | boolean): string {
  if (valeur === null || valeur === undefined || valeur === "") return "";
  if (typeof valeur === "boolean") return valeur ? "1" : "0";
  if (typeof valeur === "number") {
    if (!isFinite(valeur)) return "";
    const arrondi = Math.round(valeur * 1e6) / 1e6;
    return Object.is(arrondi, -0) ? "0" : String(arrondi);
  }
  return String(valeur).trim().replace(/\s+/g, " ");
}

L'empreinte, sans Crypto

Deux FNV-1a 32 bits avec des graines différentes, concaténés en hexadécimal. Soit 64 bits effectifs.

Le séparateur \u001f entre les valeurs n'est pas un détail : sans lui, les lignes ["AB", "C"] et ["A", "BC"] produisent la même empreinte.

function signature(valeurs: string[]): string {
  let h1 = 0x811c9dc5;
  let h2 = 0x01000193;
  const chaine = valeurs.join("\u001f");

  for (let i = 0; i < chaine.length; i++) {
    const c = chaine.charCodeAt(i);
    h1 ^= c;
    h1 = Math.imul(h1, 0x01000193) >>> 0;
    h2 ^= c;
    h2 = Math.imul(h2, 0x85ebca6b) >>> 0;
    h2 = ((h2 << 13) | (h2 >>> 19)) >>> 0;
  }

  const hex = (n: number) => ("00000000" + n.toString(16)).slice(-8);
  return hex(h1) + hex(h2);
}

Sur un jeu de 50 000 lignes distinctes, cette fonction ne produit aucune collision. C'est largement suffisant pour de la détection de changement.

La comparaison

function comparer(
  entetes: string[],
  corps: (string | number | boolean)[][],
  indexCle: number,
  distant: LigneDistante[]
): Resultat {
  const parCle: { [cle: string]: LigneDistante } = {};
  for (const l of distant) parCle[String(l.cle)] = l;

  const aCreer: Ecart[] = [];
  const aMettreAJour: Ecart[] = [];
  const vues: { [cle: string]: boolean } = {};
  const clesDupliquees: string[] = [];
  let inchangees = 0;
  let lignesExcel = 0;

  for (const ligne of corps) {
    const cle = normaliser(ligne[indexCle]);
    if (cle === "") continue;
    lignesExcel++;

    if (vues[cle]) {
      if (clesDupliquees.indexOf(cle) === -1) clesDupliquees.push(cle);
      continue;
    }
    vues[cle] = true;

    const sig = signature(ligne.map((v) => normaliser(v)));

    const champs: { [entete: string]: string | number | boolean } = {};
    for (let i = 0; i < entetes.length; i++) {
      champs[entetes[i]] = ligne[i] ?? "";
    }

    const existant = parCle[cle];
    if (!existant) {
      aCreer.push({ cle, signature: sig, id: 0, champs });
    } else if (existant.signature !== sig) {
      aMettreAJour.push({ cle, signature: sig, id: existant.id, champs });
    } else {
      inchangees++;
    }
  }

  const aSupprimer: number[] = [];
  for (const l of distant) {
    if (!vues[String(l.cle)]) aSupprimer.push(l.id);
  }

  return {
    aCreer, aMettreAJour, aSupprimer,
    stats: {
      lignesExcel, lignesSharePoint: distant.length,
      creations: aCreer.length, misesAJour: aMettreAJour.length,
      suppressions: aSupprimer.length, inchangees, clesDupliquees,
    },
  };
}

Trois comportements méritent d'être soulignés.

Les lignes vides sont ignorées. Un tableau Excel traîne presque toujours des lignes vides en fin de plage. Sans ce filtre, elles sont créées dans SharePoint à chaque exécution.

Les clés en double sont signalées, pas traitées deux fois. Elles remontent dans les statistiques. C'est une erreur de données que le script ne doit pas masquer.

Les suppressions sont détectées. Une ligne présente dans SharePoint et absente d'Excel ressort dans aSupprimer. À vous de décider si vous supprimez réellement ou si vous archivez : sur des données métier, j'archive.

Le flux Power Automate

Sept actions. Pas une de plus.

1. Déclencheur planifié. Toutes les heures en journée suffit dans la majorité des cas. Interrogez l'usage réel avant de descendre à 15 minutes : chaque exécution consomme son socle de requêtes, même quand rien n'a changé.

2. Obtenir les éléments SharePoint. Un point décisif : utilisez $select pour ne ramener que la clé, la colonne de signature et l'identifiant. Sans cela vous rapatriez toutes les colonnes de 5 000 éléments, pour rien.

3. Sélectionner pour transformer la sortie en tableau compact {cle, signature, id}. Une seule action, pas une boucle.

4. Exécuter le script, en lui passant ce tableau converti en chaîne JSON.

5 à 7. Écrire les écarts par lot. C'est l'autre moitié du gain.

L'écriture par lot : 100 opérations, une requête

SharePoint Online implémente l'option OData $batch (Make batch requests with the REST APIs). Vous envoyez une requête HTTP contenant jusqu'à 100 opérations, et elle compte pour une seule requête Power Platform.

L'action « Envoyer une requête HTTP à SharePoint » appartient au connecteur SharePoint standard. Elle est donc incluse dans une licence Microsoft 365, sans premium.

Le corps est du multipart/mixed :

POST _api/$batch
Content-Type: multipart/mixed; boundary="batch_a1b2c3"

--batch_a1b2c3
Content-Type: multipart/mixed; boundary="changeset_d4e5f6"

--changeset_d4e5f6
Content-Type: application/http
Content-Transfer-Encoding: binary

PATCH https://contoso.sharepoint.com/sites/ops/_api/web/lists/getbytitle('Commandes')/items(42) HTTP/1.1
Content-Type: application/json;odata=verbose
IF-MATCH: *
X-HTTP-Method: MERGE

{"__metadata":{"type":"SP.Data.CommandesListItem"},"Montant":250,"Signature":"3f2a...e91c"}

--changeset_d4e5f6--

--batch_a1b2c3--

Quatre points qui font échouer un premier essai.

Les fins de ligne doivent être des CRLF. Microsoft le documente explicitement : d'autres fins de ligne provoquent des erreurs de désérialisation.

Le type d'entité n'est pas devinable. SP.Data.CommandesListItem se récupère sur _api/web/lists/getbytitle('Commandes')?$select=ListItemEntityTypeFullName. Un nom de liste contenant un espace ou un accent donne un type encodé, pas le nom que vous imaginez.

Un lot n'est pas transactionnel. Microsoft est formel : si une opération du changeset échoue, les autres aboutissent quand même et rien n'est annulé. Lisez la réponse, elle contient le statut de chaque opération.

Les URL internes doivent viser le même site que l'URL de la requête, et elles sont sensibles à la casse.

Le bilan

Même fichier, 5 000 lignes, 50 modifications dans la journée.

Boucle classique Synchronisation différentielle
Lecture Excel ~10 1 (dans le script)
Lecture SharePoint 5 000 ~5
Comparaison 5 000 0 (dans le script)
Écriture 5 000 1
Actions de structure ~10 ~6
Total plus de 15 000 une quinzaine
Quota Microsoft 365 dépassé dès la première exécution 0,25 % du quota

Une exécution par heure sur 12 heures reste sous 200 requêtes par jour. Vous avez de la marge pour le reste de vos flux.

Les pièges rencontrés en production

Le seuil d'affichage des listes SharePoint. Au-delà de 5 000 éléments, une requête sur une colonne non indexée est refusée. Indexez la colonne clé dès la création de la liste, pas quand le problème survient. Le sujet est voisin de celui de la délégation dans Power Apps, traité dans la limite de délégation passe de 2 000 à 10 000 lignes.

La colonne de signature doit être exclue de la signature. Évident une fois écrit, invisible à la relecture. Si vous hachez la ligne SharePoint au lieu de la ligne Excel, la signature se hache elle-même et plus rien n'est stable.

Les dates. Excel les stocke en numéros de série. C'est parfait pour détecter un changement, puisque c'est stable. Mais au moment d'écrire dans SharePoint, il faut convertir. Ne comparez jamais une date formatée : un changement de format de cellule déclencherait une mise à jour fantôme.

L'échec silencieux. Un lot qui renvoie 200 peut contenir dix opérations en erreur. Analysez la réponse et remontez les échecs. Ce travers est détaillé dans détecter les erreurs silencieuses en production, et le motif de gestion d'erreur dans un vrai TRY-CATCH pour vos workflows.

Le propriétaire du flux porte le quota. Un flux planifié consomme les requêtes de son propriétaire, pas de celui qui a modifié le fichier. Un compte de service dédié évite qu'un collaborateur voie ses propres flux ralentir.

Et avec un dataflow Dataverse ?

C'est l'autre façon de faire, décrite en détail dans le guide complet pour synchroniser un Excel avec Dataverse. Les deux approches ne répondent pas à la même question.

Office Script + SharePoint Dataflow Dataverse
Licence Microsoft 365 suffit Power Apps Premium requise
Écriture Seules les lignes modifiées Lecture complète de la source à chaque actualisation
Actualisation incrémentielle Native, c'est le principe Nécessite une destination Azure Data Lake, pas Dataverse
Suppressions Détectées Non gérées par un upsert, à traiter à part
Volume confortable Jusqu'à quelques dizaines de milliers de lignes Centaines de milliers et au-delà
Relations entre tables Faibles Natives
Sécurité par ligne Non Native
Transformation des données À écrire soi-même Power Query, sans code
Mise en place Une journée Deux heures
Maintenance Du code à comprendre Interface graphique

Le point qui tranche le plus souvent, c'est la licence. Un dataflow écrit dans Dataverse, et Dataverse demande une licence premium par utilisateur. Si votre organisation est en Microsoft 365 sans extension, la question est réglée avant même d'avoir commencé. Ce que couvre exactement une licence Microsoft 365 est détaillé dans ce que votre licence inclut vraiment.

Le deuxième point, c'est l'actualisation incrémentielle. Elle existe pour les dataflows, mais la documentation Microsoft est claire : dans Power Apps, elle exige un plan par application ou par utilisateur, et une destination Azure Data Lake Storage (Using incremental refresh with dataflows). Un dataflow qui alimente une table Dataverse relit donc l'intégralité de la source à chaque actualisation. Sur un fichier stable où dix lignes bougent par jour, c'est beaucoup de travail pour peu de changements.

Quand choisir le dataflow quand même : volumétrie importante, besoin de relations entre entités, sécurité par ligne, transformations complexes, ou licences premium déjà en place. Dataverse est un meilleur socle de données que SharePoint, ce n'est pas discutable. La question est de savoir si vous en avez besoin, et si vous le payez déjà.

Quand choisir l'Office Script : un fichier, une liste, pas de licence premium, et un besoin de fraîcheur dans l'heure.

L'arbitrage complet entre les deux socles est sur SharePoint ou Dataverse.

Ce que cette méthode ne résout pas

Elle synchronise un fichier Excel vers SharePoint. Elle ne règle pas le fait que le fichier Excel reste la source de vérité.

Tant que la saisie se fait dans le classeur, vous conservez les mêmes risques : pas de droits par utilisateur, pas d'historique des modifications, une formule qu'un collaborateur casse sans s'en apercevoir. La synchronisation rend les données lisibles ailleurs, elle ne les gouverne pas. Les signes qui montrent qu'un fichier a dépassé sa fonction sont listés dans cinq signaux d'alerte.

C'est une excellente solution transitoire. Ce n'est pas une destination.

Questions fréquentes

Faut-il une licence premium pour synchroniser un Excel vers SharePoint ? Non. Office Scripts demande une licence Microsoft 365 professionnelle. Le connecteur SharePoint, y compris l'action « Envoyer une requête HTTP à SharePoint », est standard.

Jusqu'à combien de lignes cette méthode tient-elle ? La comparaison de 5 000 lignes prend moins de 20 millisecondes, loin des 120 secondes de délai. La contrainte réelle vient du seuil d'affichage SharePoint à 5 000 éléments et de la limite de 5 Mo sur les données Excel. Au-delà de 50 000 lignes, la question de Dataverse se pose.

Que se passe-t-il à la première exécution ? La liste SharePoint est vide, toutes les lignes ressortent en création. Sur 5 000 lignes, c'est 50 lots de 100, soit 50 requêtes. Une seule fois.

Et si quelqu'un modifie directement la liste SharePoint ? Sa signature ne correspondra plus à celle d'Excel, et la ligne sera écrasée à la prochaine exécution. Cette méthode est unidirectionnelle par construction. Une synchronisation bidirectionnelle est un autre sujet, bien plus délicat.

Peut-on faire la même chose vers Dataverse ? Oui, le principe se transpose. Mais si vous avez Dataverse, vous avez une licence premium, donc 40 000 requêtes par jour, et le dataflow devient plus simple à maintenir.

Combien de temps pour mettre ça en place ? Une journée pour un développeur qui connaît Power Automate, en comptant les tests. L'essentiel du temps passe sur la normalisation des données et les cas particuliers de votre fichier, pas sur le script.


Vous avez un fichier Excel qui pilote un processus et vous hésitez entre le synchroniser et le remplacer ? Chiffrez votre application en 5 minutes ou regardez l'offre Transformation Excel.

Sources

Partager cet article

Un projet Power Platform en tête ?

Cadrage, audit, développement ou déblocage d'urgence - parlons-en.

Ahmed Bouchaala, Power Platform Solution Architect et président de BA-IT
Auteur

Ahmed Bouchaala

Power Platform Solution Architect, président de BA-IT

Power Platform Solution Architect certifié PL-600, président de BA-IT. Plus de dix ans sur l'écosystème Microsoft.

En savoir plus sur l'auteur