function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
morsbornmorsborn 

S Control & View

Hello

Can anyone point me to some code examples that can be put on a button in a view to update a bunch of records? e.g. I want to obtain all open cases, go through them one at at time and, using a formula based on two of the fields, populate a third field. The record should then be saved before moving on to the next one. Is this easy to do?

Thanks in advance.

AkiTAkiT
You can activate the mass action list button, and then write your s-control code for the button - look examples from help & training section. Search for "s-control" and look for the usage examples.

-Aki
werewolfwerewolf
One example can be found here:

http://community.salesforce.com/sforce/board/message?board.id=ajax_toolkit&message.id=6136

Not such a good idea to save records one-by-one though as you mentioned.  That's a very chatty Scontrol and will eat many API queries.  Do all your updates with a single call to update, as this sample does.
AkiTAkiT
Regarding list buttons that execute JavaScript, do you know how to open external site in the iframe with side & tab bar still visible?

E.g. below code looks the id of selected record, and opens external site with ref to this record id. But it seems to open completely new page, no sidebar there anymore.

Code:
{!REQUIRESCRIPT("/soap/ajax/9.0/connection.js")}

// Get the record IDs that were checked
var records = {!GETRECORDIDS( $ObjectType.Version__c )};

// Parameters for integration
var serverurl = "{!$Api.Enterprise_Server_URL_100}";
var sessionid = "{!$Api.Session_ID}";

//Check users selections
if (records[0] == null) {
alert("Please select at least one record.") }
else if (records[1] != null){

alert("Please select only 1 record.")

}
else {

// create a form that is then posted to initiate external web site. 
f = document.createElement("form");
f.action="https://tst.extsite.com/ktoc/configHtml/HtmlServlet";
f.method = "post";
f.name ="6Form";
f.id ="6Form";

// create input line for ext. web site
i = document.createElement("input");
i.name = "CMDLN2";
i.id = "B6CMDLN2";
i.type = "hidden";
i.value = "-baseURL=https://tst.extsite.com/ktoc/camosHtml/ -sfSessionID="+sessionid+" -recordID="+records ";
f.appendChild(i);

// add the form to the document.
document.body.appendChild(f);

// submit the form
document.getElementById("6Form").submit();

}

 

morsbornmorsborn
Thankyou for the pointers. I am still a little stuck though. I have tried using the help but cannot see how to create a button on the case view. I am getting a little lost with it all. Where do I insert the code?

I have altered the code in the example ready for insertion. I am hoping it will do the following:
- Get all case records in the view
- For each one update SLA Hours left by subtracting hours spend so far from the number of available hours.

Here's my code. Any comments even if it is to say it's way off would be very appreciated!

Thanks in advance for your continued support! :)



{!REQUIRESCRIPT("/soap/ajax/10.0/connection.js")}

var records = {!GETRECORDIDS($ObjectType.Case)};
var userId = "{!$User.Id}";
if (records[0] == null)
{
alert("Please select at least one case")
}
else
{
var query = "Select c.CaseNumber, c.Id, c.OwnerId, c.Owner.Name From Case c Where Id In (";
for (var n in records) {
query = query + "'"+records[n]+"'";
if (n!=records.length-1) {
query = query + ",";
}
}
query = query + ")";

var queryResults = sforce.connection.query(query);
var caseDetails = queryResults.getArray('records');

var updateRecords = [];


var caseIter = new sforce.QueryResultIterator(queryResults);
while (caseIter.hasNext()) {
var caseObj = caseIter.next();

// declare two variables to hold the number of hours available to solve the issue (SLA1 - stored as a number) and the number
// of hours spent internally so far (SLA1 - text field so needs converting to number)

var SLA1 = caseObj.SLA_Hours_c;
var SLA2 = parsefloat(caseObj.Total_CHL_Time_in_Hours_c);

if (caseObj.SLA_Hours_c != 0)
    {
    var caseUpdate = new sforce.SObject("Case");
    caseUpdate.Id = caseObj.Id;
    var HoursLeft = SLA1-SLA2;
    caseUpdate.SLA_Time_Left_c = HoursLeft.toString();
    updateRecords.push(caseUpdate);                               
    }

if (updateRecords.length>0)
    {
    alert("SLA time left updated successfully.");
    }

parent.window.location.reload();
}
werewolfwerewolf
I see your problem: you've built an array of updateRecords but you never actually called sforce.connection.update with it.  So the updates aren't being sent.

If you're doing SLA calculations you'd surely have a far easier time of it with an Apex trigger...
morsbornmorsborn
Hi,

I just copied the code from the example you mentioned and tried to alter it to do what I need so being honest I wasn't 100% sure if it was applicable or not. You mention Apex Triggers, please could you expand on why you think they would be more relevant?

Just to recap...

I want to add a button to the case or another relevant view to update a field based on the value in two other fields on all open cases.

I don't know the right way to do this and have struggled with the vast number of options in the help and on these boards to find the right approach. Please could you let me know how you would go about solving this?

Your input is very appreciated!

Thanks
werewolfwerewolf
So yes, if you add a call to sforce.connection.update at the bottom of your Scontrol, like my example did at the bottom with the:

if (updateRecords.length>0) {
sforce.connection.update(updateRecords);
That said, with an Apex trigger there wouldn't have to be a button there.  Apex gets triggered automatically when a Case (or any object) is saved, and so you could create an Apex trigger before insert and before update on Case that calculates these fields and sets them on the case.  There are some good examples of Apex triggers in the Force.com Cookbook.
morsbornmorsborn
Thanks werewolf.

I am interested to know, if the Apex trigger is invoked when the object (case) is saved, does that mean it only works each time the record is updated manually? If a case hasn't been touched for a few hours and my SLA time left field is now two hours out e.g. showing 4 hours left in the view but actually it should be 2 because 2 more hours have passed, how would the update be triggered?
werewolfwerewolf
No, the Apex trigger won't trigger itself -- a user change has to be made.  If you need to do real-time calculations here (like SLA time remaining), have you considered using a formula field?  Provided you're not doing anything too intensive that should work.
morsbornmorsborn
Hi

I came across a code snippet that looks simpler and sounded like exactly what I was trying to do. It's a list button that can be placed on the case list view to execute some javascript. I copied the code from the salesforce slides (https://admin.acrobat.com/_a13852757/buttonsandlinks/
) and tried putting my field names in. I get a range of errors though! I don't seem to be able to get at the field values on the current case. What is the proper syntax to use?  For example, with the case object "c", can I refer to fields like

c.SLA_Hours_c.value ?

I must be missing something very basic and it's driving me mad!

I've tried all sorts of things but it errors every time after it alerts the id. My understanding is that the code should work on any ticked items in the view (I've set it to enable multiple selection).

Can someone help me out with the code? Thanks



{!REQUIRESCRIPT("/soap/ajax/8.0/connection.js")}
var records = {!GETRECORDIDS($ObjectType.Case)};
var newRecords = [];
if (records[0] == null) { alert("Please select at least one row")}
else
{
for (var n in records)

alert(n);

{
var c = new sforce.SObject("Case");
c.id = records[n];
alert(c.id);

var SLA1 = 0;
var SLA2 = 0;

SLA1 = c.SLA_Hours_c.value;
alert(SLA1);

SLA2 = parsefloat(c.Total_CHL_Time_in_Hours_c.value);
alert(SLA2);

if (SLA1 != 0)
    {
    var HoursLeft = SLA1-SLA2;
    c.SLA_Time_Left_c = HoursLeft.toString();                       
    }

newRecords.push(c);
}
result = sforce.connection.update(newRecords);
window.location.reload();
}