cancel
Showing results for 
Search instead for 
Did you mean: 

Databricks API JSON Result to Collection

naveed_raza
Level 8

Hi All,

Does anybody get a chance to work on Databricks API ?

Databricks API result comes in JSON and the JSON format is different compare to other API results as here in Databricks API we are getting columns in different array of object and actual data in different array of object.

What is the best way to convert this into proper data table (collection) with headers ?

Example: 

{
"schema": {
   "columns": 
      [
        {
          "name": "headername",
          "type": "string"
        },
        {
          "name": "headername2",
          "type": "date"
        }
      ]
  },
 "result": 
   {
     "data_array":[
           [
             "row1header1value",
             "row1header2value"
           ],
           [
             "row2header1value",
             "row2header2value"
           ]
         ]
   }
}

 #API, #databricks, #json

1 BEST ANSWER

Helpful Answers

naveed_raza
Level 8

finally i have written the code to convert into table format,

here is sample Databricks API JSON output ( i have removed un wanted columns from JSON and kept only required one)

{
    "manifest": {
        "schema": {
            "columns":
            [{
                    "name": "headername",
                    "type_name": "string"
                }, {
                    "name": "headername2",
                    "type_name": "string"
                }
            ]
        }
    },
    "result": {
        "data_array": [
            [
                "row1header1value",
                "row1header2value"
            ],
            [
                "row2header1value",
                "row2header2value"
            ]
        ]
    }
}

 here is my vb.net code, which i have written as a Global Code and using code staging calling this code by passing entire Databricks API JSON string as an input , and in output fetching Datatable and record count.

Note: make sure to add all necessary DLLs and namespace

Public Function ConvertDatabricksResultToDataTable(jsonStr As String) As DataTable

	Dim dt As New DataTable()

 ' Parse the JSON
	Dim jObj = JObject.Parse(jsonStr)

 ' Get Columns from manifest.schema.columns and adding to data table
	 Dim cols = jObj("manifest")("schema")("columns")

	 For Each col In cols
		 Dim colName As String = col("name").ToString()
		 Dim colType As String = col("type_name").ToString()

		' map Databricks type to VB.NET type
		 Select Case colType.ToUpper()
			Case "LONG", "BIGINT"
				dt.Columns.Add(colName, GetType(Long))
			Case "INTEGER", "INT"
				dt.Columns.Add(colName, GetType(Integer))
			Case "DECIMAL", "DOUBLE", "FLOAT"
				dt.Columns.Add(colName, GetType(Decimal))
			Case "DATE", "TIMESTAMP", "DATETIME"
				dt.Columns.Add(colName, GetType(Date))
			Case "BOOLEAN", "BOOL"
				dt.Columns.Add(colName, GetType(Boolean))
			Case Else
				dt.Columns.Add(colName, GetType(String))
		 End Select
	 Next

 ' Looping each record and addings rows from result.data_array
	Dim rows = jObj("result")("data_array")

	For Each r In rows
		Dim arr As New List(Of Object)

		For i = 0 To dt.Columns.Count - 1
			Dim value = r(i).ToString()

			' Convert data types per column
			Dim colType = dt.Columns(i).DataType

			If colType Is GetType(Long) Then
				arr.Add(Long.Parse(value))
			ElseIf colType Is GetType(Integer) Then
				arr.Add(Integer.Parse(value))
			ElseIf colType Is GetType(Decimal) Then
				arr.Add(Decimal.Parse(value))
			ElseIf colType Is GetType(Date) Then
				Dim d as Date
				If Date.TryParseExact(value,{"yyyy-MM-dd","yyyy-MM-ddTHH:mm:ss","yyyy-MM-ddTHH:mm:ssZ"},System.Globalization.CultureInfo.InvariantCulture,Globalization.DateTimeStyles.None,d) then
					arr.Add(d)
				else
					arr.Add(DBNull.Value)
				End if
			ElseIf colType Is GetType(Boolean) Then
				Select Case value.ToString().Trim().ToLower()
					Case "true", "1", "yes"
						arr.Add(True)
					Case "false", "0", "no"
						arr.Add(False)
					Case Else
						arr.Add(DBNull.Value)
				End Select
			Else
				arr.Add(value) ' fallback string
			End If
		Next

		dt.Rows.Add(arr.ToArray())
	Next

	Return dt

End Function

 Please do let us know, if this solution is best to go or can we do it in any other better way. Hope this will help for others also.

 

Regards,

Mohammad Naveed

View answer in original post

12 REPLIES 12

naveed_raza
Level 8

i reviewed other options like OLEDB and ODBC,

Looks like using OLEDB we can't connect to Databricks, and using ODBC , we have to do some work around and for that looks like we have install Databricks odbc driver and do setup in bots to make this callable so that will get data in proper table format.

by seeing this , i have to go with Databricks API only and have to found a way to convert that JSON in proper table format

naveed_raza
Level 8

i thought of storing columns collection and data collection separately and doing loop for data , but thinking looping is not the good idea here.

i am writing VB.Net code to convert this into proper table format, will share the code here once its done

Hi @naveed_raza 

Have you tried Utility - JSON VBO->JSON to Collection 

Best Regards,

Sayeed Bin Abdullah 

naveed_raza
Level 8

Using JSON Utility , it convert in table, however one column we have nested collection and another column will have data collection.

One Table will have 2 columns , and each column will have nested collection, headers in one column, actual data in another

naveed_raza
Level 8

@SayeedBinAbdullah - this is how its showing , if we use JSON utility 

schema column will have columns , and result column will have actual data row. i am done with coding, testing , will share the code shortly.

 

naveed_raza_0-1765309734727.png

naveed_raza_2-1765309850239.png

naveed_raza_3-1765309878077.png

 

 

naveed_raza
Level 8

finally i have written the code to convert into table format,

here is sample Databricks API JSON output ( i have removed un wanted columns from JSON and kept only required one)

