Using SharePoint Designer Loops to Update a field in a list when the field in another list is updated - loops

I've had a couple of attempts at this, but can only get one record to update. Hopefully someone can shed some light on what's I'm doing wrong, assuming this is possible.
I have a list of Employees (List A), within that list I have a field to flag when they leave.
The second list (List B) is a list of activities. I need to be able to filter this list to exclude everyone who's left, or no longer active. I've added an equivalent Yes/No field to this list.
What I'm trying to do is update the Inactive field in List B for in every record for the employee in List A that the field has changed in.
My Lists before and after look like this
My Basic Workflow Loop looks like this
List A = Current List
List B = Leave Requests
I can break down all of the selections above if that would help someone to help me on this.
Thanks

This can be done with a combination of the REST API and a workflow. Being a complete noobie to Sharepoint, this took me a while to figure out, but hopefully this step by step workflow example will help someone else out there.
Firstly, I primarily used these two blogs to come up with my solution:
Wonder Laura - Loop through multiple Sharepoint items
Kemanth Kumar - Loop Through SharePoint Custom List Items
Final Workflow
Step 1: Create your two lists in Sharepoint. In my case, List A is call StaffList which is a list of all staff members and List B is called LeaveRequests.
Viewing the logs:
You will notice that I have written to the log history throughout the script. To see these logs go to the List A page, click on the staff member you will be changing and the workflow icon lights up in the ribbon at the top. Click on it and all your workflows that have run or are running for that particular staff member will be listed.
API Results
We will be putting a call through to the API and can be annoying at times not seeing what the API returns. See the end of this post to see how to view the API results easily view email.
Step 2: Open Sharepoint designer, click on "Workflows" in the left panel and "List Workflow" should popup in the top ribbon. Click on "List Workflow" and select List A (StaffList) which you created. This will be the list that will be manually updated by a user and will run the workflow. Type a name and description in the box that pops up and Platform type needs to be Sharepoint 2013 Workflow.
You will need to make this workflow run automatically, so save the Workflow then click on Workflow settings in the top ribbon and under Start Options, select the workflow to start Automatically when an item is changed.
Step 3: Showing Start Time using webserver time.
Create a Stage from the ribbon and name it Start Time.
From the Action ribbon click Set a Workflow Variable. Click on workflow variable and create a new string variable called StartUrl. Set the value to your Sharepoint or website address in the string builder.
Select Build Dictionary from the action ribbon. Click on “this” and a box will popup. Create two items in there, one named “Accept” and the other “Content-Type” and both type String an Value will be application/json;odata=verbose. Then output to a new dictionary variable called requestHeaders.
Now you will call a HTTP web service from the actions ribbon. Click on “this” and Enter the first Variable in the URL box. DON’T type in the variable as it won’t work do a Lookup by clicking Add or Change Lookup. A box will pop up, select Workflow Variables and Parameters from the Date source and variable StartUrl from Field from Source. Use method GET click Ok. Set the response content to a dictionary variable called responseContent, response headers to dictionary variable called responseHeaders and response status code to string variable responseCode. Then edit the call properties by click on the right dropdown arrow and click properties. A box will pop up, set request headers to variable requestHeaders.
Now you will need to get the response from the call by using Get Item from Dictionary from actions ribbon. The item path should be set to Date/(0) and dictionary should be responseHeaders (usually this would be responseContent, but the Date of the server sits in the Headers). Output to String variable called StartDate. For more detail on this, go tothis helpful link. Please note this comes through in GMT time. If anyone has ideas on converting to this to a more readable date format, let me know.
Now you can Log the Start Date. Select log to history from the action ribbon and click on message and type Started: and now you will have to put in the variable. DON’T type in the variable as it won’t work do a Lookup by clicking Add or Change Lookup. A box will pop up, select Workflow Variables and Parameters from the Date source and variable StartDate from Field from Source.
Step 4: Create a stage that will get a list of records that need to be updated from the LeaveRequests list (List B). Point the Start Time stage to this new stage by inserting a “go to stage” action in the Transition to stage area in the Start Time Stage.
I have used the user as a common field between both lists. The aim is update a column called StaffListInactive with either yes or no. These values are actually taken from a field in List A.
Lets start off with getting the ID of the staff member in List A that is being changed. Set a workflow variable of type Integer called StaffListID. Do a lookup for the value with data source of current list, field from source in my case will be the employee name and return field as User Id (as Integer). Field will be Employee Name, value will be a lookup of current item, Employee Name and returned as User Id Number.
Now set another workflow variable type string which will be a REST API called RestUrl. A lot of magic happens in this url including getting the list GUID, selecting the fields from the list you want to return, filtering only results we need and increasing the number of results that are returned. Sharepoint’s default is 100 records.
The format of this url for getting items from a list is as follows for your BASE sharepoint site:
http://yoursharepointid.sharepoint.com/_api/web/lists/getbyid(guid‘yourlistguid’)/Items
For a link with additional queries/filters:
http://yoursharepointid.sharepoint.com/_api/web/lists/getbyid(guid’yourlistguid’)/Items?$select=ColumnName,Column2Name&$filter=ColumnName eq ‘content’&$top=9999
To get the GUID, in Sharepoint designer 2013, click “Lists and Libraries” in the left panel, select List B (LeaveRequests). You will then see the List ID. Insert this into the GUID area in between the ‘ and ’.
If your column name has a space, you will need to insert x0020 in place of the space. So mine looks like this Employee_x0020_Name. Also another point to note is in order to get the Employee ID, you will need to include the Id at the end of the Column Name: Employee_x0020_NameId. For filtering this column needs to be Employee_x0020_Name/Id.
So Finally my url looks like this:
http://****.sharepoint.com/_api/web/lists/getbyid(guid’***********************’)/Items?$select=ID,StaffListInactive, Employee_x0020_NameId &$filter= Employee_x0020_Name/Id eq ‘[%Variable: StaffListID%]’&$top=9999
Remember to do a lookup when inserting the variable.
Now you will need to build a dictionary the same as you did in Step 3 above. You could copy the actions and then reassign new variables (although not essential from this workflow). The only variable you will need to change is the URL variable in the Web service call to RestUrl which was created above. If you copy across the build dictionary action, you will need to add the Accept and Content-Type items to it again.
For the get Item from Dictionary action, your path for this will be d/results and your dictionary will now be responseContent and output this to dictionary variable called List.
Step 5: Now we count the number of results pulled from the API and run them through a loop which will update each record.
Create another Stage Cclled Update Inactive Status.
Add “Count Items from Dictionary” action and set dictionary to List Variable and output a new integer variable called ItemCount.
Set an integer variable called index with value 0.
From the loop ribbon insert a loop with a condition. Update the values so that they read variable index is less than variable ItemCount.
In the loop you can Log which loop is running by adding a Log action and calling it Loop Number: Variable Index.
Now this next part is not necessary to include but I feel it’s good to have this check to see that the user being updated is actually the user that you want to be updated. IE, we compare the ID’s of the users in both lists.
Add a Get Item from Dictionary action with the path being d/results([%Variable:index%])/Employee_x0020_NameId. Remember to do a lookup on the variable. The dictionary will be responseContent and the output variable we will call EmployeeID type integer.
Now we add an “If any value equals value” from the Condition ribbon and set the first value to the following: Data Source is Current list, field from source is Employee Name, Field is employee name and value is a lookup of Data source is Current Item, Field from source is Employee Name and return User Id Number.
For the second value in the If statement select Workflow Lookup for User from the list, then click Add and when the box pops up data source will be Workflow Variables and Parameters and field from source will be Variable EmployeeID.
Now we need to update the record by getting the value from List A (StaffList) and setting it in List B (LeaveRequests).
Add “Update List Item” from the actions ribbon and click on this list and choose List B (LeaveRequests) from the List dropdown. Click the add button and “Set this field” to the column you want to change (mine is StaffListInactive) and click on the lookup for “To this value”. When the box pops up date source is current list, field from source is Inactive (this is the field you are updating from is List A), Field is Inactive and value is a lookup of current item and inactive.
Once that is done you will need to update the field and values on the “Update List Item” window. Set the Field to ID and the value is a lookup of workflow variable and EmployeeID.
Log that the record has been update.
Now we need to add 1 to the index variable and set it. This sits outside of the if statement but still within the loop.
Add a “Do Calculation” action and set this to Variable Index plus 1. Output this to number variable IndexPlusOne.
Now set Variable index to variable IndexPlusOne.
Step 6: Log the finished time.
This is identical to the Start Time Stage. So copy the start time stage and paste it at the bottom of your work flow and remember to make sure all your stages are linked. Update the details as you see fit.
In conclusion when you update details on List A, List B will now update the selected field to match the selected field in List A based on the staff member that has been changed.
API Results Cont…
This might be old hat to a lot of people but came in very useful for error testing.
After any of your web service calls add a Send to Email Action. Select your email in the to field and give it a subject. In the body of the email add in the responseHeaders and responseContent variables. Each time your workflow runs, you will be emailed. The email comes through faster than what the records update in the workflow log, so was quicker for me to troubleshoot.

