> For the complete documentation index, see [llms.txt](https://pathta.gitbook.io/pathta-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://pathta.gitbook.io/pathta-docs/reporting/see-your-data-on-power-bi-with-pathta-function/installation-of-pathta-pbi-function.md).

# Installation of Pathta PBI function

{% hint style="info" %}
You can instal the Pathta function or use the empy Power BI file below which already contains the function
{% endhint %}

## First possibility : use empty Power BI file

{% file src="/files/mjCrHXAXACyRiHoMGr9P" %}

## Second possibility : copy Function code in a blank query

Open Power BI and add a Blank query data source. Copy paste the following M code in the Advanced Editor

<figure><img src="https://1039087027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FKMgBZ3wq0SUPGSqOmR9C%2Fuploads%2FFwC9tvK0qviN6Hq5RNnH%2Fimage.png?alt=media&amp;token=87615c96-0202-4af5-ae2e-535b6cf4e3d2" alt=""><figcaption></figcaption></figure>

```powerquery
let
    PathtaFx = (Credential as text, PathId as number, optional JsonParameters as any) as table =>
    let
        BaseUrl = "https://reporting.pathta.io",

        SafeWebGet = (relativePath as text, query as record) as binary =>
            let
                Attempt = (n as number) as binary =>
                    let
                        TryResp = try Web.Contents(
                            BaseUrl,
                            [
                                RelativePath         = relativePath,
                                Query                = query,
                                Headers              = [ Accept = "application/json" ],
                                ManualStatusHandling = {400, 401, 403, 404, 408, 429, 500, 502, 503, 504}
                            ]
                        ),
                        Status = if TryResp[HasError] then 0 else Value.Metadata(TryResp[Value])[Response.Status],
                        IsOk   = not TryResp[HasError] and Status >= 200 and Status < 300,
                        Result =
                            if IsOk then
                                TryResp[Value]
                            else if n >= 3 then
                                error [
                                    Reason  = "Pathta API Error",
                                    Message = "L'appel API Pathta a échoué après 3 tentatives sur " & relativePath
                                              & (if TryResp[HasError]
                                                 then " : " & TryResp[Error][Message]
                                                 else " (HTTP " & Number.ToText(Status) & ")"),
                                    Detail  = if TryResp[HasError]
                                              then TryResp[Error]
                                              else try Text.FromBinary(TryResp[Value]) otherwise null
                                ]
                            else
                                Function.InvokeAfter(() => @Attempt(n + 1), #duration(0, 0, 0, 1))
                    in Result
            in Attempt(1),

        FieldsJson = Json.Document(
                SafeWebGet(
                    "Reporting/" & Number.ToText(PathId) & "/PathFields",
                    [credential = Credential]
                )
            ),
        FieldsTbl = Table.FromRecords(FieldsJson),
        FieldsRen = Table.RenameColumns(FieldsTbl, {{"id","FieldId"},{"name","FieldName"},{"type","FieldType"}}, MissingField.UseNull),

        FieldIds   = List.Transform(FieldsRen[FieldId], each Text.From(_, "en-US")),
        FieldNames = FieldsRen[FieldName],
        FieldTypes   = List.Transform(FieldsRen[FieldType], each
            if      _ = "String"        then type text
            else if _ = "Int32"         then Int64.Type
            else if _ = "Int64"         then Int64.Type
            else if _ = "Decimal"       then type number
            else if _ = "Double"        then type number
            else if _ = "Boolean"       then type logical
            else if _ = "DateTime"      then type datetime
            else if _ = "Date"          then type date
            else if _ = "StringArray"   then type list
            else if _ = "Int32Array"    then type list
            else if _ = "Int64Array"    then type list
            else if _ = "DecimalArray"  then type list
            else if _ = "DoubleArray"   then type list
            else if _ = "BooleanArray"  then type list
            else if _ = "DateTimeArray" then type list
            else if _ = "DateArray"     then type list
            else if _ = "MultipleLinks" then type list
            else if _ = "SimpleLink"    then type text
            else type any
        ),

        RenamePairs        = List.Zip({FieldIds, FieldNames}),
        FieldsZipped       = List.Zip({FieldNames, FieldTypes}),
        ListCols           = List.Select(FieldsZipped, each _{1} = type list),
        NonListCols        = List.Select(FieldsZipped, each _{1} <> type list),
        NonListTypePairs   = List.Transform(NonListCols, each { _{0}, _{1} }),

        ParametersText =
            if JsonParameters <> null
            then Text.FromBinary(Json.FromValue(JsonParameters), TextEncoding.Utf8)
            else null,

        GetPage = (optional TaskId as nullable text, optional PageKey as nullable text) as table =>
            let
                QueryRecordBase = [
                    fieldIds   = Text.Combine(FieldIds, ";"),
                    credential = Credential
                ],
                QueryWithParams =
                    if ParametersText <> null
                    then Record.AddField(QueryRecordBase, "parameters", ParametersText)
                    else QueryRecordBase,
                QueryWithTask =
                    if TaskId <> null and TaskId <> "" then Record.AddField(QueryWithParams, "taskId", TaskId) else QueryWithParams,
                FinalQuery =
                    if PageKey <> null and PageKey <> "" then Record.AddField(QueryWithTask, "pageKey", PageKey) else QueryWithTask,

                Resp =
                    Json.Document(
                        SafeWebGet(
                            "Reporting/" & Number.ToText(PathId) & "/PathRows",
                            FinalQuery
                        )
                    ),

                Rows     = if Record.HasFields(Resp, "Rows")    then Resp[Rows] else {},
                T0 = Table.FromList(Rows, Splitter.SplitByNothing(), {"Data"}),
                T1 = if Table.RowCount(T0) = 0 then #table(FieldNames,{}) else Table.ExpandRecordColumn(T0, "Data", FieldIds, FieldIds),
                T2 = Table.RenameColumns(T1, RenamePairs, MissingField.Ignore),
                T3 = List.Accumulate(
                        ListCols,
                        T2,
                        (s, c) => Table.TransformColumns(s, {{c{0}, each if _ = null then {} else _}})
                    ),
                T4 = Table.TransformColumnTypes(T3, NonListTypePairs),
                NextTask = if Record.HasFields(Resp, "TaskId")  then Text.From(Resp[TaskId]) else null,
                NextKey  = if Record.HasFields(Resp, "PageKey") then Text.From(Resp[PageKey]) else null,
                Out = T4 meta [NextTask = NextTask, NextKey = NextKey]
            in
                Out,

        FirstTbl = GetPage(null, null),
        Pages =
            List.Generate(
                () => [Tbl = FirstTbl],
                each [Tbl] <> null,
                each
                    let m = Value.Metadata([Tbl]),
                        nxtTask = m[NextTask]?,
                        nxtKey  = m[NextKey]?,
                        nxtTbl  = if nxtKey <> null and nxtKey <> "" then GetPage(nxtTask, nxtKey) else null
                    in  [Tbl = nxtTbl],
                each [Tbl]
            ),

        Combined =
            if FirstTbl = null then #table(FieldNames, {})
            else
                Table.Combine(List.RemoveNulls(Pages))
            in
                Combined
in
    PathtaFx
```

## Calling Pathta function&#x20;

The function has 2 parameters : the first one Credential is the token parameter and the second one is the Path Id.\
You can find those 2 informations in the checking tab of a reporting Path\
Fill Token (Credential) and PathId parameter and click on Invoke.

<figure><img src="https://1039087027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FKMgBZ3wq0SUPGSqOmR9C%2Fuploads%2FFc4ryGPSh59MFhmwaNqh%2Fimage.png?alt=media&amp;token=54676c9f-fc02-4fee-8bd2-7739f68d6f0e" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
You can see how to find your Credential and PathId there :&#x20;

[Find Credential and  Path Id](/pathta-docs/reporting/see-your-data-on-power-bi-with-pathta-function/find-credential-and-path-id.md)
{% endhint %}

Click on Edit Credentials (necessary for the first call)

<figure><img src="https://1039087027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FKMgBZ3wq0SUPGSqOmR9C%2Fuploads%2FTn8yas9DNgbHhxiEm9kF%2Fimage.png?alt=media&amp;token=d42e39ee-29a5-4587-94a3-7edde904ab99" alt=""><figcaption></figcaption></figure>

Select Anonymous and click on connect

<figure><img src="https://1039087027-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FKMgBZ3wq0SUPGSqOmR9C%2Fuploads%2FuigitJOfe1XSYRcvum0i%2Fimage.png?alt=media&amp;token=5a3df105-80de-4044-9aad-d8ef8cc10989" alt=""><figcaption></figcaption></figure>

{% hint style="success" %}
Your fonction is now ready to use !
{% endhint %}
