I am currently working on a Microsoft Power Virtual Agent (PVA) chatbot that helps users understand complicated documents. Right now I am looking at making a flow that takes a user's zipcode as input and then returns a departments contact information from a Sheet. I am firstly not sure what the best solution is, I am using 'get rows' on a Google Sheet, but I am not sure if I should be using a Sharepoint list instead.
My real issues are the following:
How do I get the right row out based on the zipcode a user provides? So if I give it 2000 as a Zipcode in PVA and turn that into an input for the flow, how does it run through the rows in a sheet and find the right one dynamically, then how do I select that row and turn the other cells that are part of it into variables? I tried to use control loops but could not get that to work right.
I've added a pic here of what I currently have
Try this and see how you go.
I created an Excel document that stores your zip codes. You need to store it in a SharePoint online folder, mine looks like this ...
You'll notice that in Excel Online (hopefully you have this, if not, it's a tenancy thing that needs to be activated) you'll have a tab in the ribbon called Automate ...
In there, create a new script, call it Zip Code Lookup and then paste in this code ...
function main(workbook: ExcelScript.Workbook, zipCodeToFilter: string)
{
let activeSheet = workbook.getActiveWorksheet();
let zipCodeRange = activeSheet.getUsedRange();
let zipCodeValues = zipCodeRange.getValues();
let zipCodeFilter = zipCodeValues.filter(row => {
return row[0].toString() == zipCodeToFilter;
});
let zipCodeResult: ZipCode = null;
if (zipCodeFilter.length == 1) {
zipCodeResult = {
zipCode: zipCodeFilter[0][0].toString(),
phoneNumber: zipCodeFilter[0][1].toString(),
departmenName: zipCodeFilter[0][2].toString(),
website: zipCodeFilter[0][3].toString()
}
}
return zipCodeResult;
}
interface ZipCode {
zipCode: string,
phoneNumber: string,
departmenName: string,
website: string
}
Now in PowerAutomate, you should be able to include an action called Run script which is a part of the Excel Online (Business) group of actions.
Here is an example of what I have configured. Specifically, I'm going to look up zip code 53478 ...
... then when the script runs, you get this output and all of the variables are split out for future use.
So I can set the department name into a new variable if I need to (but you don't because it's already a dynamic property) ...
Related
I'm new here. Thanks in advance for your advice.
I’m working on an app which will ask the user how many items they made.
The user will enter a number. My app should then create that many new records in a table called 'Items_Made'.
E.g. The app asks “How many items did you make?”, the user enters “19”, the app then creates 19 new records in the 'Items_Made' table.
I've managed to pull together some code (shown below) that creates ONE new record, but I would like it to create several. I probably need some kind of loop or 'while' function but am unsure how to do so.
var ceateDatasource = app.datasources.Items_Made.modes.create;
var newItem = ceateDatasource.item;
ceateDatasource.createItem();
This code successfully creates 1 record. I would like it to be able to create several.
Creating a lot of records via client script is not recommended, especially if you loose connection or the app gets closed by mistake. In my opinion, the best way to handle this would be via server script for two things: First, It's more reliable and second, it's faster. As in the example from the official documentation, to create a record you need to do something like this:
// Assume a model called "Fruits" with a string field called "Name".
var newRecord = app.models.Fruits.newRecord();
newRecord.Name = "Kiwi"; // properties/fields can be read and written.
app.saveRecords([newRecord]); // save changes to database.
The example above is a clear example on how to create only one record. To create several records at once, you can use a for statement like this:
function createRecordsInBulk(){
var newRecords = [];
for(var i=0; i<19; i++){
var newRecord = app.models.Fruits.newRecord();
newRecord.Name = "Kiwi " + i;
newRecords.push(newRecord);
}
app.saveRecords(newRecords);
}
In the example above, you initiate newRecords, an empty array that will be responsible for holding all the new records to create at once. Then using a for statement, you generate 19 new records and push them into the newRecords. Finally, once the loop is finished, you save all the records at once by using app.saveRecords and passing the newRecords array as an argument.
Now, all this is happening on the server side. Obviously you need a way to call this from the client side. For that, you need to use the google.script.run method. So from the client side you need to do the following:
google.script.run.withSuccessHandler(function(result) {
app.datasources.Fruits.load();
}).createRecordsInBulk();
All this information is clearly documented on the app maker official documentation site. I strongly suggest you to always check there first as I believe you can get a faster resolution by reading the documentation.
I'd suggest making a dropdown or textbox where the user can select/enter the number of items they want to create and then attach the following code to your 'Create' button:
var createDatasource = app.datasources.Items_Made.modes.create;
var userinput = Number(widget.root.descendants.YourTextboxOrDropdown.value);
for (var i = 0; i <= userinput; i++) {
var newItem = createDatasource.item;
createDatasource.createItem();
}
Simple loop with your user input should get this accomplished.
I have an issue where some of our orders are being imported directly into Netsuite, and there is information from the first line item, that I need to copy into the transaction record (i.e. custom field on sales order)
I want to set this up so that it is automatic, I don't have access to the system that is used to bring the orders into Netsuite, and I only JUST got suitescript access and everything I read about that is way above my head..
I know basic HTML and some of the scripting formulas from Netsuite and that's all.
I was hoping there would be a CUSTOM FIELD FORMULA or some other similar way that I can just easily source the information directly from the first item in the item sublist?
This would be quite trivial to implement using SuiteScript. The example below assumes you want to copy the Memo field (description) from the first line item to the body Memo field. The basic idea would be something like the below (untested code):
function userEventBeforeSubmit(type){
if (type === 'create') {
var record = nlapiGetNewRecord();
var memo = record.getLineItemValue('item', 'memo', 1);
record.setFieldValue('memo', memo);
}
}
If want to accomplish this via custom fields etc. it is possible using "Custom Fields with Values Derived from Summary Search Results".
To do this create a Saved Search as follows:
Type: Transaction
Criteria: [none]
Results: Formula (Text), Summary
Type = Maximum, Formula: DECODE({line}, 1, {memo}, NULL)
Available Filters: Internal ID
Then create a Custom Transaction Body Field as follows:
Type: Free Form Text
Store Value: F
Validation & Filtering > Search: [Saved Search from previous step]
As this is a dynamically calculated field (Store Value = F), it would be available when viewing the record, but not in Saved Searches and lists. To remove this limitation, you can create a Workflow that would copy this field to another one that is stored.
I've recently added Facebook authentication to my site, which results in the user automatically being directed to the Address page once they have authenticated. Those users logging in this way will not be shown the extra questions I had asked them during the normal checkout/registration process ('How did you hear about us ?', etc..).
My question is, how do I add these fields into the Address form and get them to be inserted into the ps_customer table as they would be if a user was registering using the traditional way ? I could add fields to the Address template/controller right now, but they would end up being saved in the ps_address table instead
Any help would be much appreciated,
Thanks
It is possible but will need some work around.
After you added the fields to the address form, you have to overried the Address.php class. Do it as followed.
1) In override/classes folder find the Address.php file, and also open classes/Address.php file .
2) In file classes/Address.php file, find add function which will be as below
/**
* #see ObjectModel::add()
*/
public function add($autodate = true, $null_values = false)
{
if (!parent::add($autodate, $null_values))
return false;
if (Validate::isUnsignedId($this->id_customer))
Customer::resetAddressCache($this->id_customer);
return true;
}
Copy that exact function to override/classess/Address.php file and place it in the class.
3) Just after the below code
if (!parent::add($autodate, $null_values))
return false;
Write down your code to insert the extra fields to another table. Just get the POSTed values and write you won sql query to insert it into customers table or any other tables if you need.
Thank you
I'm trying to retrieve the list of valid Reasons for a WorkItem (MS Agile 5 template), which works correctly for a new work item.
However for editing existing work items, the AllowedValues is always empty, whatever the state.
WorkItem item = GetItem(...)
item.Fields["Reason"].AllowedValues.ToList() // always empty
(ToList is my own extension method).
The problem is, the Visual Studio UI correctly updates the Reasons list when you change the state in the drop down list.
The Reason field also has IsLimitedToAllowedValues=false but when you enter an arbitary value it complains that it's not a valid list item.
We also use MS Agile 5 & the following worked fine on an existing work items named myWorkItem (I tried with User Story & Task):
FieldDefinitionCollection fdc = myWorkItem.Type.FieldDefinitions;
Console.WriteLine(myWorkItem.Type.Name);
foreach (FieldDefinition fd in fdc)
{
if(fd.Name == "Reason")
{
AllowedValuesCollection avc = fd.AllowedValues;
foreach (string allowedValue in avc)
{
Console.WriteLine(allowedValue.ToString());
}
}
}
I am writing an integration piece between Drupal/Ubercart and a in-house admin system.
The customer uses Ubercart products with attributes (e.g. a Plaque, which can contain a name, a company, a registration date and month). When an order is placed, the values entered for the attributes are written to uc_order_products, where the data field contains the actual values entered by the user. As far as I can tell, this is the only place where product attributes values, as entered by an end user to place an order, is stored.
The encoded attribute values uses a format seen all over Drupal tables to encode objects:
a:3:{s:10:"attributes";a:4:{s:26:"Name (to appear on plaque)";a:1:{i:0;s:10:"Some
Namee";}s:7:"Company";a:1:{i:0;s:28:"Some Company Name Goes here_";}s:19:"Certification
Month";a:1:{i:0;s:0:"";}s:18:"Certification Year";a:1:
{i:0;s:4:"2011";}}s:9:"shippable";s:1:"1";s:6:"module";s:10:"uc_product";}
And expanded, it looks like this:
a:3:
{
s:10:"attributes";
a:4:
{
s:26:"Name (to appear on plaque)";
a:1:
{
i:0;
s:10:"Some Namee";
}
s:7:"Company";
a:1:
{
i:0;
s:28:"Some Company Name Goes Herep";
}
s:19:"Certification Month";
a:1:
{
i:0;
s:0:"";
}
s:18:"Certification Year";
a:1:
{
i:0;
s:4:"2011";
}
}
s:9:"shippable";
s:1:"1";
s:6:"module";
s:10:"uc_product";
}
I there a simple way to get to the individual field values within this text using SQL? I can write a SQL function to go look for specifics, but I'd like to know if someone knows of an existing MySQL approach (perhaps within Drupal) which would do this.
Thanks!
That's a serialized array, meaning data that was processed by PHP's serialize() function before Drupal inserted it into the database. Use the opposite function unserialize() to turn that string back into an array.
Don't know if any built-in solution exists, but I ended up writing a SQL Function which takes as parameter text such as Name (to appear on plaque). The function then locates the text and extracts the succeeding { ... } block and from it retrieves the corresponding string value. Rough, but works in this case.
If someone has a better solution, I'd like to hear about it!