Related

Number of fields

I am new in salesforce and I have a question. I am creating a new reporty type using opportunites and when I was in field layout properties I noticed there were total 40 fields for opporutiy object. I didnt had another object relation with opportunity just simple opportunity. But when I went to opportunity in in object manager there were only 29 items listed in fields and realtionship. Why are there 11 more fields in opportunity in reprot type then in fields and realtuionship
I was expeting the same number of fields in object manager and in report type but report type had more fields even when no object was linked with it
There's a number of fields that exist in the table but aren't visible in setup because you can't modify them, can't change user's right to see/edit them. It's bit like https://help.salesforce.com/s/articleView?id=sf.dev_objectfields.htm&type=5 but it doesn't mention CreatedDate, LastmodifiedDate, SystemModStamp... and on Opportunity there are more.
https://developer.salesforce.com/docs/atlas.en-us.238.0.object_reference.meta/object_reference/sforce_api_objects_opportunity.htm may be a good start but if you truly want everything - run a "describe" operation in Apex or maybe REST API (https://workbench.developerforce.com/ -> utilities -> rest explorer for example)

Google Sheets: Trying to get values for Data in a column and row

Not sure I was able to explain myself too well in the title so here it goes:
I have been trying to figure this one out using the Filter function, but I am unable to make it work, and I am sure there must be an easy way to do it. The idea is that I have a column with the names of the members of a team, and each team member needs to perform a number of actions in a set of tasks. I am counting the amount of actions performed by each team member on each task, and trying to filter those by team member and by task.
So it goes like this: I have a list of names in column B. The number of actions in column C and the task would be selected from a dropdown menu done with 'Data validation'. When I select the task from my drop down menu, the number of actions would change to reflect the actions performed per agent on the selected task.
I added an example too. In the example I filtered the data in sheet 'Data' by names, but I don't know how to add a criteria that would also filter by the tasks on row 1 in the sheet 'Data', or if it is even possible.
Example: https://docs.google.com/spreadsheets/d/1PcdwNHDagfSmtF2Hl27YnrsAsPsF3A5OLuo2YcqGFdk/edit#gid=0
Thanks!
try:
=ARRAYFORMULA(IFNA(VLOOKUP(B2:B&C1,
SPLIT(FLATTEN(Data!A2:A&Data!B1:E1&"×"&Data!B2:E), "×"), 2, 0)))

