Répondre à: Requête OData / pagination
-
Bonjour Xavier,
J’ai déjà eu cela avec des limitation à 500 enr par appel. J’ai dû créer des fonctions en M pour gérer cela.
Voici mes fonctions :
importTablenletn Source = (tableImport) =>n letn firstPageUrl = "https://<NomDuSite>/api/" & tableImport,nn output = @GenerateByPage(n (lastPage) =>n letn next = if lastPage <> null then Value.Metadata(lastPage)[Next] else null,n urlToUse = if (next <> null) then next else firstPageUrl,n current = if (lastPage <> null and next = null) then null else getJson(urlToUse),n dataset = if (current <> null) then getDataset(current) else null,n link = if (current <> null) then current[next_page_url] else nulln inn dataset meta [Next=link]n ),nn getDataset = (json) =>n letn ConvertirEnTable = Table.FromRecords({json}),n Developper = Table.ExpandListColumn(ConvertirEnTable, "data"),n GarderData = Table.SelectColumns(Developper,{"data"})n in GarderData,n n getJson = (url) =>n letn waitForResult = WaitFor(n (iteration) =>n letn Source = Web.Contents(url, [Headers=[Authorization="Bearer " & ApiToken], ManualStatusHandling = {500}, IsRetry = iteration > 0]),n contentType = Value.Metadata(Source)[Content.Type],n actualResult = if contentType = "application/json" then Json.Document(Source) else nulln in actualResult,n (iteration)=> #duration(0, 0, 0, Number.Power(2, iteration)),n 5n )n inn if waitForResult = nulln then error "Wait for gave up after too many retry"n else waitForResultn inn outputninn Source
A noter que le Token est dans un paramètre que j’ai appelé “ApiToken”.
Ensuite, j’ai une fonction qui permet de générer par page :
GenerateByPagenletn Source = (getNextPage as function) as table =>n letn listOfPages = List.Generate(n () => getNextPage(null), // get the first page of datan (lastPage) => lastPage <> null, // stop when the function returns nulln (lastPage) => getNextPage(lastPage) // pass the previous page to the next function calln ),n // concatenate the pages togethern tableOfPages = Table.FromList(listOfPages, Splitter.SplitByNothing(), {"Column1"}),n firstRow = tableOfPages{0}?n inn // if we didn't get back any pages of data, return an empty tablen // otherwise set the table type based on the columns of the first pagen if (firstRow = null) thenn Table.FromRows({})nt // check for empty first tablen else if (Table.IsEmpty(firstRow[Column1])) thenn firstRow[Column1]n elsen Value.ReplaceType(n Table.ExpandTableColumn(tableOfPages, "Column1", Table.ColumnNames(firstRow[Column1])),n Value.Type(firstRow[Column1])n )ninn Source
Enfin, parce qu’il y a une limite de nombre de transactions par minute, j’avais dû créer une fonction d’attente :
WaitFornletn Source = (producer as function, interval as function, optional count as number) as any =>n letn list = List.Generate(n () => {0, null},n (state) => state{0} <> null and (count = null or state{0} < count),n (state) => if state{1} <> null then {null, state{1}} else {1 + state{0}, Function.InvokeAfter(() => producer(state{0}), interval(state{0}))},n (state) => state{1})n inn List.Last(list)ninn Source
J’espère que cela pourra t’aider. Peut-être une idée d’article à faire dès que je pourrais car c’est une vraie problématique.
ATTENTION : j’ai eu des problèmes avec ce genre de code car la source devient dynamique et elle ne peut pas être utilisée dans Power BI Services. En effet l’actualisation automatique des sources dynamiques ne fonctionne pas.
CommentID=rPOfMdeNFioAZOK, PostID=IT9iFywp9PBDbYs