{
    "manifest": {
        "schema": {
            "columns":
            [{
                    "name": "headername",
                    "type_name": "string"
                }, {
                    "name": "headername2",
                    "type_name": "string"
                }
            ]
        }
    },
    "result": {
        "data_array": [
            [
                "row1header1value",
                "row1header2value"
            ],
            [
                "row2header1value",
                "row2header2value"
            ]
        ]
    }
}

 here is my vb.net code, which i have written as a Global Code and using code staging calling this code by passing entire Databricks API JSON string as an input , and in output fetching Datatable and record count.

Note: make sure to add all necessary DLLs and namespace

Public Function ConvertDatabricksResultToDataTable(jsonStr As String) As DataTable

	Dim dt As New DataTable()

 ' Parse the JSON
	Dim jObj = JObject.Parse(jsonStr)

 ' Get Columns from manifest.schema.columns and adding to data table
	 Dim cols = jObj("manifest")("schema")("columns")

	 For Each col In cols
		 Dim colName As String = col("name").ToString()
		 Dim colType As String = col("type_name").ToString()

		' map Databricks type to VB.NET type
		 Select Case colType.ToUpper()
			Case "LONG", "BIGINT"
				dt.Columns.Add(colName, GetType(Long))
			Case "INTEGER", "INT"
				dt.Columns.Add(colName, GetType(Integer))
			Case "DECIMAL", "DOUBLE", "FLOAT"
				dt.Columns.Add(colName, GetType(Decimal))
			Case "DATE", "TIMESTAMP", "DATETIME"
				dt.Columns.Add(colName, GetType(Date))
			Case "BOOLEAN", "BOOL"
				dt.Columns.Add(colName, GetType(Boolean))
			Case Else
				dt.Columns.Add(colName, GetType(String))
		 End Select
	 Next

 ' Looping each record and addings rows from result.data_array
	Dim rows = jObj("result")("data_array")

	For Each r In rows
		Dim arr As New List(Of Object)

		For i = 0 To dt.Columns.Count - 1
			Dim value = r(i).ToString()

			' Convert data types per column
			Dim colType = dt.Columns(i).DataType

			If colType Is GetType(Long) Then
				arr.Add(Long.Parse(value))
			ElseIf colType Is GetType(Integer) Then
				arr.Add(Integer.Parse(value))
			ElseIf colType Is GetType(Decimal) Then
				arr.Add(Decimal.Parse(value))
			ElseIf colType Is GetType(Date) Then
				Dim d as Date
				If Date.TryParseExact(value,{"yyyy-MM-dd","yyyy-MM-ddTHH:mm:ss","yyyy-MM-ddTHH:mm:ssZ"},System.Globalization.CultureInfo.InvariantCulture,Globalization.DateTimeStyles.None,d) then
					arr.Add(d)
				else
					arr.Add(DBNull.Value)
				End if
			ElseIf colType Is GetType(Boolean) Then
				Select Case value.ToString().Trim().ToLower()
					Case "true", "1", "yes"
						arr.Add(True)
					Case "false", "0", "no"
						arr.Add(False)
					Case Else
						arr.Add(DBNull.Value)
				End Select
			Else
				arr.Add(value) ' fallback string
			End If
		Next

		dt.Rows.Add(arr.ToArray())
	Next

	Return dt

End Function

 Please do let us know, if this solution is best to go or can we do it in any other better way. Hope this will help for others also.

 

Regards,

Mohammad Naveed

Hi Naveed,

Can you please list down all the dll's required?

naveed_raza
Level 8

Hi Sayeed,

for me its hard to tell , as here i have created a reusable object (RPA Utility) which has all the actions which is not there in regular VBOs and i have added all possible DLLs to my object by default.

mostly NewtonJSON and other basic DLLs, here is my list of DLLs which i added.

naveed_raza_0-1765363349974.png

 

Hi all,

If it helps, I created a reusable object that runs a query on Databricks (there are two actions, one for a personal token, the other for a token generated by Service Principal). Here is the code: 

