Bij een ‘lokale’ installatie van Exact is het heel makkelijk om gegevens uit de database op te halen om verder te analyseren. Mijn collega Gertjan heeft hier al eens eerder over geblogd (zie https://growteq.nl/2016/06/28/correcte-auditfiles-genereren-uit-exact-globe/ ). Als je gebruik maakt van Exact Online is dit minder recht toe recht aan. Exact Online werkt met een RESTfull API webservice (REST API) waarmee via het internet gegevens kunnen worden uitgelezen. De techniek rondom REST API’s bestaat al veel langer en hier is ook veel informatie over beschikbaar. Exact geeft ook zelf veel informatie op haar website beschikbaar over de mogelijke koppelingen (https://developers.exactonline.com/).
In onze projecten hebben wij al de REST API van Exact Online gebruikt. Daarbij maakten wij gebruik van SQL Server Integration Services in combinatie met C# scripts. Deze oplossing is vaak onderdeel van een grotere datawarehouse implementatie. Voor de gebruiker die ook ‘Self Service‘ gegevens uit Exact Online wil gebruiken voor analyses, kan de REST API ook rechtstreeks in Power BI worden ingelezen. In deze blog laat ik zien welke stappen hiervoor moeten worden doorlopen.
Benodigdheden
- Power BI desktop (alleen voor Windows beschikbaar).
- Postman. Dit is een gratis app waarmee REST API’s eenvoudig kunnen worden getest.
Proces van authenticatie en autorisatie
Eén van de grootste uitdagingen bij het aanroepen van de REST API van Exact Online is het doorlopen van het proces van authenticatie en autorisatie. Hierbij maakt Exact Online gebruik van de techniek OAUTH 2.0. Helaas ondersteunt Power BI deze techniek (nog) niet vanuit de standaard functionaliteit.
OAUTH 2.0 werkt met tokens die worden uitgegeven nadat de klant met zijn inloggegevens is ingelogd in Exact Online. Deze tokens worden gebruikt voor de uitwisseling van gegevens, waardoor het niet nodig is om de inloggegevens elke keer mee te sturen bij het aanroepen van de webservice. De toestemming die aan de app wordt gegeven is een jaar geldig, waarna opnieuw toestemming moet worden verleend.
Stappenplan
De volgende stappen zijn nodig om de gegevens vanuit de REST API in te kunnen lezen:
- Registratie van een app bij Exact Online
- Aanvragen access token via Postman
- Aanroepen van de API in Power BI
Registratie van een app bij Exact Online
Om de RESTfull API van ExactOnline te kunnen gebruiken moet je je eerst registreren als Developer in de App center van Exact Online. Deze registratie verloopt via https://www.exact.com/nl/exact-online/partners/app-center-partner.
Naast de mogelijkheid om de REST API’s te gebruiken, krijg je ook toegang tot een test administratie.
Nadat je een account hebt aangemaakt, kun je inloggen in de App Center via de link https://apps.exactonline.com/
Nadat je bent ingelogd, klik je bovenin de menubal op ‘Mijn apps beheren’
Klik onder de tab Test-apps op ‘Een nieuwe test-app registereren:
Voeg een App naam toe en vul als Redirect URL https://www.getpostman.com/oauth2/callback in.
Klik op Bewaren.
Je komt nu gelijk in het overzicht met de App details.
Onder het kopje Autorisatiegegevens vind je de Client ID en de ClientSecret.
Deze gegevens hebben we straks nodig, dus sla deze ergens op of houdt de website open.
Aanvragen access token via Postman
Zoals aangegeven ondersteunt Power BI standaard geen OAUTH 2.0 authenticatie flow. Daarom maken wij hier gebruik van Postman om deze authenticatie te regelen. De verleende toestemming is een jaar geldig, dus dan kunnen we in ieder geval even vooruit.
Open Postman en klik in het rechterscherm op Autorization:
Selecteer als Type OAuth 2.0.
Klik nu op Get New Access Token
Vul het pop-up scherm dat volgt in zoals in de afbeelding is aangegeven. Gebruikt als Client_id en Client_secret de gegevens van de app die in de eerste stap van deze blog is aangemaakt.
Als je kiest voor Request Token kom je in het volgende scherm van Exact Online.
Vul jouw inloggegevens voor Exact Online in. In het daarop volgende scherm geef je als gebruiker toestemming aan de App om verbinding te mogen maken met Exact Online.
Klik op ‘Toestaan’ om terug te keren naar Postman. Vervolgens selecteer je de zojuist aangemaakte Token ‘ExactOnline’. Aan de rechterkant van het scherm zie je nu de gegevens van de token verschijnen.
De access_token is 600 seconden geldig. Daarna kan met behulp van een refresh_token een nieuw access_token worden opgevraagd.
Als je iets naar beneden scrolt zie je ook de gegevens van het refresh_token.
Deze token gaan we gebruiken in Power BI.
Aanroepen van de API in Power BI
Open Power BI desktop.
Kies in het lint op het tabblad Home voor Edit Queries
Kies in de Query Editor in het lint op tabblad Home nu voor Manage Parameters.
Maak via de knop New de volgende parameters aan:
Client_id & Client_secret
Gebruik de gegevens voor het client-id en client_secret de gegevens die in stap 1 zijn aangemaakt.
URL
Vul hier de waarde https://start.exactonline.nl in.
Refresh_token
Als waarde voor de refresh_token moet de waarde van de refresh_token worden ingevuld die we in Stap 2 in Postman hebben opgevraagd.
URI
Exact Online kent vele verschillende resources die kunnen worden opgevraagd. Via de volgende link is de uitgebreide lijst terug te vinden: https://start.exactonline.nl/docs/HlpRestAPIResources.aspx?SourceAction=10
In deze blog gaan we een lijst met Grootboekrekeningen en Omschrijving ophalen. Vul als waarde bij de URI ‘financial/GLAccounts’ in.
DivisionCode
Power BI moet weten voor welke administratie de gegevens opgehaald moeten worden. Vul hier de DivisionCode vanuit Exact in.
Dit is overigens niet hetzelfde als het administratienummer in Exact Online.
Mocht je de DivisionCode niet weten ga dan naar Postman.
Vul achter GET de volgende URL in: https://start.exactonline.nl/api/v1/current/Me?$select=CurrentDivision
Vraag een nieuwe Access Token aan
Eventueel kun je de Access Token uit Stap 2 gebruiken, maar als deze verlopen is, kun je een nieuwe aanvragen.
Selecteer de Access Token en klik aan de rechterkant op Use Token.
Klik bovenin op de blauwe knop Send.
Onderin Postman krijg je nu het resultaat.
Tussen de tags CurrentDivision vind je de DivisionCode die je kunt gebruiken.
Gegevens ophalen
Klik op OK en kies in het lint op het tabblad Home nu voor New Source en dan Blank Query.
Vul in het Advanced Editor scherm de volgende code in:
[code language=”csharp”]
let
actualUrl = URL & “/api/oauth2/token”,
cntnt = Text.ToBinary(Uri.BuildQueryString(
[refresh_token= Refresh_token
,grant_type=”refresh_token”
,client_id= Client_id
,client_secret=Client_secret
])),
options = [Headers =[#”Content-type”=”application/x-www-form-urlencoded”],Content=cntnt],
result = Web.Contents(actualUrl, options),
#”JSON” = Json.Document(result),
access_token= #”JSON”[access_token],
AccessTokenHeader = “Bearer ” & access_token,
GetJsonQuery = (Web.Contents( URL & “/api/v1/”& Number.ToText(DivisionCode) & “/” & URI,
[Headers=[Authorization=AccessTokenHeader]])),
#”Imported XML” = Xml.Tables(GetJsonQuery,null,65001),
#”Changed Type” = Table.TransformColumnTypes(#”Imported XML”,{{“id”, type text}, {“updated”, type datetime}}),
#”Expanded link” = Table.ExpandTableColumn(#”Changed Type”, “link”, {“Attribute:rel”, “Attribute:title”, “Attribute:href”},
{“link.Attribute:rel”, “link.Attribute:title”, “link.Attribute:href”}),
#”Expanded entry” = Table.ExpandTableColumn(#”Expanded link”, “entry”,
{“id”, “title”, “updated”, “author”, “link”, “category”, “content”}, {“entry.id”, “entry.title”, “entry.updated”,
“entry.author”, “entry.link”, “entry.category”, “entry.content”}),
#”Expanded entry.content” = Table.ExpandTableColumn(#”Expanded entry”, “entry.content”,
{“http://schemas.microsoft.com/ado/2007/08/dataservices/metadata”, “Attribute:type”},
{“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata”, “entry.content.Attribute:type”}),
#”Removed Other Columns” = Table.SelectColumns(#”Expanded entry.content”,{“link.Attribute:title”,
“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata”}),
#”Filtered Rows” = Table.SelectRows(#”Removed Other Columns”, each ([#”link.Attribute:title”] = “GLAccounts”)),
#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata” =
Table.ExpandTableColumn(#”Filtered Rows”, “entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata”,
{“properties”}, {“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties”}),
#”Removed Other Columns1″ = Table.SelectColumns(#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata”,
{“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties”}),
#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties” =
Table.ExpandTableColumn(#”Removed Other Columns1″,
“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties”, {“http://schemas.microsoft.com/ado/2007/08/dataservices”},
{“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.http://schemas.microsoft.com/ado/2007/08/dataservices”}),
#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.http://schemas.microsoft.com/ado/2007/08/dataservices”
= Table.ExpandTableColumn(#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties”,
“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.http://schemas.microsoft.com/ado/2007/08/dataservices”,
{“Code”, “Description”}, {“Code”, “Description”}),
#”Sorted Rows” = Table.Sort(#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.
http://schemas.microsoft.com/ado/2007/08/dataservices”,{{“Code”, Order.Ascending}})
in
#”Sorted Rows”
[/dm_code_snippet]
In hoofdlijnen doet deze code het volgende:
- Ten eerste vraagt de code met behulp van de refresh_token een nieuw access_token aan.
- Vervolgens wordt dit access_token gebruikt in de aanroep van de API URL financials/GetAccounts.
- Tenslotte zet het laatste gedeelte van de code de response van de API om in een tabel en verwijdert het de gegevens die we hier niet nodig hebben.
Als resultaat verschijnt er nu een tabel met de grootboekrekeningen van de geselecteerde administratie.
Conclusie
Het gebruiken van de REST API van Exact Online in Power BI is niet geheel recht toe recht aan. Echter, met name het gedeelte rondom de authenticatie vraagt een aantal extra handelingen. Niettemin, als één en ander eenmaal is ingericht, kun je je met behulp van de refresh_token jezelf in Power BI authentiseren.
Exact Online is een grote bron van gegevens waar zeker veel informatie uitgehaald kan worden met behulp van Power BI. Meer dan genoeg om uitgebreid te analyseren in ieder geval.
Succes!
Lees deel 2 en deel 3 van deze serie om meer te lezen over Self Service data ophalen vanuit Exact Online in Power BI
Meer weten over onze oplossingen?
Onze consultants hebben veel ervaring binnen een grote verscheidenheid aan branches.
Eens verder brainstormen over de mogelijkheden voor jouw organisatie?
Maak kennis met onze specialist Arnoud van der Heiden.
Wellicht herkent u een van deze vraagstukken.
Inmiddels hebben wij ruime ervaring opgedaan met Business Intelligence. Wij staan ook u graag te woord bij vragen of opmerkingen.
Business Intelligence (BI) is het technologie gedreven proces van gegevensanalyse dat bedrijven in staat stelt om waardevolle inzichten te halen uit hun gegevens. BI-oplossingen kunnen helpen bij het verzamelen, analyseren en presenteren van bedrijfsgegevens om betere beslissingen te nemen en concurrentievoordeel te behalen.
BI richt zich op het verzamelen, analyseren en presenteren van historische en huidige gegevens om bedrijfsprestaties te meten en te rapporteren. BA daarentegen richt zich meer op het voorspellen van toekomstige trends en mogelijkheden door geavanceerde analysemethoden en -modellen toe te passen op gegevens.
Het gebruik van BI-oplossingen kan bedrijven helpen om hun prestaties te verbeteren, betere beslissingen te nemen en concurrerend te blijven. Het kan hen helpen om inzicht te krijgen in klantgedrag, trends te identificeren, kosten te verlagen, de efficiëntie te verbeteren en nieuwe zakelijke kansen te ontdekken.
Growteq biedt verschillende BI-oplossingen aan, waaronder Power BI van Microsoft, QlikView en Qlik Sense, Tableau en SAP BusinessObjects. Elk van deze oplossingen heeft zijn eigen sterke punten en functies, en kan worden aangepast aan de behoeften van een bedrijf.
Ja, Growteq kan bedrijven helpen bij het implementeren van BI-oplossingen door het bieden van strategisch advies, consultancy en implementatiediensten. Ze werken samen met klanten om oplossingen op maat te maken die aan hun specifieke behoeften voldoen en hen helpen om waarde te halen uit hun gegevens.
De kosten van BI-oplossingen kunnen variëren afhankelijk van de grootte van het bedrijf, de omvang van de implementatie en de gekozen oplossing. Growteq werkt samen met klanten om oplossingen te vinden die passen bij hun budget en behoeften. De voordelen van het gebruik van BI-oplossingen kunnen echter vaak opwegen tegen de kosten, omdat ze bedrijven kunnen helpen om hun prestaties te verbeteren en hun concurrentievoordeel te behalen.
De implementatie van een BI-oplossing omvat meestal de volgende stappen:
- Ten eerste, het definiëren van de doelstellingen en vereisten van het BI-project.
- Vervolgens, het verzamelen en integreren van relevante gegevens uit verschillende bronnen.
- Daarna, het ontwikkelen van een datawarehouse om de gegevens op te slaan in een logisch model.
- Implementatie van dashboards, KPI’s en visualisatie voor gegevenspresentatie
- Training van medewerkers
- En ten slotte, de continue monitoring en optimalisatie van de BI-oplossing.
BI maakt verschillende soorten analyses mogelijk, waaronder:
- Descriptive analyse: Hierbij worden historische gegevens gebruikt om te begrijpen wat er in het verleden is gebeurd.
- Diagnostische analyse: Hierbij wordt onderzocht waarom bepaalde gebeurtenissen of trends zich hebben voorgedaan
- Voorspellende analyses: Hierbij worden gegevens en modellen gebruikt om toekomstige gebeurtenissen en trends te kunnen voorspellen
- Prescriptive analyse: Hierbij worden aanbevelingen gedaan over mogelijke acties op basis van analyse en voorspelling
Enkele populaire BI-tools zijn o.a.:
- Microsoft Power BI
- QlikView
- Qlik Sense
- Tableau
- MicroStrategy
- IBM Cognos
Business Intelligence (BI) kan gegevens uit verschillende bronnen gebruiken, zoals:
- Interne databases en systemen (bijvoorbeeld CRM-systemen, ERP-systemen)
- Externe gegevensbronnen (bijvoorbeeld marktonderzoekgegevens, sociale media)
- Gestructureerde gegevens (bijvoorbeeld databases en spreadsheets)
- Ongestructureerde gegevens (bijvoorbeeld tekstuele gegevens, e-mails, logboeken etc.)
- Big data-bronnen (bijvoorbeeld sensorgegevens, weblogs)
Growteq heeft ervaring met al deze bronnen.
Selfservice BI, het vermogen van niet-technische gebruikers om zelfstandig gegevens te verkennen, te analyseren en rapporten en dashboards te maken met behulp van gebruiksvriendelijke BI-tools, biedt diverse voordelen. Enkele van deze voordelen zijn:
- Verminderde afhankelijkheid van IT-afdelingen voor rapportage en analyses.
- Bovendien leidt het tot snellere besluitvorming doordat gebruikers direct toegang hebben tot benodigde gegevens.
- Daarnaast biedt selfservice BI verhoogde flexibiliteit en aanpasbaarheid bij het verkennen van gegevens.
- Bovendien stimuleert het een gegeven gestuurde cultuur binnen de organisatie.
73 reacties. Leave new
Hallo Gideon,
Dank je wel voor het delen van deze geweldige blog.
Ik heb hem nagespeeld, werkt prima. Ik kwam twee kleine dingen tegen die na knippen en plakken van het script niet direct werkten.
de ‘ ‘ zitten in de weg en prefix ‘Bearer ‘ heeft een spatie nodig. Voor de rest prima. Scheelt mij een hele hoop uitzoekwerk.
Hebben je misschien ook al onderzocht welke mogelijkheden er zijn om na het publishen van de PBIX het mogelijk is om de scheduled refresh in te stellen. Ik krijg de boodschap: “U kunt geen vernieuwing plannen voor deze gegevensset, omdat een of meer bronnen geen ondersteuning bieden voor vernieuwing.”
Zou toch te gek zijn als dit ook nog zou werken,.
Mijn M-script zoals het bij mij werkte:
let
actualUrl=URL&”/api/oauth2/token”,cntnt=Text.ToBinary(Uri.BuildQueryString([refresh_token=Refresh_token,grant_type=”refresh_token”,client_id=Client_id,client_secret=Client_secret])),
options=[Headers=[#”Content-type”=”application/x-www-form-urlencoded”],Content=cntnt],
result=Web.Contents(actualUrl,options),
#”JSON”=Json.Document(result),
access_token=#”JSON”[access_token],
AccessTokenHeader=”Bearer ” & access_token,
GetJsonQuery = (Web.Contents( URL & “/api/v1/”& Number.ToText(DivisionCode) & “/” & URI,[Headers=[Authorization=AccessTokenHeader]])),
ImportedXML = Xml.Tables(GetJsonQuery,null,65001),
#”Expandedlink”=Table.ExpandTableColumn(ImportedXML,”link”,{“Attribute:rel”,”Attribute:title”,”Attribute:href”},
{“link.Attribute:rel”,”link.Attribute:title”,”link.Attribute:href”}),
#”Expandedentry”=Table.ExpandTableColumn(#”Expandedlink”,”entry”,
{“id”,”title”,”updated”,”author”,”link”,”category”,”content”},{“entry.id”,”entry.title”,”entry.updated”,
“entry.author”,”entry.link”,”entry.category”,”entry.content”}),
#”Expandedentry.content”=Table.ExpandTableColumn(#”Expandedentry”,”entry.content”,
{“http://schemas.microsoft.com/ado/2007/08/dataservices/metadata”,”Attribute:type”},
{“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“,”entry.content.Attribute:type”}),
#”RemovedOtherColumns”=Table.SelectColumns(#”Expandedentry.content”,{“link.Attribute:title”,
“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“}),
#”FilteredRows”=Table.SelectRows(#”RemovedOtherColumns”,each([#”link.Attribute:title”]=”GLAccounts”)),
#”Expandedentry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“=
Table.ExpandTableColumn(#”FilteredRows”,”entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“,
{“properties”},{“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties“}),
#”RemovedOtherColumns1″=Table.SelectColumns(#”Expandedentry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“,
{“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties“}),
#”Expandedentry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties“=
Table.ExpandTableColumn(#”RemovedOtherColumns1”,
“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties“,{“http://schemas.microsoft.com/ado/2007/08/dataservices”},
{“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.http://schemas.microsoft.com/ado/2007/08/dataservices“}),
#”Expandedentry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.http://schemas.microsoft.com/ado/2007/08/dataservices”
=Table.ExpandTableColumn(#”Expandedentry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties“,
“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.http://schemas.microsoft.com/ado/2007/08/dataservices“,
{“Code”,”Description”},{“Code”,”Description”})
in
#”Expandedentry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.http://schemas.microsoft.com/ado/2007/08/dataservices“
Haha .. de ‘ ‘ moet zijn de ==> “& n b s p ; ” zonder de spaties 🙂
Beste Wouter,
Bedankt voor je reactie. Het blijkt dat de website de codes inderdaad een beetje vervormd. Mooi dat het toch gelukt is.
Het reschedulen lukt waarschijnlijk niet door de web.contents functie. Power BI valideert de url die je meegeeft in deze functie en omdat de url zonder authenticatie nog niet werkt, gaat het mis.
Dit kan je oplossen door de volgende aanpassingen te maken:
ActualUrl vervangen door:
actualUrl = URL
En de options aan te passen naar:
options = [RelativePath = “/api/oauth2/token”, Headers =[#”Content-type”=”application/x-www-form-urlencoded”],Content=cntnt],
Dit zorgt ervoor dat de URL die gevalideerd wordt, goed gaat. Middels het toevoegen van het RelativePath in de options, gaat de functie alsnog naar de juiste url toe.
Ik ben benieuwd of het hiermee lukt.
Beste Gideon
Bedankt voor deze post, alles werkt tot en met de query in PowerBI bij mij. Ik krijg de error ‘Token Identifier Expected’ bij de lijn
Weet u toevallig de oorzaak hiervan of weet u waar ik meer kan lezen over het opstellen van dergelijke queries? Alvast bedankt
lijn = “& n b s p ; “
Beste Peter,
In de code staat de code “& n b s p”. Deze kun je het beste helemaal verwijderen uit de code. Ik heb de code in de blog aangepast. Deze is het met kopieren er waarschijnlijk ten onrechte bij gekomen.
De ‘taal’ waarin de querie geschreven is, is de Power Query Formula Language “M”. De officiele documentatie vind je via de volgende link: https://msdn.microsoft.com/library/mt211003.aspx
Ik hoop dat je er zo uitkomt! Succes.
Bedankt, de ‘Token Identifier Error’ is hiermee opgelost, echter zit ik nu vast op het onderstaande. Is er een extra installatie vereist voor de ADO.NET te gebruiken?
Expression.Error: The name ‘Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.
http://schemas.microsoft.com/ado/2007/08/dataservices‘ wasn’t recognized. Make sure it’s spelled correctly.
Als het goed is, is dit niet nodig, maar misschien toch wel afhankelijk van de compjuter waar je op werkt.
Wat je zou kunnen doen, is alle code na “[Headers=[Authorization=AccessTokenHeader]])) ” tot en met het woordje IN verwijderen en dan in jouw versie de stappen zelf volgen om de output te verwerken.
Let op dat je ook de komma verwijderd na “[Headers=[Authorization=AccessTokenHeader]]))”
Het is me uiteindelijk gelukt op een wat andere manier. Ik heb het Postman gedeelte & parameters achterwege gelaten en alles via Power BI gedaan. Bedankt!
Beste Gideon, dank voor je uitleg – hiermee is het zelfs mij gelukt :-). Ik heb meer verstand van Finance dan van IT.
Als ik het echter probeer toe te passen op “financialtransaction/TransactionLines”, krijg ik bij “GetJsonQuery” een foutmelding: “DataSource.Error: Web.Contents kan de inhoud niet ophalen van ‘https://start.exactonline.nl/api/v1/791095/financialtransaction/TransactionLines’ (400): Bad Request
Details:
DataSourceKind=Web
DataSourcePath=https://start.exactonline.nl/api/v1/791095/financialtransaction/TransactionLines
Url=https://start.exactonline.nl/api/v1/791095/financialtransaction/TransactionLines”
Kun jij me verder helpen?
Beste Ronald,
Dit type foutmelding geeft aan dat de API de aanvraag niet goed kan verwerken, bijvoorbeeld omdat er tekens in staan die niet herkend worden.
Er worden een paar variabelen ingevuld. Zou het kunnen dat daar ‘special characters’ in worden gebruikt? Zoals het & tekens of een ‘ ?
Hoi Gideon,
Dank voor je reactie. Om alles uit te sluiten heb ik nu het volgende gedaan:
In PBI heb ik eerst in jouw werkende query de variabele “URI” vervangen door de harde waarde “financial/GLAccounts”. Dit werkte gewoon. Daarna heb ik in “Advanced Editor” de code van de query t/m de stap “GetJSonQuery” gekopieerd en in een nieuwe query (“GLAccounts”) geplakt. Het resultaat van deze query was: het xml-icoontje met als label “start.exactonline.nl” en het aantal bites; ook dit werkte dus. So far so good.
Daarna heb ik in “Advanced Editor” in de query “GLAccounts” de harde waarde “financial/GLAccounts” vervangen door “financialtransaction/TransactionLines” en toen kwam een andere foutmelding: “kan niet verifiëren met de opgegeven referenties. Probeer het opnieuw.” Er is dus geen ander verschil dan bovenstaand en toch werkt het in ene niet meer. (Ik heb zelfs een compare in MSWord gedaan en dat leverde ook geen andere verschillen op).
Het enige verschil is dus de benaderde tabel. Als ik kijk op de link uit je blog (https://start.exactonline.nl/docs/HlpRestAPIResources.aspx?SourceAction=10) dan zie ik dat
– GLAccounts als supported methods “Get/Post/Put/Delete” heeft en geen webhook en
– FinancialTransactions alleen “Get” en wel een webhook heeft
Dit heeft er volgens mij (een leek) niets mee te maken.
Ik weet niet hoe ik hiermee nu verder kom…
Bijvoorbaat dank voor je feedback.
…. overigens, na een refresh kwam de oude foutmelding weer naar voren:
“DataSource.Error: Web.Contents kan de inhoud niet ophalen van ‘https://start.exactonline.nl/api/v1/791095/financialtransaction/TransactionLines’ (400): Bad Request
Details:
DataSourceKind=Web
DataSourcePath=https://start.exactonline.nl/api/v1/791095/financialtransaction/TransactionLines
Url=https://start.exactonline.nl/api/v1/791095/financialtransaction/TransactionLines”
Hi Ronald,
Dit zou nog met de data source settings te maken kunnen hebben. IN Edit Query editor kan je naar de data source settings kijken.
Voor deze bron zal het Privacy level denk ik op Public moeten staan. Kun je dat checken?
De query maakt inderdaad gebruik van de Get dus dat zou in dit geval niet uit moeten maken,
Hoi Gideon,
Als ik klik op “Start/Queries bewerken/Instellingen voor gegevensbron” krijg ik een pop-up “Onverwachte fout – De Objectverwijzing is niet op een exemplaar van het object ingesteld”. Er is hier dus duidelijk iets mis….
Overigens heeft mijn GLAccounts versie 60 records. Ik ben er in geslaagd om voor sommige andere tabellen data naar voren te krijgen, maar in alle gevallen heb ik 60 records, niet meer, niet minder. Ik zei het net al: er is hier dus duidelijk iets mis…. 🙂
Hi Ronald,
Dit is inderdaad niet een hele leuke melding. En nogal vaag ook.
Het zou kunnen dat dit te maken heeft met de versie van Power BI die je gebruikt. Welke versie gebruik je?
Wellicht helpt het om Power BI te updaten naar de laatste versie
Hoi Gideon,
Bedankt voor jouw blog. Precies wat ik zocht. Ga dit graag eens uitproberen.
Ik wil eerst ff testen met een demo omgeving van Exact. Stap 1 en 2 zijn gelukt. BIj het aanvragen van de request token wordt ik naar het login scherm van Exact. Online verwezen. Ik vul accountnaam en wachtwoord in maar dan krijg ik de volgende foutmelding: Oeps! Er is een fout opgetreden. Neem contact op….
Met dezelfde gegevens kan ik wel inloggen bij Exact Online. Jij enig idee wat ik fout doe?
Rob.
Beste Rob,
Vraag je de request token aan vanuit Postman?
Je zou de redirect uri kunnen controleren die je bij Exact Online hebt opgegeven. Deze moet wel goed staan, anders weet exact online niet waar je naar teruggestuurd moet worden.
Het is mij inmiddels gelukt om de request token aan te vragen na inloggen bij Excact met het inlogscherm dat jij ook beschrijft (ik kreeg eerst een algemeen inlogscherm).
Ook mijn divisienummer is bekend, ik heb de parameters en de juiste refresh token ingevoerd.
Bij het uitvoeren van het PowerBI Script moest ik bij de stap result mijn credentials opgeven. Ik heb daar gekozen voor Anonymous en kwam vervolgens door de stap heen. Nu krijg ik de vraag weer bij de stap GetJsonQuery. En kiezen voor Anonymous helpt niet. Ook niet als ik het laagste level kies.
Enig idee wat er fout gaat? De Query zou toch zonder interactie moeten lopen?
Alvast bedankt voor je hulp.
Rob.
Ik heb ‘m!
Weet niet helemaal zeker wat het nu precies was, maar met dezelfde Anonymous credentials kom ik nu door alle stappen heen…..
De laatste stap “Sorted Rows” leverde mij nog een foutmelding op:
Expression.Error: The name ‘Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties. …. enz enz. Dezelfde melding van Peter eerder dus…
Deze melding heb ik opgelost. In het script begint regel 90 net HTTP:// … Die regel moet echter direct aansluiten op de regel ervoor (harde return weggehaald).
En dan gaat ‘ie goed….
Top!
Hoi Gideon,
Net als Ronald Kiebert wil ik een tweede tabel kunnen ontsluiten. Ik heb een tweede URI parameter aangemaakt en die verwezen naar: financial/GLSchemes.
Vervolgensm, net als Ronald een nieuwe query gemaakt, kopie t./m stap
#”Imported XML”….
Om daarna de inhoud van het GL sschema op te halen e.d.
Ook nu krijg ik helaas weer meldingen.
Helaas ook bij de eerste query….
“Expression.Error: The ‘Authorization’ header is only supported when connecting anonymously. These headers can be used with all authentication types: Accept, Accept-Charset, Accept-Encoding, Accept-Language, Cache-Control, If-Modified-Since, Prefer, Referer”
Wat ik nu ook probeer met de Data Source Settings, ik krijg het niet meer voor elkaar.
Ik vermoed dat er iets niet goed gaat met de access_token. Die is niet als parameter aangemaakt, maar wordt wel gebruikt in he script (van af regel 25:
access_token= #”JSON”[access_token],
AccessTokenHeader = “Bearer ” & access_token,
GetJsonQuery = (Web.Contents( URL & “/api/v1/”& Number.ToText(DivisionCode) & “/” & URI,
[Headers=[Authorization=AccessTokenHeader]])),
Waar haalt hij de access_code vandaan?
NB: ik ben geen “echte” developper en dit is mijn eerste keer dat ik m.bv. een API (op Excact) data probeer op te halen. Ik doe mijn best, maar heb je hulp hier toch echt even nodig…
Rob.
Hi
De access_token wordt opgehaald in de eerste 18 regels code. Met behulp van het refreshtoken wordt een nieuw access_token opgevraagd welke 600 seconde geldig is. Daarom wordt elke keer opnieuw het refreshtoken gebruikt in deze code.
De melding die je krijgt: The ‘Authorization’ header is only supported when connecting anonymously. heeft wel te maken met de Data Source settings. Deze moet op Anonymous staan om het script anders niet werkt. Misschien helpt het om een nieuwe Power BI dashboard aan te maken en het e.e.a. opnieuw aan te maken. Soms onthoudt Power BI dingen die niet de bedoeling zijn…
Hoi Gideon,
Bedankt voor je uitleg. Ik blijf tegen de onderstaande foutmelding aan lopen :
DataSource.Error: Web.Contents failed to get contents from ‘https://start.exactonline.nl/api/oauth2/token’ (400): Bad Request
Details:
DataSourceKind=Web
DataSourcePath=https://start.exactonline.nl/api/oauth2/token
Url=https://start.exactonline.nl/api/oauth2/token
Ik heb je tips al uitgevoerd, opnieuw begonnen, een nieuwe token opgevraagd, maar de fout blijft komen.
Heb jij nog wat tips?
Alvast bedankt !!
Groeten,
Mark
Hi Mark,
Zou je een stukje van jouw code kunnen posten die je nu hebt ingevoerd in de Advanced Editor? Misschien dat ik daar iets aan kan zien.
Je hebt via Postman wel een token kunnen opvragen?
Hoi Gideon,
Ik kan wel een token opvragen.
Mijn code is:
= let
actualUrl = URL & “/api/oauth2/token”,
cntnt = Text.ToBinary(Uri.BuildQueryString(
[refresh_token= Refresh_token
,grant_type=”refresh_token”
,client_id= Client_id
,client_secret=Client_secret
])),
options = [Headers =[#”Content-type”=”application/x-www-form-urlencoded”],Content=cntnt],
result = Web.Contents(actualUrl, options),
#”JSON” = Json.Document(result),
access_token= #”JSON”[access_token],
AccessTokenHeader = “Bearer ” & access_token,
GetJsonQuery = (Web.Contents( URL & “/api/v1/”& Number.ToText(DivisionCode) & “/” & URI,
[Headers=[Authorization=AccessTokenHeader]])),
#”Imported XML” = Xml.Tables(GetJsonQuery,null,65001),
#”Changed Type” = Table.TransformColumnTypes(#”Imported XML”,{{“id”, type text}, {“updated”, type datetime}}),
#”Expanded link” = Table.ExpandTableColumn(#”Changed Type”, “link”, {“Attribute:rel”, “Attribute:title”, “Attribute:href”},
{“link.Attribute:rel”, “link.Attribute:title”, “link.Attribute:href”}),
#”Expanded entry” = Table.ExpandTableColumn(#”Expanded link”, “entry”,
{“id”, “title”, “updated”, “author”, “link”, “category”, “content”}, {“entry.id”, “entry.title”, “entry.updated”,
“entry.author”, “entry.link”, “entry.category”, “entry.content”}),
#”Expanded entry.content” = Table.ExpandTableColumn(#”Expanded entry”, “entry.content”,
{“http://schemas.microsoft.com/ado/2007/08/dataservices/metadata”, “Attribute:type”},
{“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“, “entry.content.Attribute:type”}),
#”Removed Other Columns” = Table.SelectColumns(#”Expanded entry.content”,{“link.Attribute:title”,
“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“}),
#”Filtered Rows” = Table.SelectRows(#”Removed Other Columns”, each ([#”link.Attribute:title”] = “GLAccounts”)),
#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata” =
Table.ExpandTableColumn(#”Filtered Rows”, “entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“,
{“properties”}, {“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties“}),
#”Removed Other Columns1” = Table.SelectColumns(#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“,
{“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties“}),
#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties” =
Table.ExpandTableColumn(#”Removed Other Columns1″,
“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties“, {“http://schemas.microsoft.com/ado/2007/08/dataservices”},
{“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.http://schemas.microsoft.com/ado/2007/08/dataservices“}),
#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.http://schemas.microsoft.com/ado/2007/08/dataservices”
= Table.ExpandTableColumn(#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties“,
“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.http://schemas.microsoft.com/ado/2007/08/dataservices“,
{“Code”, “Description”}, {“Code”, “Description”}),
#”Sorted Rows” = Table.Sort(#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.http://schemas.microsoft.com/ado/2007/08/dataservices“,{{“Code”, Order.Ascending}})
in
#”Sorted Rows”
Kun je daar wat mee?
Alvaste bedankt!!
Groeten,
Mark
Hi Gideon,
Een token opvragen lukt (ik heb er nu ook meerdere).
Dit heb ik nu als code staan:
= let
actualUrl = URL & “/api/oauth2/token”,
cntnt = Text.ToBinary(Uri.BuildQueryString(
[refresh_token= Refresh_token
,grant_type=”refresh_token”
,client_id= Client_id
,client_secret=Client_secret
])),
options = [Headers =[#”Content-type”=”application/x-www-form-urlencoded”],Content=cntnt],
result = Web.Contents(actualUrl, options),
#”JSON” = Json.Document(result),
access_token= #”JSON”[access_token],
AccessTokenHeader = “Bearer ” & access_token,
GetJsonQuery = (Web.Contents( URL & “/api/v1/”& Number.ToText(DivisionCode) & “/” & URI,
[Headers=[Authorization=AccessTokenHeader]])),
#”Imported XML” = Xml.Tables(GetJsonQuery,null,65001),
#”Changed Type” = Table.TransformColumnTypes(#”Imported XML”,{{“id”, type text}, {“updated”, type datetime}}),
#”Expanded link” = Table.ExpandTableColumn(#”Changed Type”, “link”, {“Attribute:rel”, “Attribute:title”, “Attribute:href”},
{“link.Attribute:rel”, “link.Attribute:title”, “link.Attribute:href”}),
#”Expanded entry” = Table.ExpandTableColumn(#”Expanded link”, “entry”,
{“id”, “title”, “updated”, “author”, “link”, “category”, “content”}, {“entry.id”, “entry.title”, “entry.updated”,
“entry.author”, “entry.link”, “entry.category”, “entry.content”}),
#”Expanded entry.content” = Table.ExpandTableColumn(#”Expanded entry”, “entry.content”,
{“http://schemas.microsoft.com/ado/2007/08/dataservices/metadata”, “Attribute:type”},
{“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“, “entry.content.Attribute:type”}),
#”Removed Other Columns” = Table.SelectColumns(#”Expanded entry.content”,{“link.Attribute:title”,
“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“}),
#”Filtered Rows” = Table.SelectRows(#”Removed Other Columns”, each ([#”link.Attribute:title”] = “GLAccounts”)),
#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata” =
Table.ExpandTableColumn(#”Filtered Rows”, “entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“,
{“properties”}, {“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties“}),
#”Removed Other Columns1” = Table.SelectColumns(#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“,
{“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties“}),
#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties” =
Table.ExpandTableColumn(#”Removed Other Columns1″,
“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties“, {“http://schemas.microsoft.com/ado/2007/08/dataservices”},
{“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.http://schemas.microsoft.com/ado/2007/08/dataservices“}),
#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.http://schemas.microsoft.com/ado/2007/08/dataservices”
= Table.ExpandTableColumn(#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties“,
“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.http://schemas.microsoft.com/ado/2007/08/dataservices“,
{“Code”, “Description”}, {“Code”, “Description”}),
#”Sorted Rows” = Table.Sort(#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.http://schemas.microsoft.com/ado/2007/08/dataservices“,{{“Code”, Order.Ascending}})
in
#”Sorted Rows”
Ik hoop dat je er wat mee kunt.
Groeten,
Mark
Hi,
Als je in de Advanced Editor zit, krijg je dan een melding linksonderin.
In de engelse versie kan er staan ‘Token literal expected’ Show error.
Of staat er No syntax errors detected?
In de code die jij hebt geplakt staat voor het woordje LET namelijk een = teken. en die moet iig weg volgens mij
Hi Gideon,
Op het moment dat ik het ‘=’weg laat, dan worden in de query “” en #LF getoond, zie onder
let#(lf) #(lf)actualUrl = URL & “”/api/oauth2/token””,#(lf) #(lf)cntnt = Text.ToBinary(Uri.BuildQueryString(#(lf) #(lf)[refresh_token= Refresh_token#(lf) #(lf),grant_type=””refresh_token””#(lf) #(lf),client_id= Client_id#(lf) #(lf),client_secret=Client_secret#(lf) #(lf)])),#(lf) #(lf) #(lf)options = [Headers =[#””
Linksonderaan komt de melding ‘Ready’
Hi
Die #(lf) is een spcial character, maar zou niet in de advanced editor naar voren moeten komen. Welicht dat er met het kopieren van de code ook een stukje opmaakt mee gekopieerd is.
Heb je al geprobeerd om de code nog een keer te opnieuw in te voeren. Wellicht eerst plakken in kladblok en dan pas in power bi? Of ‘overtypen’.
Zitten er anders in de client_secret of client_id nog special characters? Aanhalingstekens of slashes of iets dergelijks?
Beste Gideon,
In twee andere berichten zag ik dat je ook ervaring hebt met het ophalen van data uit AFAS via de GetConnector.
Volgens mij moet het mogelijk zijn om op een vergelijkbare manier zoals hierboven met Power BI en de functie Web.Contents direct gegevens te importeren van een AFAS web services GetConnector maar ik krijg het (nog) niet voor elkaar…
Heb jij misschien een voorbeeld van de daarvoor benodigde M code?
Alvast bedankt!
Groeten,
Martijn
Beste Martijn,
AFAS rechtstreeks naar Power BI heb ik nog niet eerder gedaan, maar zou iid wel moeten lukken.
Ik zal er eens naar kijken. Misschien mooie aanleiding voor een nieuwe blog 🙂
Bedankt voor de snelle reactie. Goed om te horen dat het in ieder geval mogelijk moet zijn. Mocht je een voorbeeld kunnen produceren dan hoor ik het natuurlijk graag 🙂
Martijn
Zie http://blog.smartinsight.nu/afas-getconnectoren-gebruiken-in-power-bi/
Was nog makkelijker dan gedacht 🙂
Super! Ik was ook al weer wat verder maar met jouw uitleg erbij komt het zeker goed. Bedankt! 🙂
Hallo Gideon,
vooreerst bedankt om dit artikel te delen!
Heb een vraag tijdens de laatste stap gegevens ophalen.
Momenteel krijg ik eerst de melding:
‘please specify how to connect’: via edit credentials kom ik in het access web content scherm.
Hier kies ik voor anonymous en geef ik als “select which level to apply these settings to” het volgende in: “https://start.exactonline.be/”
Wanneer ik klik op connect krijg ik volgende melding:
“Information is required about data privacy”: Ik krijg het privacy levels scherm te zien waar ik moet aanduiden of de url https://start.exactonline.be/ Public, Organizational of Private is.
Heb alle combinaties geprobeerd maar krijg telkens de melding “we couldn’t authenticate with the credentials provided. Please try again”.
Enig idee? Client id, secret en refresh token meermaals gecontroleerd maar hier is alles correct meegegeven.
Alvast bedankt voor uw antwoord.
Vriendelijke groet,
Koen
Beste Koen,
De melding lijkt toch aan te geven dat er met de combinatie van inloggegevens iets niet goed gaat.
Heb je via Postman ook geprobeerd connectie te maken? Krijg je dan wel resultaten?
Zou het misschien nog kunnen dat in de refreshtoken ‘speciale characters’ voorkomen zoals haakjes of its dergelijks? Daar kan het namelijk nog misgaan.
Beste Gideon,
bedankt voor de postman tip. Via postman werkte alles perfect, heb dan veder gekeken naar het advanced script en zag dat er 2 spaties aanwezig waren bij het doorgeven van de AccessTokenHeader. door een spatie weg te doen is het gelukt!
Bedankt,
Vriendelijke groeten,
Koen
mooi dat het gelukt is!
Dag Gideon,
Dank voor het delen van deze kennis.
Mijn query loopt momenteel vast met de volgende melding:
Expression.Error: De veldnaam Authorization wordt alleen ondersteund bij een anonieme verbinding. Deze veldnamen kunnen met alle authenticatietypen worden gebruikt: Accept, Accept-Charset, Accept-Encoding, Accept-Language, Cache-Control, If-Modified-Since, Prefer, Referer
Deze bevinst zich in de GetJsonQuery. De instellingen voor de gegevensbron (https://start.exactonline.nl/api/oauth2/token) staat echter ingesteld op anoniem.
Dank alvast voor je hulp!
ik krijg deze error:
Expression.Error: The name ‘Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.
http://schemas.microsoft.com/ado/2007/08/dataservices‘ wasn’t recognized. Make sure it’s spelled correctly.
ik las de oplossing al, nu echter deze melding:
DataSource.Error: Web.Contents failed to get contents from ‘https://start.exactonline.nl/api/oauth2/token/api/oauth2/token’ (404): Not Found
Details:
DataSourceKind=Web
DataSourcePath=https://start.exactonline.nl/api/oauth2/token/api/oauth2/token
Url=https://start.exactonline.nl/api/oauth2/token/api/oauth2/token
zie dat api/oauth2 dubbel staat… maar zie niet waar het mis is in de code:
let
actualUrl = URL & “/api/oauth2/token”,
cntnt = Text.ToBinary(Uri.BuildQueryString(
[refresh_token= Refresh_token
,grant_type=”refresh_token”
,client_id= Client_id
,client_secret=Client_secret
])),
options = [RelativePath = “/api/oauth2/token”, Headers =[#”Content-type”=”application/x-www-form-urlencoded”],Content=cntnt],
result = Web.Contents(actualUrl, options),
#”JSON” = Json.Document(result),
access_token= #”JSON”[access_token],
AccessTokenHeader = “Bearer ” & access_token,
GetJsonQuery = (Web.Contents( URL & “/api/v1/”& Number.ToText(DivisionCode) & “/” & URI,
[Headers=[Authorization=AccessTokenHeader]])),
#”Imported XML” = Xml.Tables(GetJsonQuery,null,65001),
#”Changed Type” = Table.TransformColumnTypes(#”Imported XML”,{{“id”, type text}, {“updated”, type datetime}}),
#”Expanded link” = Table.ExpandTableColumn(#”Changed Type”, “link”, {“Attribute:rel”, “Attribute:title”, “Attribute:href”},
{“link.Attribute:rel”, “link.Attribute:title”, “link.Attribute:href”}),
#”Expanded entry” = Table.ExpandTableColumn(#”Expanded link”, “entry”,
{“id”, “title”, “updated”, “author”, “link”, “category”, “content”}, {“entry.id”, “entry.title”, “entry.updated”,
“entry.author”, “entry.link”, “entry.category”, “entry.content”}),
#”Expanded entry.content” = Table.ExpandTableColumn(#”Expanded entry”, “entry.content”,
{“http://schemas.microsoft.com/ado/2007/08/dataservices/metadata”, “Attribute:type”},
{“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“, “entry.content.Attribute:type”}),
#”Removed Other Columns” = Table.SelectColumns(#”Expanded entry.content”,{“link.Attribute:title”,
“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“}),
#”Filtered Rows” = Table.SelectRows(#”Removed Other Columns”, each ([#”link.Attribute:title”] = “GLAccounts”)),
#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata” =
Table.ExpandTableColumn(#”Filtered Rows”, “entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“,
{“properties”}, {“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties“}),
#”Removed Other Columns1” = Table.SelectColumns(#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata“,
{“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties“}),
#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties” =
Table.ExpandTableColumn(#”Removed Other Columns1″,
“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties“, {“http://schemas.microsoft.com/ado/2007/08/dataservices”},
{“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.http://schemas.microsoft.com/ado/2007/08/dataservices“}),
#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.http://schemas.microsoft.com/ado/2007/08/dataservices”
= Table.ExpandTableColumn(#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties“,
“entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.http://schemas.microsoft.com/ado/2007/08/dataservices“,
{“Code”, “Description”}, {“Code”, “Description”}),
#”Sorted Rows” = Table.Sort(#”Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.http://schemas.microsoft.com/ado/2007/08/dataservices“,{{“Code”, Order.Ascending}})
in
#”Sorted Rows”
Hallo Gideon,
Exact geeft aan dat er een limiet is van 60 records per API request >> https://developers.exactonline.com/#REST Restrictions.html
Ik vermoed dat dit de oorzaak is van het feit dat ik maar 60 rijen GL accounts te zien krijg in Power BI met jouw script (net als Ronald Kiebert hierboven). Is deze aanname juist volgens jou? En zo ja, heb je enig idee hoe / of ik deze limiet kan verhogen met een aanpassing van het script?
Beste Sander,
De cdocumentatie geeft aan dat op de meeste READ request geen limiet zit, maar het lijkt er wel op dat dit het probleem is als je maar 60 records ziet.
Dit is op te lossen door een nieuwe request te doen en gebruik te maken van de skiptoken.
Hiervoor moet het script wel uitgebreid worden.
Bedankt voor de tip Gideon. Ik zal kijken of ik het script kan aanpassen.
Dag Sander & Gideon, is het nog gelukt om de paging werkend te krijgen?
Ik loop ook tegen de beperking van 60 records aan..
Beste Valentijn,
Ik heb hier nog niet verder naar gekeken..
Maar je zou neen soort van loop moeten maken en op basis van de skip token bepalen of je verder moet gaan.
Wat op deze pagina beschreven staat zou ook verder kunnen helpen om meer dan 60 records op te halen: https://datachant.com/2016/06/27/cursor-based-pagination-power-query/
Komt misschien door :
”Most of the REST API have a page size of 60. The bulk and sync endpoints have a pagesize of 1000. It is recommended to use the sync endpoints where possible. Please check here for more information on restrictions.”
On
https://start.exactonline.nl/docs/HlpRestAPIResources.aspx
Hoi Gideon,
Met bovenstaande reacties al een paar foutmeldingen weten op te lossen. De volgende staat er alleen helaas nog niet tussen:
— Formula.Firewall: Query ‘Query1’ (step ‘Sorted Rows’) is accessing data sources that have privacy levels which cannot be used together. Please rebuild this data combination. —
Enig idee waar dit aan kan liggen?
Alvast bedankt.
Hi Michael,
De privacy levels van een data source kan je instellen via Home, Pijltje naast Edit Queries, Data source settings.
Els je vervolgens op Edit settings klikt, zie je het Privacy Level staan.
Blijkbaar zjn er meerdere data sources die verschillende privacy levels hebben.
Als je deze opnieuw instelt (ik denk op None) dan moet het volgens mij goed komen.
Hallo,
Misschien een beetje rare vraag maar ik zie het “Apps beheren” linkje niet om op te klikken terwijl ik wel een App Development account heb. We hebben al eens eerder een integratie gemaakt met FreshDesk namelijk. Heb je hiervoor iet speciaals nodig?
Hi Eric,
Ik heb even gekeken maar ik zie dat het tegenwoordig Registreer API Keys heet in plaats van Apps beheren.
De vervolg stappen lijken nog wel hetzelfde.
Hi Gideon,
Bedankt voor he reactie. Er blijkt wel meer anders te zijn. Ik kan ook geen test app registreren. Ik moet een productie app registreren en daar moet ik voor betalen. Ik zou dit wel graag eerst willen testen. Ik heb al bij Exact een support vraag hierover gesteld. Het is mij nog niet gelukt om dit op jou manier werkend te krijgen.
Hi
Heb je je aangemeld als App ontwikkelaar via de volgende link: https://www.exact.com/nl/exact-online/partners/app-center-partner/ ?
Of had je al een account?
Hartelijk dank voor het delen van deze informatie: Ik krijg echter nog de volgende foutmelding:
Expression.Error: The column ‘id’ of the table wasn’t found.
Details:
id
Nu vraag ik mij af wat doe ik fout?
Beste Gerben,
Haal je ook de Grootboekrekeningen ook (financial/GLAccounts)? Elk endpoint van de API heeft zijn eigen kolommen.
Deze kun je hier vinden: https://start.exactonline.nl/docs/HlpRestAPIResources.aspx?SourceAction=10
In bovenstaande code onder Gegevens ophalen zie je rond regel 42 staan welke kolommen verwacht worden:
#”Expanded entry” = Table.ExpandTableColumn(#”Expanded link”, “entry”,
{“id”, “title”, “updated”, “author”, “link”, “category”, “content”}, {“entry.id”, “entry.title”, “entry.updated”,
“entry.author”, “entry.link”, “entry.category”, “entry.content”})
Misschien heeft het endpoint dat jij gebruikt geen ID?
Hoi Gideon, bedankt voor dit leuke stuk.
Op dit moment loop ik vast op: Formula.Firewall: Query ‘Query1’ (step ‘Custom1’) is accessing data sources that have privacy levels which cannot be used together. Please rebuild this data combination.
Als ik de datasource settings – permissions wijzig (Anonymous, None) of andere combi’s helpt dat niet. Heb jij nog een tip?
Bvd Sjoerd
Beste Sjoerd,
Dit is idd een vervelende melding die niet altijd goed te traceren is.
Kan het zijn dat je twee queries met elkaar probeert te verbinden via bijvoorbeeld een merge? Dan kan het helpen om deze dataverbinding een keer helemaal opnieuw aan te maken?
Wellicht lees je ook nog een excel bestand of zo in? Deze combinatie loopt wel vaker mis.
Als je de Applied steps per stuk doorloopt, dan kun je achterhalen bij welke stap hij precies misloopt. Misschien dat je het dan kan achterhalen.
Ik krijg de onderstaande melding, iemand een idee?
An error occurred in the ‘’ query. Expression.Error: The name ‘Sorted Rows’ wasn’t recognized. Make sure it’s spelled correctly.
Hi Brian,
Dat lijkt in 1 van de laatst regels te zitten.
Als je in de Advanced editor kijkt, zie je dan een foutmelding (links onderin)?
Anders kan je wellicht onder de Applied steps in de Query editor de stap Sorted rows verwijderen.
Hi Gideon,
Nee in de Advanced editor krijg ik netjes No syntax errors have been detected.
Als ik jouw code erin plakt dat krijg ik onderstaande error
Expression.Error: The name ‘Expanded entry.content.http://schemas.microsoft.com/ado/2007/08/dataservices/metadata.properties.
http://schemas.microsoft.com/ado/2007/08/dataservices‘ wasn’t recognized. Make sure it’s spelled correctly.
Als ik vervolgens de na [Headers=[Authorization=AccessTokenHeader]])) alles weghaalt tot in krijg ik de melding welke ik eerder aangaf over die Sorted rows.
Groet, Brian
De Expanded entry content lijkt te verwijzen naar een stukje code die nog na de AccessTokenHeader staat.
Heb je dit staan:
let
actualUrl = URL & “/api/oauth2/token”,
cntnt = Text.ToBinary(Uri.BuildQueryString(
[refresh_token= Refresh_token
,grant_type=”refresh_token”
,client_id= Client_id
,client_secret=Client_secret
])),
options = [Headers =[#”Content-type”=”application/x-www-form-urlencoded”],Content=cntnt],
result = Web.Contents(actualUrl, options),
#”JSON” = Json.Document(result),
access_token= #”JSON”[access_token],
AccessTokenHeader = “Bearer ” & access_token,
GetJsonQuery = (Web.Contents( URL & “/api/v1/”& Number.ToText(DivisionCode) & “/” & URI,
[Headers=[Authorization=AccessTokenHeader]]))
in
GetJsonQuery
In mijn Exact online heb ik meerdere administratie. Als ik gegevens op wil halen zal ik ergens moeten aangeven uit welke administratie ik deze wil halen. Op dit moment ben ik zover dat ik geen foutmeldingen meer krijg maar ik krijg ook geen data te zien.
Via Postman heb ik de DivisionCode opgehaald, maar hier kan ik nergens iets vinden om te bepalen om welke administratie het gaat.
Iemand een idee hoe dit in te stellen is?
Hoi Danielle,
De Division Code die je hebt opgehaald, is de identificatie van de administratie.
Als je deze invult bij de parameters wordt deze division code gebruikt bij het ophalen van de gegevens.
Hoi Gideon,
Bedankt voor je snelle reactie. Maar als ik in Postman de stappen doorloop voor de Request Token kom ik in het inlogscherm van Exact Online. De gegevens (inlognaam en wachtwoord) die ik hier invul geven toegang tot een aantal administraties. Ik zou toch ergens moeten bepalen voor welke administratie ik gegevens wil ophalen.
Na het doorlopen van alle stappen en het invullen van de code krijg ik geen foutmelding maar ik krijg ook geen gegevens. Ik zie 1 kolom met 1 rij met daarin de tekst “Sorted Rows”
Hoi Danielle,
Als je inlogt in Exact Online zelf en daar van admiistratie wisselt zie je in de URL ook de divisioncode staan van de administratie waar je dan in zit.
Helpt dat?
Beste Joep en anderen,
Bij het kopieren van de code wordt automatisch word-wrap toegepast. In de betreffende regel is dat halverwege een quoted string en dat geeft problemen.
Haal de enters weg en het probleem is opgelost
Beste,
Bij het toepassen van deze code lukt het om in de Query editor data uit exact online te halen. Jammer genoeg lukt het mij niet om de data te laden wanneer ik op close & apply indruk. Ik denk dat het te maken heeft met de access token en de refresh token, maar ik weet niet hoe ik deze kan refreshen tijdens een ‘apply change’.
Beste,
Bij het registreren van een nieuwe app vul ik de app naam en redirect URI in https://www.getpostman.com/oauth2/callback
ik heb de keuze om de app te regristeren echter gebeurd er daarna niks. iemand tips?
Groeten, Frank
Beste,
Na invullen van de Exaxt Online gebruikersnaam en wachtwoord en token, krijg ik de volgende foutmelding Authentication failed, in de postman console geeft die aan invalid request. Gegevens zijn ingevuld zoals aangegeven in de handlading, iemand tips?
Ik heb hetzelfde probleem. Heeft dit te maken met MFA welke ik nergens in kan vullen?
Hi Jasper,
Heeft inderdaad te maken met MFA, voor zover ik heb gelezen ondersteund postman geen MFA,
Heb jij al een oplossing, je zou me kunnen benaderen op linkedin.
Met vriendelijke groet,
Frank Hagenaars