Query of Arrays in Salesforce

I need to do 1 of two things (I believe):
1- Get a Custom Object ID so I can query it directly
2- Get a list of values of a specific field within the Object entries.
Ultimate End goal:
Add and modify rows in my custom object via external API. However to do this I need to check and make sure my new entry/row does not already exist.
What I have:
I have a custom object (called Customer_Arrays__c). It is a table that I can add new rows to (I will call entrys). Each entry has 6 or 7 fields. 1 of these fields is called (external_ID__c). This is the field I utilize to match to new incoming data to see if the entry already exists, or if it needs to add a new row to my table. This Customer_Arrays__c is a child to my opportunity I believe – it is part of every opportunity and each line item I add has a field defaulted to the opportunity.
Help I need:
1- How do I query the value of my Cutomer_Arrays__c based upon an opportunity ID?
2- How do I query a list of values in my (external_ID__c) based upon an opportunity ID?
Thanks for your help! I have read half a dozen+ posts on similar topics and am missing something. Examples of some Past try's that failed:
Select external_ID__c,FROM Custom_Arrays__c WHERE Opportunity='00...'
Select Id (Select ID, Custom_Arrays__c from Custom_Arrays__c) from Opportunity where id ='00...'
List FROM Custom_Arrays__c WHERE Opportunity='00...'
Select Id, external_ID__c, (Select external_ID__c FROM Custom_Arrays__c) WHERE Opportunity__c='00...'
Thanks again!
Only you know how did you name the lookup field (foreign key) from arrays to Opportunity. You'll need to check in setup, next to where external_ID__c is. Since it's a custom field (gets __c at the end), my guess is you went with default.
Try
SELECT Id, Name, External_Id__c
FROM Customer_Arrays__c
WHERE Opportunity__c = '006...'
Thank you eyescream, that got me almost all the way there. Turns out I also needed a __r for the parent child relationship.
Here is a snip out of my final code that works - I think it covers everything:
SELECT Field1__c, Opportunity__r.Id, Opportunity__r.Opportunity__c,
FROM Customer_Arrays__c
WHERE Opportunity__r.Id = '006...'.
Thank you so very much!!!