<process name="VBO - Databricks" version="1.0" bpversion="7.1.0.62280" narrative="" byrefcollection="true" type="object" runmode="Exclusive" preferredid="a89c02ea-a295-4848-b504-a2afe92a5e7e">
  <appdef>
    <element name="Application Root">
      <id>a1fcd9f9-3d26-4f70-bcc0-8406d53a2f05</id>
      <type>Application</type>
      <basetype>Application</basetype>
      <datatype>unknown</datatype>
      <diagnose>False</diagnose>
    </element>
  </appdef>
  <view>
    <camerax>0</camerax>
    <cameray>0</cameray>
    <zoom version="2">1.25</zoom>
  </view>
  <preconditions />
  <endpoint narrative="" />
  <subsheet subsheetid="7d7495b5-ea2b-424a-aae0-3c029b92f2a9" type="CleanUp" published="True">
    <name>Clean Up</name>
    <view>
      <camerax>0</camerax>
      <cameray>0</cameray>
      <zoom version="2">1.25</zoom>
    </view>
  </subsheet>
  <subsheet subsheetid="9cb7bf9b-8ba4-45f2-b334-fc34ba39707a" type="Normal" published="False">
    <name>Authentication</name>
    <view>
      <camerax>0</camerax>
      <cameray>21</cameray>
      <zoom version="2">1.25</zoom>
    </view>
  </subsheet>
  <subsheet subsheetid="8e5d6e27-2067-4108-a3de-c6d32385476c" type="Normal" published="True">
    <name>Execute Query</name>
    <view>
      <camerax>-111</camerax>
      <cameray>243</cameray>
      <zoom version="2">1.25</zoom>
    </view>
  </subsheet>
  <subsheet subsheetid="fa900c6f-ef74-4b80-a2e5-f70e341de476" type="Normal" published="True">
    <name>Execute Query - Using Token</name>
    <view>
      <camerax>-111</camerax>
      <cameray>96</cameray>
      <zoom version="2">1.25</zoom>
    </view>
  </subsheet>
  <stage stageid="ea40e4ef-0578-444a-93d6-cf433c09b609" name="Start" type="Start">
    <loginhibit />
    <display x="15" y="-105" />
    <onsuccess>1fba778b-777b-4bb2-8996-1fc62fc8fcd2</onsuccess>
  </stage>
  <stage stageid="1fba778b-777b-4bb2-8996-1fc62fc8fcd2" name="End" type="End">
    <loginhibit />
    <display x="15" y="90" />
  </stage>
  <stage stageid="f34ba72c-ee5c-4e66-9417-d7196dd2134a" name="Stage1" type="ProcessInfo">
    <display x="-195" y="-105" w="150" h="90" />
    <references>
      <reference>System.dll</reference>
      <reference>System.Data.dll</reference>
      <reference>System.Xml.dll</reference>
      <reference>System.Drawing.dll</reference>
      <reference>System.Net.Http.dll</reference>
      <reference>EPPlus.dll</reference>
      <reference>ClosedXML.dll</reference>
      <reference>netstandard.dll</reference>
      <reference>System.Core.dll</reference>
      <reference>System.Net.Http.Json.dll</reference>
      <reference>Newtonsoft.Json.dll</reference>
      <reference>System.Windows.Forms.dll</reference>
      <reference>System.Net.Http.dll</reference>
    </references>
    <imports>
      <import>System</import>
      <import>System.Drawing</import>
      <import>System.Data</import>
      <import>System.Net.Http</import>
      <import>System.Text</import>
      <import>ClosedXML.Excel</import>
      <import>OfficeOpenXml</import>
      <import>System.Collections.Generic</import>
      <import>System.Linq</import>
      <import>System.IO</import>
      <import>Newtonsoft.Json</import>
      <import>Newtonsoft.Json.Linq</import>
      <import>System.Windows.Forms</import>
      <import>System.Net.Http.Headers</import>
    </imports>
    <language>csharp</language>
    <globalcode><![CDATA[]]></globalcode>
    <code><![CDATA[public class DataTableToExcel
{
    public void ExportToExcel(DataTable dataTable, string filePath, string sheet)
    {
        // Configura EPPlus per usare la licenza non commerciale
 
        using (var package = new ExcelPackage())
        {
            var worksheet = package.Workbook.Worksheets.Add(sheet);
 
            // Aggiungi le intestazioni delle colonne
            for (int col = 0; col < dataTable.Columns.Count; col++)
            {
                worksheet.Cells[1, col + 1].Value = dataTable.Columns[col].ColumnName;
            }
 
            // Aggiungi i dati delle righe
            worksheet.Cells["A2"].LoadFromDataTable(dataTable, false);
 
            // Salva il file Excel
            var fileInfo = new FileInfo(filePath);
            package.SaveAs(fileInfo);
        }
    }
}
 
 
 
public class Column
{
    public string name { get; set; }
}
 
public class Row
{
    public List<string> values { get; set; }
}
 
public class JsonResponse
{
    public List<Column> columns { get; set; }
    public List<Row> rows { get; set; }
}
 
 
 
public static DataTable GenerateDataTableFromJson(string json)
    {
        JObject jsonObject = JObject.Parse(json);
        JArray columns = (JArray)jsonObject["manifest"]["schema"]["columns"];
        JArray dataArray = (JArray)jsonObject["result"]["data_array"];
 
        DataTable dataTable = new DataTable();
 
        foreach (var column in columns)
        {
            dataTable.Columns.Add(column["name"].ToString(), typeof(string));
        }
 
        foreach (var row in dataArray)
        {
            DataRow dataRow = dataTable.NewRow();
            for (int i = 0; i < columns.Count; i++)
            {
                dataRow[i] = row[i].ToString();
            }
            dataTable.Rows.Add(dataRow);
        }
 
        return dataTable;
    }
 
public static string EscapeForJson(string s)
    {
        if (s == null) return "";
        return s.Replace("\\", "\\\\").Replace("\"", "\\\"");
    }
]]></code>
  </stage>
  <stage stageid="ce38e7ce-fcf1-4e63-bd70-44a2babf6a61" name="Clean Up" type="SubSheetInfo">
    <subsheetid>7d7495b5-ea2b-424a-aae0-3c029b92f2a9</subsheetid>
    <display x="-195" y="-105" w="150" h="90" />
  </stage>
  <stage stageid="6638295e-5a03-4485-84f4-0be42967f3be" name="Start" type="Start">
    <subsheetid>7d7495b5-ea2b-424a-aae0-3c029b92f2a9</subsheetid>
    <loginhibit />
    <display x="15" y="-105" />
    <onsuccess>9e0c8841-53a6-4607-ad35-b1d9f8b571d7</onsuccess>
  </stage>
  <stage stageid="9e0c8841-53a6-4607-ad35-b1d9f8b571d7" name="End" type="End">
    <subsheetid>7d7495b5-ea2b-424a-aae0-3c029b92f2a9</subsheetid>
    <loginhibit />
    <display x="15" y="90" />
  </stage>
  <stage stageid="a7ffe0ff-6bed-410a-8542-627fac718426" name="Execute Query" type="SubSheetInfo">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <display x="-195" y="-105" w="150" h="90" />
  </stage>
  <stage stageid="7f49a903-a4c5-4669-b7e3-c8b900154c68" name="Start" type="Start">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <loginhibit />
    <display x="-60" y="-135" />
    <inputs>
      <input type="text" name="baseUrl" stage="baseUrl" />
      <input type="text" name="accessToken" stage="accessToken" />
      <input type="text" name="warehouseId" stage="warehouseId" />
      <input type="text" name="sqlQuery" stage="sqlQuery" />
      <input type="flag" name="CreateExcel" stage="CreateExcel" />
      <input type="text" name="FilepathXLSX" stage="FilepathXLSX" />
      <input type="text" name="SheetName" stage="SheetName" />
    </inputs>
    <onsuccess>d0350ab4-99aa-4763-8c78-887721f4a3a5</onsuccess>
  </stage>
  <stage stageid="6a16195e-41c8-4e52-8625-061243db0811" name="End" type="End">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <loginhibit />
    <display x="-60" y="345" />
    <outputs>
      <output type="flag" name="Success" stage="Success" />
      <output type="text" name="Error Message" stage="Error Message" />
      <output type="collection" name="Report" stage="Report" />
    </outputs>
  </stage>
  <stage stageid="882d594d-6359-4c08-9c68-adb46b927cc7" name="" type="Note">
    <subsheetid>7d7495b5-ea2b-424a-aae0-3c029b92f2a9</subsheetid>
    <narrative>Clean Up Page
 
