I am a newbie with Rest Assured and seek help. I have written code to read values from an excel sheet and pass them as a path params in my Rest Assured tests. And this works as expected. However after I get the json response from the post request I make, I want to update the same excel with values from the response.
The excel has columns called Train number, date of journey and various class codes as other columns like first class code, business class code, standard class code that should show the availabality in them and so on something like this:
Initially:
ServiceName | Date | A0 | A1 | A2 | ...... 45 columns
9008 |2019-07-28| 0 | 0 | 0 |....... 45 columns
After test:
ServiceName | Date | A0 | A1 | A2 | ...... 45 columns
9008 |2019-07-28| 45 | 23 | 64 |....... 45 columns
I have followed apache-poi documentation to read values from excel with supporting methods to read rows, columns and getting cell value. However could not find anything that suggests how to update the same excel with the values from Json response.
These are the test and data provider methods I have come up for reading values from excel
#DataProvider(name="logicalAvProvider")
String [][] getLogicalAv() throws IOException
{
String path = "C:\\Misc\\LogAv.xlsx";
int rownum = XLUtils.getRowCount(path, "LogAv");
int colcount=XLUtils.getCellCount(path, "LogAv",rownum );
String LogAvData[][] = new String[rownum-1][colcount];
for (int i=1; i <rownum; i++ ) {
for (int j=0; j<colcount; j++) {
LogAvData[i-1][j] = XLUtils.getCellData(path, "LogAv", i, j);
//System.out.println("Data is " +LogAvData[i-1][j]);
}
}
return(LogAvData);
}
#Test(dataProvider="logicalAvProvider")
public void LogicalAvailablity(String ServiceName, String Date) throws IOException {
Response res=
given()
//.log().all()
.spec(reqSpec)
.pathParams("service_name", ServiceName, "travel_date", Date)
.when()
.get(EndPoints.LOGICAL_AVAILABILTY)
.then()
.spec(resSpec)
.extract().response();
//.log().body();
}
This is the sort of response we see after doing the post request. I need the number available to be updated under the respective columns in the excel.
[
{
"od_pair": "7015400:8727100",
"buckets": [
{
"bucket": "C00",
"original": 2,
"available": 2
},
{
"bucket": "A01",
"original": 76,
"available": 0
},
{
"bucket": "B01",
"original": 672,
"available": 477
},
{
"bucket": "B03",
"original": 578,
"available": 383
}
]
}
]
An advice on the approach to update the excel sheet with the values. I am not expecting anyone to give me the exact solution of my problem but any advice on the approach or any reference that I can refer to achieve this would be highly appreciated.
Extract the required data from response and then write it to excel sheet.
Using restAssured/JsonPath you can extract data from API response.
Using apachePOI you should be able to write into Excel, refer below link for more details:
https://www.codejava.net/coding/how-to-write-excel-files-in-java-using-apache-poi
Let us know if you run into any issues
Related
I have a Kusto query taken from this example that looks like this:
Resources
| where type =~ 'microsoft.compute/virtualmachines'
| extend vmPowerState = tostring(properties.extended.instanceView.powerState.code)
| summarize count() by vmPowerState
I would like to create an weekly alert that send the result through an e-mail in a CSV file.
The Logic App is organized in 5 steps:
One:
Two:
With
URL: https://management.azure.com/providers/Microsoft.ResourceGraph/resources
Body:
{
"query": "Resources | where type =~ 'microsoft.compute/virtualmachines' | extend vmPowerState = tostring(properties.extended.instanceView.powerState.code) | summarize count() by vmPowerState"
}
Three:
Where I parse the Body and I give an extract of the JSON Schema:
{
"count": 3,
"data": [
{
"count_": 3,
"vmPowerState": "PowerState/stopped"
},
{
"count_": 29,
"vmPowerState": "PowerState/deallocated"
},
{
"count_": 118,
"vmPowerState": "PowerState/running"
}
],
"skip_token": null,
"total_records": 3
}
Here I have a few doubt because I found a guide that says that I should use array formula instead. I'm not very sure about that because I cannot see the details in the example. Anyway this is what I do:
Four:
Five:
Where I create the attachment from the CSV
The e-mail in the end arrives but the attachment is not a CSV, it's a JSON file:
What the hack am I doing wrong?
if you want to use "Create CSV table" with Columns set to "Automatic", do pass the "body" of "parse Json".
you don't need to use the array variable but whatever you use need to return an array like this:
The body of the json parser on your example has many other json nodes enveloping that. You should have the option "data" as there is an array there called "data"
if you want to cut it short, try "data"
you can change to "custom". that would allow you to remove redundant data or format data (like the "PowerState" in "PowerState/stopped"):
you can also add the .csv to the file name:
The above worked for me but it can be enhanced
The suggestoin posted by #BrunoLucasAzure really helped me understand how Logic Apps works.
However I would like to reply to my own question with the right solution: I had to paste a sample of the JSON output pressing on the button Use sample payload to generate schema.
Then follow the workflow and everything will be fine.
The next problem I need to fix is pagination but apparently there is a solution for that too: https://techcommunity.microsoft.com/t5/integrations-on-azure-blog/logic-app-http-pagination-deeper-look-build-custom-paging/ba-p/2907605
We are using Azure application Insights for error logging. I am new to KQL and trying to fetch custom properties from inbuilt "customDimensions" column in the following format,
Value as is from "customDimensions" column
exceptions
| project customDimensions
{
"File Name":"Sample File 1",
"Correlation ID":"e33a8d45-1234-1234-1223-54a6fec30356",
"Error List":"[
{\"Function Name\":\"Sample Function 1\",\"Code\":\"12345\"},
{\"Function Name\":\"Sample-Function-2\",\"Code\":\"12343\"}]"
}
Expected Output
File Name
Correlation ID
Function Name
Code
Sample File 1
e33a8d45-1234-1234-1223-54a6fec30356
Sample Function 1
12345
Sample File 1
e33a8d45-1234-1234-1223-54a6fec30356
Sample-Function-2
12343
How can I achieve the above output using KQL?
Thank You.
This might seem a little bit tricky, but bear with me :-)
Every sub-element extracted from a dynamic element, is dynamic.
parse_json() / todynamic() when given a dynamic argument, returns it, As Is.
So first, we use tostring() and only then we use todynamic() so the string would be parsed as json, to dynamic type.
datatable(ErrorDetails:dynamic)
[
dynamic({
"File Name":"Sample File 1",
"Correlation ID":"e33a8d45-0566-4bf2-94f8-54a6fec29bff",
"Error List":"[{\"Function Name\":\"Sample Function 1\",\"Code\":\"12345\"},{\"Function Name\":\"Sample-Function-2\",\"Code\":\"12343\"}]"
})
]
| mv-expand EL = todynamic(tostring(ErrorDetails["Error List"]))
| project ["File Name"] = ErrorDetails["File Name"], ["Correlation ID"] = ErrorDetails["Correlation ID"], ["Function Name"] = EL["Function Name"], ["Code"] = EL["Code"]
File Name
Correlation ID
Function Name
Code
Sample File 1
e33a8d45-0566-4bf2-94f8-54a6fec29bff
Sample Function 1
12345
Sample File 1
e33a8d45-0566-4bf2-94f8-54a6fec29bff
Sample-Function-2
12343
Fiddle
I have below JSON output from an API, in Office Excel I am importing data via Web from API.
[{
"level": 1,
"children": [{
"level": 2,
"children": [{
"level": 3,
"name": "Chandni Chowk",
"data": ["Data 1", "Data 2"]
}],
"name": "Delhi",
"data": ["Delhi Area"]
}],
"name": "Country",
"data": ["India", "Bangladesh"]
}]
https://learn.microsoft.com/en-us/powerquery-m/quick-tour-of-the-power-query-m-formula-language
I have above document.
let
Source = Json.Document(Web.Contents("MY API URL GOES HERE")),
AsTable = Table.FromRecords(Source)
----
----
in
#"Renamed Column2"
In the power query editor I have this for now.
As a out put in Excel file I need like this.
Country Delhi Chandni Chowk
India Delhi Area Data 1
Bangladesh Data 2
Can I get this data from this JSON or I need to change my JSON output format which matches power query?
Power Query interprets JSON as a hierarchy of records and lists. My goal is to flatten the JSON into a record like this and then convert it into a table:
Country : {"India", "Bangladesh"}
Delhi : {"Delhi Area"}
Chandni Chowk : {"Data 1", "Data 2"}
At any particular level, we can pull the name and data value using Record.FromList:
Record.FromList({CurrentLevel[data]}, {CurrentLevel[name]})
For the first level, this is
Record.FromList({{"India","Bangladesh"}}, {"Country"})
which corresponds to the first field in the goal record.
At any level, we can navigate to the next level like this:
NextLevel = CurrentLevel[children]{0}
Using these to building blocks, we can now write a custom function Expand to flatten the record:
1 | (R as record) as record =>
2 | let
3 | ThisLevel = Record.FromList({R[data]}, {R[name]}),
4 | CombLevel = if Record.HasFields(R, {"children"})
5 | then Record.Combine({ThisLevel, #Expand(R[children]{0})})
6 | else ThisLevel
7 | in
8 | CombLevel
Line 1: The syntax for defining a function. It takes a record R and returns a record after doing some transformations.
Line 3: How to deal with the current level, as mentioned earlier.
Line 4: Check if the record has another level to expand down to.
Line 5: If it does, then Record.Combine the result of the current level with the result of the next level, where the result of the next level is calculated by navigating to the next level and recursively applying the function we're defining. With three levels this looks like:
Record.Combine({Level1, Record.Combine({Level2, Level3})})
Line 6: Recursion stops when there are no more levels to expand. No more combinations, just the last level is returned.
All that's left is to transform it into the shape we want. Here's what my query looks like using the Expand function we just defined:
let
Source = Json.Document( < JSON Source > ),
ExpandRecord = Expand(Source{0}),
ToTable = Table.FromColumns(
Record.FieldValues(ExpandRecord),
Record.FieldNames(ExpandRecord)
)
in
ToTable
This uses Record.FieldValues and Record.FieldName as arguments in Table.FromColumns.
The step after using the Expand custom function looks like this in the query editor if you select the first list cell:
The final result is what you asked for:
I am wondering can a range of values that I want to update to a spreadsheet can be sent in a single batch update together with the spreadsheet properties update? For example (code below) I want make a spreadsheet property update (add worksheet) and then add data to the same, newly added worksheet. How can this be achieved, if it can be done using a single request? (not making 1 request .values().batchUpdate() and 2nd .batchUpdate())
I have the following:
REQUESTS = []
# addSheet request
REQUESTS.append({"addSheet": {"properties": {"title": "MySheet",'sheetId': '0'}}})
# add value request
REQUESTS.append({'range':'MySheet!A1', 'values': list_of_lists, 'majorDimension':'COLUMNS'})
# create a request body
body = {"requests": REQUESTS}
# make update
sheet_service.spreadsheets().batchUpdate(spreadsheetId=sheet_id, body=body).execute()
The code above return the following error:
"Invalid JSON payload received. Unknown name "range" at 'requests[1]': Cannot find field.
Invalid JSON payload received. Unknown name "values" at 'requests[1]': Cannot find field.
Invalid JSON payload received. Unknown name "majorDimension" at 'requests[1]': Cannot find field.". Details: "[{'#type': 'type.googleapis.com/google.rpc.BadRequest', 'fieldViolations': [{'field': 'requests[1]', 'description': 'Invalid JSON payload received. Unknown name "range" at \'requests[1]\': Cannot find field.'}, {'field': 'requests[1]', 'description': 'Invalid JSON payload received. Unknown name "values" at \'requests[1]\': Cannot find field.'}, {'field': 'requests[1]', 'description': 'Invalid JSON payload received. Unknown name "majorDimension" at \'requests[1]\': Cannot find field.'}]}]">
Thanks
I believe your goal as follows.
You want to insert new sheet to the Google Spreadsheet.
You want to add the values to the inserted sheet.
You want to achieve above 2 processes with one API call using the method of batchUpdate in Sheets API.
You want to achieve above using googleapis for python.
Modification points:
In this case, in order to add the values to the inserted sheet, I would like to propose to manually add the sheet ID as the unique value.
I think that your 1st request body can be used. But your 2nd request body cannot be used for the batchUpdate method.
When above points are reflected to your script, it becomes as follows.
Modified script:
spreadsheet_id = '###' # Please set the Spreadsheet ID.
list_of_lists = [['sample value 1', 123, 456], ['sample value 2', 789, 123]] ## Please set your values.
sheet_service = build('sheets', 'v4', credentials=creds)
rows = []
for r in list_of_lists:
col = []
for c in r:
col.append({"userEnteredValue": ({"numberValue": c} if str(c).replace('.', '', 1).isdigit() else {"stringValue": c})})
rows.append({"values": col})
print(rows)
new_sheet_id = 123456
body = {
"requests": [
{
"addSheet": {
"properties": {
"title": "MySheet",
"sheetId": new_sheet_id
}
}
},
{
"updateCells": {
"start": {
"sheetId": new_sheet_id,
"rowIndex": 0,
"columnIndex": 0
},
"rows": rows,
"fields": "userEnteredValue"
}
}
]
}
res = sheet_service.spreadsheets().batchUpdate(spreadsheetId=spreadsheet_id, body=body).execute()
print(res)
In this sample script, 123456 is used as the sheet ID of the inserted sheet. If this value has already been used, please change it.
In this sample script, the string and number types are used as the additional value to the inserted sheet. If you want to use other types, please modify above script for your actual situation.
References:
Method: spreadsheets.batchUpdate
AddSheetRequest
UpdateCellsRequest
I have a simplified test scenario created where I have a spreadsheet with two cells (C2/C3) having an array formula:
{=NaNTest()}
My simplified CustomFunction is as follows:
public class NaNTest : CustomFunctions.Function
{
public NaNTest() : this( "NaNTest" ) { }
public NaNTest( string name ) : base( name, CustomFunctions.Volatility.Invariant, CustomFunctions.ValueType.Variant ) { }
public override void Evaluate( CustomFunctions.IArguments a, CustomFunctions.IValue r )
{
var result = new double[ 1, 2 ];
result[ 0, 0 ] = double.NaN;
result[ 0, 1 ] = 0d;
r.SetArray( result );
}
}
This sets both C2 and C3 to #NUM! when I'd expect only C2 to be. Is there a way to make it correctly* assign C3 to 0?
Thanks in advance.
* I say correctly because we have to implement an Excel add-in that our clients use to author spreadsheets and it provides same 'functionality' that we provide on 'our servers' when we open/process the spreadsheet in our 'SpreadsheetGear calculations' (i.e. the NaNTest() function above). The libraries we use to create the add-in only assign C2 to #NUM! and having the two implementations (client side add-in vs server side SpreadsheetGear) behaving differently makes maintenance/debugging difficult.
This behavior is by design. Note the comment in the documentation for the IValue.SetArray(...) method:
If any of the numbers in the array are not valid numbers, the result
of the custom function will be ValueError.Num.
Since NaN isn't a valid number the entire array will resolve to #NUM! instead. Actually, if you try to set a cell value on its out (outside of a custom function), such as...
worksheet.Cells["A1"].Value = double.NaN;
...you should find that cell evaluates to #NUM! as well. If such cases can occur in your custom function, you'll likely just need to write a check for this condition and respond in whatever manner is required by your application.