How do I set a conditional for a checkbox in an access report

so basically I am making a student database that contains student grades, I have a query that gives me a list of what classes a specific student has taken that are part of their major.
This is what the query returns:
Query result
So what I want to do is create a report that has a section like this where it lists all possible classes they can taken per that major:
Report
and I want to have a checkbox next to each class and have the box be checked off if they have taken the class, if they have not I want the box to be empty, so I don't necessarily need anything on the report like grades etc. I just want it checked off if they have taken that specific class . How can I go about this, lost on this part.
Although more information may be required to answer your question correctly, I'll give this a shot:
Assuming your the check box in question is called "Check1" and the table in question is called "Table1" and the field is called "Test" and the Report you mentioned is a form called "Report"... AND its only on the table when it has been completed.
Something to the effect of an "On Load" command into the form like:
If Not IsNull(DLookup("Class_UID", "Table1", "Class_UID = 'INF-202'")) Then
Forms("Report").Check1.Value = 1
End If
Of course, this would need to be added for each unique Class_UID
It's a simplistic way to do it, but far from the only option.

How to send an Email notification by day end using Rules with all the nodes published that day?

I am trying to achieve email notification . The condition is , it should go by end of the day with the current day published content list.
For the same I have tried couple of things using Rules, but stuck in between.
Any help?
I tried using rules, and I created a rule like so:
Events:
After updating existing content of type(content type name)
Cron maintenance tasks are performed
Condition: Data to compare: [node:field-img-status], Data value: Approve
When I am trying to add second condition to check if the node is published within 24hrs, I am unable to achieve it. When I add strtotime("-1 day"), I get an error like:
Wrong date format. Specify the date in the format 2017-05-10 08:17:18.
I tried date('Y-m-d h:i:s',strtotime("-1 day")) but I did not succeed.
Now I am trying one more method to achieve it using Views Rules which is suggested in this answer to the question about 'How to create a Drupal rule to check (on cron) a date field and if passed set field "status" to "ended"?'.
Below is a blueprint of how I'd get this to work ...
Step 1: Create a single eMail for each node that was published
Create a view (using Views) of all the nodes that were published the last 24 hours. Make sure to include a column in that view for the various data you want to be included about each node in your eMail later on.
Use Rules to create a rule with a Rules Action that consists of a "Rules Loop", in which its "list items" are actually the list of nodes that you want to be included in your eMail later on. To create this Rules Loop, use the Views Rules combined with a Views display type of "Views Rules", for the view that you created. Refer to my answer to "How to pass arguments to a view from Rules?" for way more details on how to use the Views Rules module.
For each list item in the Rules Loop of the previous step, you have access to all data for each column in the View you created. By using these data you could add an additional Rules Action (within the same Rules Loop) to send an appropriate eMail about the node being processed.
Step 2: Group all eMails in a single eMail
Obviously, the previous step creates a single eMail for each node that was published in the last 24 hours. If you only have a few nodes that may not be a real issue to worry about. But if you have dozens (or more?) of such nodes then you might want to consider consolidating all such eMails in a single eMail, which contains (in its eMail body) the complete list of nodes.
A possible solution to implement such consolidation, is similar to what is shown in the Rules example included in my answer to "How to concatenate all token values of a list in a single field within a Rules loop?". In your case, you could make it work like so:
Add some new Rules variable that will be used later on as part of the eMail body, before the start of your loop. Say you name the variable nodes_list_var_for_email_body.
Within your loop, for each iteration, prepend or append the value for each "list item" to that variable nodes_list_var_for_email_body.
Move the Rules Action to send an eMail outside your loop, and after the loop completed. And finetune the details (configuration) of your (new) "send an eMail" Rules Action. When doing so, you'll be able to select the token for nodes_list_var_for_email_body to include anywhere in your eMail body.
Step 3: Schedule the daily execution of your rule
Use the Rules Once per Day to schedule the daily execution of your rule. Refer to my answer to "How to limit the execution of a rule for sending an email to only run once in a day?" for way more details about this module.
Voilà, that's it ...
This is how I would achieve this:
Make some view which would list all nodes created today.
Make some end-point (from my module, check out: https://api.drupal.org/api/drupal/modules%21system%21system.api.php/function/hook_menu/7.x)
It would call this view, and grab that node list (i.e. with views_get_view_result : https://api.drupal.org/api/views/views.module/function/views_get_view_result/7.x-3.x ), loop through the list, compose the email and send it.
Then I would set cron job to call that end-point at end of every day.

Resources