This is an optional page where you might choose to perform some finalisation (or "cleanup") tasks as your business object is closed down.
 
The cleanup action will be called automatically immediately after closing your business object at the end of a business process.
 
You will not be able to call this action from a business process, nor will it be called at any other time than before the disposal of the business object.</narrative>
    <display x="-180" y="60" w="180" h="230" />
  </stage>
  <stage stageid="211de8a5-16c7-48bf-bff2-3e8859a8d124" name="" type="Note">
    <narrative>Initialise Page
 
This is an optional page where you might choose to perform some initialisation tasks after your business object is loaded.
 
The initialise action will be called automatically immediately after loading your business object.
 
You will not be able to call this action from a business process, nor will it be called at any other time than after the creation of the object.</narrative>
    <display x="-180" y="60" w="180" h="230" />
  </stage>
  <stage stageid="d0350ab4-99aa-4763-8c78-887721f4a3a5" name="Call API" type="Code">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <loginhibit />
    <display x="-60" y="-75" />
    <inputs>
      <input type="text" name="baseUrl" expr="[baseUrl]" />
      <input type="text" name="accessToken" expr="[accessToken]" />
      <input type="text" name="warehouseId" expr="[warehouseId]" />
      <input type="text" name="sqlQuery" expr="[sqlQuery]" />
    </inputs>
    <outputs>
      <output type="flag" name="Success" stage="Success" />
      <output type="text" name="ErrorMessage" stage="Error Message" />
      <output type="text" name="JSONOutput" stage="JSONOutput" />
    </outputs>
    <onsuccess>5555a2e6-2d06-4da2-b986-60516c04f8c4</onsuccess>
    <code><![CDATA[Success = false;
ErrorMessage = "";
JSONOutput = "";
 
 
HttpClient client = new HttpClient();
 
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, baseUrl)
{
Content = new StringContent(
              $"{{\"statement\":\"{sqlQuery}\", \"warehouse_id\":\"{warehouseId}\", \"timeout_seconds\":600}}",
              Encoding.UTF8,
              "application/json"
              )
};
request.Headers.Add("Authorization", $"Bearer {accessToken}");                // Invia la richiesta
HttpResponseMessage response = client.SendAsync(request).Result;
 
 
if (response.IsSuccessStatusCode)
{
string responseBody = response.Content.ReadAsStringAsync().Result;
Success = true;
JSONOutput = responseBody;
}
else
{
 
string responseBody = response.Content.ReadAsStringAsync().Result;
ErrorMessage = responseBody;
 
}
 
 
]]></code>
  </stage>
  <stage stageid="8e8901e4-0469-467c-ba32-ef8872e06bd4" name="baseUrl" type="Data">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <display x="-165" y="30" />
    <datatype>text</datatype>
    <initialvalue />
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="dccd3340-c59f-4c07-9cf0-6b2158a0b15c" name="accessToken" type="Data">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <display x="-225" y="30" />
    <datatype>text</datatype>
    <initialvalue />
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="a37d696c-f22a-42d2-926e-972ba737ca40" name="warehouseId" type="Data">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <display x="-165" y="-15" />
    <datatype>text</datatype>
    <initialvalue />
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="bd29c410-6809-46ee-ba90-4913e5c23721" name="sqlQuery" type="Data">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <display x="-225" y="-15" />
    <datatype>text</datatype>
    <initialvalue />
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="23e4c765-3cad-483e-b764-22c0b9fa4986" name="Success" type="Data">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <display x="-165" y="360" />
    <datatype>flag</datatype>
    <initialvalue>False</initialvalue>
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="c9bef68e-b917-4f91-a8f3-850be2935e93" name="Error Message" type="Data">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <display x="-225" y="360" />
    <datatype>text</datatype>
    <initialvalue />
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="a4f71191-c150-4bc5-a71c-1407b88ea104" name="JSONOutput" type="Data">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <display x="-225" y="195" />
    <datatype>text</datatype>
    <initialvalue />
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="23680203-a356-4f4a-9aa5-11ec8d787164" name="Report" type="Collection">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <display x="-225" y="405" />
    <datatype>collection</datatype>
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="2b95b981-f6a3-46d2-ac2f-c3bf37e109aa" name="Convert JSON" type="Code">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <loginhibit />
    <display x="-60" y="45" />
    <inputs>
      <input type="text" name="json" expr="[JSONOutput]" />
    </inputs>
    <outputs>
      <output type="flag" name="Success" stage="Success" />
      <output type="text" name="ErrorMessage" stage="Error Message" />
      <output type="collection" name="dataTable" stage="Report" />
    </outputs>
    <onsuccess>081c9bf2-4828-47ba-9f88-ee45a75f8735</onsuccess>
    <code><![CDATA[Success = false;
ErrorMessage = "";
dataTable = null;
dataTable = new DataTable();
 
try
{
dataTable = GenerateDataTableFromJson(json);
Success = true;
}
catch (Exception ex)
{
Success = false;
ErrorMessage = ex.Message;
}
 
]]></code>
  </stage>
  <stage stageid="6f826340-a4b0-4a90-a21b-b7e83d2c3b64" name="Inputs" type="Block">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <loginhibit />
    <display x="-270" y="-45" w="150" h="195" />
    <font family="Segoe UI" size="10" style="Regular" color="7FB2E5" />
  </stage>
  <stage stageid="fc658c67-57fc-4741-81e3-420dee311aad" name="Local" type="Block">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <loginhibit />
    <display x="-270" y="165" w="150" h="150" />
    <font family="Segoe UI" size="10" style="Regular" color="FFFF00" />
  </stage>
  <stage stageid="69e8baa0-51a9-4cb0-8102-628d715d54fd" name="Outputs" type="Block">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <loginhibit />
    <display x="-270" y="330" w="150" h="105" />
    <font family="Segoe UI" size="10" style="Regular" color="FF00FF" />
  </stage>
  <stage stageid="3d0bd6c8-bfea-4f19-b1f0-17af6082fd95" name="FilepathXLSX" type="Data">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <display x="-165" y="75" />
    <datatype>text</datatype>
    <initialvalue />
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="6fce1fed-aed7-4be8-98a7-47cd4d387274" name="CreateExcel" type="Data">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <display x="-225" y="75" />
    <datatype>flag</datatype>
    <initialvalue>False</initialvalue>
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="4a1251fb-c3ba-49fa-82e5-4364fec79357" name="Create Excel" type="Code">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <loginhibit />
    <display x="-60" y="225" />
    <inputs>
      <input type="collection" name="DatatableResult" expr="[Report]" />
      <input type="text" name="Filepath" expr="[FilepathXLSX]" />
      <input type="text" name="SheetName" expr="[SheetName]" />
    </inputs>
    <outputs>
      <output type="flag" name="Success" stage="Success" />
      <output type="text" name="ErrorMessage" stage="Error Message" />
    </outputs>
    <onsuccess>943d0920-2cf6-4da3-9b48-9a5af41f847f</onsuccess>
    <code><![CDATA[Success = false;
ErrorMessage = "";
 
try
{
DataTableToExcel exporter = new DataTableToExcel();
exporter.ExportToExcel(DatatableResult, Filepath, SheetName);
Success = true;
}
catch (Exception ex)
{
Success = false;
ErrorMessage = ex.Message;
}]]></code>
  </stage>
  <stage stageid="3f15a13e-c6d9-4309-b03c-b84634339a44" name="[CreateExcel] = True" type="Decision">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <loginhibit />
    <display x="-60" y="165" />
    <decision expression="[CreateExcel] = True" />
    <ontrue>4a1251fb-c3ba-49fa-82e5-4364fec79357</ontrue>
    <onfalse>aff1fb43-83dd-411b-895e-121a6e9aaa67</onfalse>
  </stage>
  <stage stageid="aff1fb43-83dd-411b-895e-121a6e9aaa67" name="Anchor1" type="Anchor">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <loginhibit />
    <display x="90" y="165" w="10" h="10" />
    <onsuccess>de02cbf6-bc09-4036-9c44-61fe6f59330b</onsuccess>
  </stage>
  <stage stageid="7d038089-d0d0-47d6-9567-ff7fbd4e2ad2" name="Anchor2" type="Anchor">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <loginhibit />
    <display x="90" y="345" w="10" h="10" />
    <onsuccess>6a16195e-41c8-4e52-8625-061243db0811</onsuccess>
  </stage>
  <stage stageid="8d301f0a-94c3-4852-a216-f252b27166c3" name="SheetName" type="Data">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <display x="-225" y="120" />
    <datatype>text</datatype>
    <initialvalue />
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="5555a2e6-2d06-4da2-b986-60516c04f8c4" name="[Success] = True" type="Decision">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <loginhibit />
    <display x="-60" y="-15" />
    <decision expression="[Success] = True" />
    <ontrue>2b95b981-f6a3-46d2-ac2f-c3bf37e109aa</ontrue>
    <onfalse>25ddca11-d42c-4ac1-bfeb-590504da586b</onfalse>
  </stage>
  <stage stageid="081c9bf2-4828-47ba-9f88-ee45a75f8735" name="[Success] = True" type="Decision">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <loginhibit />
    <display x="-60" y="105" />
    <decision expression="[Success] = True" />
    <ontrue>3f15a13e-c6d9-4309-b03c-b84634339a44</ontrue>
    <onfalse>d9b92af7-75ca-4170-9a32-2981d266cc24</onfalse>
  </stage>
  <stage stageid="25ddca11-d42c-4ac1-bfeb-590504da586b" name="Set Error Message" type="Calculation">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <loginhibit />
    <display x="30" y="-15" />
    <onsuccess>9708dd42-1db3-4ae3-809d-1513db8538f9</onsuccess>
    <calculation expression="&quot;Error in API Call: &quot;&amp;[Error Message]" stage="Error Message" />
  </stage>
  <stage stageid="d9b92af7-75ca-4170-9a32-2981d266cc24" name="Set Error Message" type="Calculation">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <loginhibit />
    <display x="30" y="105" />
    <onsuccess>5dc509e2-1dea-4ae3-ae96-918a7a64f060</onsuccess>
    <calculation expression="&quot;Error in JSON Conversion: &quot;&amp;[Error Message]" stage="Error Message" />
  </stage>
  <stage stageid="943d0920-2cf6-4da3-9b48-9a5af41f847f" name="[Success] = True" type="Decision">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <loginhibit />
    <display x="-60" y="285" />
    <decision expression="[Success] = True" />
    <ontrue>6a16195e-41c8-4e52-8625-061243db0811</ontrue>
    <onfalse>fc1ca4c2-0045-4d9d-ad88-61abf950a75c</onfalse>
  </stage>
  <stage stageid="fc1ca4c2-0045-4d9d-ad88-61abf950a75c" name="Set Error Message" type="Calculation">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <loginhibit />
    <display x="30" y="285" />
    <onsuccess>de02cbf6-bc09-4036-9c44-61fe6f59330b</onsuccess>
    <calculation expression="&quot;Error in Create Excel: &quot;&amp;[Error Message]" stage="Error Message" />
  </stage>
  <stage stageid="9708dd42-1db3-4ae3-809d-1513db8538f9" name="Anchor3" type="Anchor">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <loginhibit />
    <display x="90" y="-15" w="10" h="10" />
    <onsuccess>5dc509e2-1dea-4ae3-ae96-918a7a64f060</onsuccess>
  </stage>
  <stage stageid="5dc509e2-1dea-4ae3-ae96-918a7a64f060" name="Anchor4" type="Anchor">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <loginhibit />
    <display x="90" y="105" w="10" h="10" />
    <onsuccess>aff1fb43-83dd-411b-895e-121a6e9aaa67</onsuccess>
  </stage>
  <stage stageid="de02cbf6-bc09-4036-9c44-61fe6f59330b" name="Anchor5" type="Anchor">
    <subsheetid>8e5d6e27-2067-4108-a3de-c6d32385476c</subsheetid>
    <loginhibit />
    <display x="90" y="285" w="10" h="10" />
    <onsuccess>7d038089-d0d0-47d6-9567-ff7fbd4e2ad2</onsuccess>
  </stage>
  <stage stageid="8848462a-85fd-4a3a-bc39-15398ec8475f" name="Authentication" type="SubSheetInfo">
    <subsheetid>9cb7bf9b-8ba4-45f2-b334-fc34ba39707a</subsheetid>
    <display x="-195" y="-105" w="150" h="90" />
  </stage>
  <stage stageid="7f4050b6-af0c-44aa-afa5-b7d0fd9f4f1c" name="Start" type="Start">
    <subsheetid>9cb7bf9b-8ba4-45f2-b334-fc34ba39707a</subsheetid>
    <loginhibit />
    <display x="-60" y="-135" />
    <onsuccess>8c424f0b-43e3-49bd-9deb-97c9e5ded003</onsuccess>
  </stage>
  <stage stageid="aace0190-ea26-4a19-9ebe-9048a002664e" name="End" type="End">
    <subsheetid>9cb7bf9b-8ba4-45f2-b334-fc34ba39707a</subsheetid>
    <loginhibit />
    <display x="-60" y="-15" />
    <outputs>
      <output type="text" name="AccessToken" stage="AccessToken" />
    </outputs>
  </stage>
  <stage stageid="baa4ea76-41aa-46e6-8a66-4920d8f05d99" name="Inputs" type="Block">
    <subsheetid>9cb7bf9b-8ba4-45f2-b334-fc34ba39707a</subsheetid>
    <loginhibit />
    <display x="-270" y="-45" w="150" h="195" />
    <font family="Segoe UI" size="10" style="Regular" color="7FB2E5" />
  </stage>
  <stage stageid="0f8f7e0c-8f73-402c-9601-9443b4f6827e" name="Local" type="Block">
    <subsheetid>9cb7bf9b-8ba4-45f2-b334-fc34ba39707a</subsheetid>
    <loginhibit />
    <display x="-270" y="165" w="150" h="150" />
    <font family="Segoe UI" size="10" style="Regular" color="FFFF00" />
  </stage>
  <stage stageid="7066e6a3-cb35-4561-bc57-fb6785819432" name="Outputs" type="Block">
    <subsheetid>9cb7bf9b-8ba4-45f2-b334-fc34ba39707a</subsheetid>
    <loginhibit />
    <display x="-270" y="330" w="150" h="105" />
    <font family="Segoe UI" size="10" style="Regular" color="FF00FF" />
  </stage>
  <stage stageid="79280ca6-6232-452b-b7b2-8810f0ff1547" name="TenantID" type="Data">
    <subsheetid>9cb7bf9b-8ba4-45f2-b334-fc34ba39707a</subsheetid>
    <loginhibit />
    <display x="-195" y="-15" w="120" h="30" />
    <datatype>text</datatype>
    <initialvalue />
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="5e4e3fc9-859a-4eeb-b1bf-3cfedc42bb8a" name="ClientId" type="Data">
    <subsheetid>9cb7bf9b-8ba4-45f2-b334-fc34ba39707a</subsheetid>
    <loginhibit />
    <display x="-195" y="30" w="120" h="30" />
    <datatype>text</datatype>
    <initialvalue />
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="3b5f25be-6542-4ee9-aae5-7e8174743bb3" name="ClientSecret" type="Data">
    <subsheetid>9cb7bf9b-8ba4-45f2-b334-fc34ba39707a</subsheetid>
    <loginhibit />
    <display x="-195" y="75" w="120" h="30" />
    <datatype>password</datatype>
    <initialvalueenc>
    </initialvalueenc>
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="8c424f0b-43e3-49bd-9deb-97c9e5ded003" name="Get Token" type="Code">
    <subsheetid>9cb7bf9b-8ba4-45f2-b334-fc34ba39707a</subsheetid>
    <loginhibit />
    <display x="-60" y="-75" />
    <inputs>
      <input type="text" name="TenantID" expr="[TenantID]" />
      <input type="text" name="ClientId" expr="[ClientId]" />
      <input type="password" name="ClientSecret" expr="[ClientSecret]" />
    </inputs>
    <outputs>
      <output type="text" name="AccessToken" stage="AccessToken" />
    </outputs>
    <onsuccess>aace0190-ea26-4a19-9ebe-9048a002664e</onsuccess>
    <code><![CDATA[
 
        using (var httpClient = new HttpClient())
        {
            var form = new FormUrlEncodedContent(new[]
            {
                new KeyValuePair<string, string>("client_id", ClientId),
                new KeyValuePair<string, string>("client_secret", ClientSecret),
                new KeyValuePair<string, string>("grant_type", "client_credentials"),
                // Scope corretto per Azure Databricks (AAD resource + /.default)
                new KeyValuePair<string, string>("scope", "2ff814a6-3304-4ab8-85cb-cd0e6f879c1d/.default")
            });
 
            var resp = httpClient.PostAsync(tokenUrl, form).GetAwaiter().GetResult();
            string body = resp.Content.ReadAsStringAsync().GetAwaiter().GetResult();
 
            if (!resp.IsSuccessStatusCode)
            {
                throw new Exception($"Token request failed ({resp.StatusCode}): {body}");
            }
 
            var json = JObject.Parse(body);
            string accessToken = json["access_token"]?.ToString();
            if (string.IsNullOrEmpty(accessToken))
                throw new Exception("access_token missing in token response");
 
            AccessToken = accessToken;
}
]]></code>
  </stage>
  <stage stageid="46d709ef-5c75-4394-83b0-78471c8c463a" name="AccessToken" type="Data">
    <subsheetid>9cb7bf9b-8ba4-45f2-b334-fc34ba39707a</subsheetid>
    <display x="-225" y="360" />
    <datatype>text</datatype>
    <initialvalue />
    <alwaysinit />
  </stage>
  <stage stageid="4e76287c-26c7-45de-a165-1f3257d8760f" name="Execute Query - Using Token" type="SubSheetInfo">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <display x="-195" y="-105" w="150" h="90" />
  </stage>
  <stage stageid="2d3a1314-19e9-4398-9259-4ec602b70f7e" name="Start" type="Start">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="-60" y="-135" />
    <inputs>
      <input type="text" name="databricksUrl" stage="databricksUrl" />
      <input type="text" name="warehouseId" stage="warehouseId" />
      <input type="text" name="sqlQuery" stage="sqlQuery" />
      <input type="flag" name="CreateExcel" stage="CreateExcel" />
      <input type="text" name="FilepathXLSX" stage="FilepathXLSX" />
      <input type="text" name="SheetName" stage="SheetName" />
    </inputs>
    <onsuccess>33ac5062-313a-408b-a962-0eb8eab9b6a4</onsuccess>
  </stage>
  <stage stageid="d1c909a0-c003-41a6-8d16-835dcb19fd7c" name="End" type="End">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="-60" y="405" />
    <outputs>
      <output type="flag" name="Success" stage="Success" />
      <output type="text" name="Error Message" stage="Error Message" />
      <output type="collection" name="Report" stage="Report" />
    </outputs>
  </stage>
  <stage stageid="753bbed9-7194-48db-86f7-2047f2dd218f" name="accessToken" type="Data">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <display x="-165" y="195" />
    <datatype>text</datatype>
    <initialvalue />
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="74a6a9eb-ee35-4699-84ad-329239d1058f" name="warehouseId" type="Data">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <display x="-165" y="-15" />
    <datatype>text</datatype>
    <initialvalue />
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="5e43ad48-cc52-41bb-89c4-6596788a19dd" name="sqlQuery" type="Data">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <display x="-225" y="-15" />
    <datatype>text</datatype>
    <initialvalue />
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="d4f9c706-65f0-4c79-8779-a00d9d9529a3" name="Success" type="Data">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <display x="-165" y="360" />
    <datatype>flag</datatype>
    <initialvalue>False</initialvalue>
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="536e4740-8f66-4f28-b651-be23fdef263f" name="Error Message" type="Data">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <display x="-225" y="360" />
    <datatype>text</datatype>
    <initialvalue />
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="4b5e9e32-cc4c-468a-b1d1-b96bdfab941f" name="JSONOutput" type="Data">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <display x="-225" y="195" />
    <datatype>text</datatype>
    <initialvalue />
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="23766df5-bdba-449f-8d36-858278c8d97e" name="Report" type="Collection">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <display x="-225" y="405" />
    <datatype>collection</datatype>
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="767269e4-2267-4297-a3c9-d97409e501de" name="Convert JSON Token" type="Code">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="-60" y="105" />
    <inputs>
      <input type="text" name="json" expr="[JSONOutput]" />
    </inputs>
    <outputs>
      <output type="flag" name="Success" stage="Success" />
      <output type="text" name="ErrorMessage" stage="Error Message" />
      <output type="collection" name="dataTable" stage="Report" />
    </outputs>
    <onsuccess>d88bcda0-42b4-4302-ba8c-e642949c5a69</onsuccess>
    <code><![CDATA[Success = false;
ErrorMessage = "";
dataTable = null;
dataTable = new DataTable();
 
try
{
dataTable = GenerateDataTableFromJson(json);
Success = true;
}
catch (Exception ex)
{
Success = false;
ErrorMessage = ex.Message;
}
 
]]></code>
  </stage>
  <stage stageid="33c5e16f-fa4e-4750-9e61-14e9f79eb243" name="Inputs" type="Block">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="-270" y="-45" w="150" h="195" />
    <font family="Segoe UI" size="10" style="Regular" color="7FB2E5" />
  </stage>
  <stage stageid="ebf2fea7-8b77-44c8-a000-9038213e3e34" name="Local" type="Block">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="-270" y="165" w="150" h="150" />
    <font family="Segoe UI" size="10" style="Regular" color="FFFF00" />
  </stage>
  <stage stageid="deb7307c-8680-4762-9dc1-5b7d5600729f" name="Outputs" type="Block">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="-270" y="330" w="150" h="105" />
    <font family="Segoe UI" size="10" style="Regular" color="FF00FF" />
  </stage>
  <stage stageid="5529a3ca-016c-44d8-94b1-56377f9b40fd" name="FilepathXLSX" type="Data">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <display x="-165" y="75" />
    <datatype>text</datatype>
    <initialvalue />
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="5add693a-51ef-4f02-a9c8-633e927ee473" name="CreateExcel" type="Data">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <display x="-225" y="75" />
    <datatype>flag</datatype>
    <initialvalue>False</initialvalue>
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="61a50860-9a73-4cbd-8307-274af6b1cff2" name="Create Excel Token" type="Code">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="-60" y="285" />
    <inputs>
      <input type="collection" name="DatatableResult" expr="[Report]" />
      <input type="text" name="Filepath" expr="[FilepathXLSX]" />
      <input type="text" name="SheetName" expr="[SheetName]" />
    </inputs>
    <outputs>
      <output type="flag" name="Success" stage="Success" />
      <output type="text" name="ErrorMessage" stage="Error Message" />
    </outputs>
    <onsuccess>d0c941a8-7e1a-4167-b165-ae1bae998acf</onsuccess>
    <code><![CDATA[Success = false;
ErrorMessage = "";
 
try
{
DataTableToExcel exporter = new DataTableToExcel();
exporter.ExportToExcel(DatatableResult, Filepath, SheetName);
Success = true;
}
catch (Exception ex)
{
Success = false;
ErrorMessage = ex.Message;
}]]></code>
  </stage>
  <stage stageid="e7d0172b-74d8-4261-a310-976261f28845" name="[CreateExcel] = True" type="Decision">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="-60" y="225" />
    <decision expression="[CreateExcel] = True" />
    <ontrue>61a50860-9a73-4cbd-8307-274af6b1cff2</ontrue>
    <onfalse>e5242eaf-7df1-445a-be16-359ff2906db9</onfalse>
  </stage>
  <stage stageid="e5242eaf-7df1-445a-be16-359ff2906db9" name="Anchor1" type="Anchor">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="90" y="225" w="10" h="10" />
    <onsuccess>6f7ea0aa-ca84-4bc5-b2cb-b00a3f5a11c1</onsuccess>
  </stage>
  <stage stageid="c5eff911-30f7-4e00-bf78-bd2290970310" name="Anchor2" type="Anchor">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="90" y="405" w="10" h="10" />
    <onsuccess>d1c909a0-c003-41a6-8d16-835dcb19fd7c</onsuccess>
  </stage>
  <stage stageid="d2f2e471-9a3f-4b66-b87a-c3d790bfbcb0" name="SheetName" type="Data">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <display x="-165" y="30" />
    <datatype>text</datatype>
    <initialvalue />
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="ad69bfb0-e52b-47f0-a648-5f1e094fcf37" name="[Success] = True" type="Decision">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="-60" y="45" />
    <decision expression="[Success] = True" />
    <ontrue>767269e4-2267-4297-a3c9-d97409e501de</ontrue>
    <onfalse>c0a9ca49-ff4e-441d-9650-da100bcf6bad</onfalse>
  </stage>
  <stage stageid="d88bcda0-42b4-4302-ba8c-e642949c5a69" name="[Success] = True" type="Decision">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="-60" y="165" />
    <decision expression="[Success] = True" />
    <ontrue>e7d0172b-74d8-4261-a310-976261f28845</ontrue>
    <onfalse>04d9f303-e399-4bb3-93fa-3ce536aa55a1</onfalse>
  </stage>
  <stage stageid="c0a9ca49-ff4e-441d-9650-da100bcf6bad" name="Set Error Message" type="Calculation">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="30" y="45" />
    <onsuccess>0f46bfec-9fc3-4b45-9073-b2a2feebbbe3</onsuccess>
    <calculation expression="&quot;Error in API Call: &quot;&amp;[Error Message]" stage="Error Message" />
  </stage>
  <stage stageid="04d9f303-e399-4bb3-93fa-3ce536aa55a1" name="Set Error Message" type="Calculation">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="30" y="165" />
    <onsuccess>93dfc5a7-0afe-4188-9a40-fb7de4b3b993</onsuccess>
    <calculation expression="&quot;Error in JSON Conversion: &quot;&amp;[Error Message]" stage="Error Message" />
  </stage>
  <stage stageid="d0c941a8-7e1a-4167-b165-ae1bae998acf" name="[Success] = True" type="Decision">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="-60" y="345" />
    <decision expression="[Success] = True" />
    <ontrue>d1c909a0-c003-41a6-8d16-835dcb19fd7c</ontrue>
    <onfalse>33d8e73b-b167-41a9-8606-25057a305ddc</onfalse>
  </stage>
  <stage stageid="33d8e73b-b167-41a9-8606-25057a305ddc" name="Set Error Message" type="Calculation">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="30" y="345" />
    <onsuccess>6f7ea0aa-ca84-4bc5-b2cb-b00a3f5a11c1</onsuccess>
    <calculation expression="&quot;Error in Create Excel: &quot;&amp;[Error Message]" stage="Error Message" />
  </stage>
  <stage stageid="0f46bfec-9fc3-4b45-9073-b2a2feebbbe3" name="Anchor3" type="Anchor">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="90" y="45" w="10" h="10" />
    <onsuccess>93dfc5a7-0afe-4188-9a40-fb7de4b3b993</onsuccess>
  </stage>
  <stage stageid="93dfc5a7-0afe-4188-9a40-fb7de4b3b993" name="Anchor4" type="Anchor">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="90" y="165" w="10" h="10" />
    <onsuccess>e5242eaf-7df1-445a-be16-359ff2906db9</onsuccess>
  </stage>
  <stage stageid="6f7ea0aa-ca84-4bc5-b2cb-b00a3f5a11c1" name="Anchor5" type="Anchor">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="90" y="345" w="10" h="10" />
    <onsuccess>c5eff911-30f7-4e00-bf78-bd2290970310</onsuccess>
  </stage>
  <stage stageid="10d34c6c-df8b-4d15-9a20-6ae62ee2bb83" name="Call API Token" type="Code">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="-60" y="-15" />
    <inputs>
      <input type="text" name="databricksUrl" expr="[databricksUrl]" />
      <input type="text" name="accessToken" expr="[accessToken]" />
      <input type="text" name="warehouseId" expr="[warehouseId]" />
      <input type="text" name="sqlQuery" expr="[sqlQuery]" />
    </inputs>
    <outputs>
      <output type="flag" name="Success" stage="Success" />
      <output type="text" name="ErrorMessage" stage="Error Message" />
      <output type="text" name="JSONOutput" stage="JSONOutput" />
    </outputs>
    <onsuccess>ad69bfb0-e52b-47f0-a648-5f1e094fcf37</onsuccess>
    <code><![CDATA[Success = false;
ErrorMessage = "";
JSONOutput = "";
 
try
{
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {accessToken}");
var payload = new
{
statement = sqlQuery,
warehouse_id = warehouseId,
wait_timeout = "30s"
};
 
var content = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(payload), Encoding.UTF8, "application/json");
var resp = httpClient.PostAsync(databricksUrl, content).GetAwaiter().GetResult();
string body = resp.Content.ReadAsStringAsync().GetAwaiter().GetResult();
 
if (!resp.IsSuccessStatusCode)
{
throw new Exception($"Query failed ({resp.StatusCode}): {body}");
}
else
{
JSONOutput = body;
Success = true;
}
}
 
}
catch (Exception ex)
{
Success = false;
ErrorMessage = ex.ToString();
}
]]></code>
  </stage>
  <stage stageid="cb0efb85-278a-4cf1-a80d-b99a7b2439f8" name="databricksUrl" type="Data">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <display x="-225" y="30" />
    <datatype>text</datatype>
    <initialvalue />
    <private />
    <alwaysinit />
  </stage>
  <stage stageid="33ac5062-313a-408b-a962-0eb8eab9b6a4" name="Authentication" type="SubSheet">
    <subsheetid>fa900c6f-ef74-4b80-a2e5-f70e341de476</subsheetid>
    <loginhibit />
    <display x="-60" y="-75" />
    <outputs>
      <output type="text" name="AccessToken" friendlyname="AccessToken" stage="accessToken" />
    </outputs>
    <onsuccess>10d34c6c-df8b-4d15-9a20-6ae62ee2bb83</onsuccess>
    <processid>9cb7bf9b-8ba4-45f2-b334-fc34ba39707a</processid>
  </stage>
</process>
 
Simone