Rules to set date field value to a calculated value

Forums Classic DFFS Rules to set date field value to a calculated value

Viewing 15 reply threads
  • Author
    Posts
    • #18735
      Charlene
      Participant

      HELP!! I’m trying to set up rules to set a calculated date field value based on the input of an end date but need some help! I know how to calculate the dates in Excel, but don’t know JS well enough to incorporate into SharePoint! Can someone please help me with this? I added a list of dates that are calculated in Excel for reference. Do you also know how to move the tooltips to the left of the field instead of the right?

      End date inputted: 3/31/2018

      Note: All dates below should be on business days.

      PL Date: This should be at least 2 months before End date and on a Thursday = 1/25/2018
      GTM Date: This should be at least 1 month before End date and on a 2nd or 4th Friday = 2/23/2018
      Comm1 Date: This should be the next business day after GTM Date = 2/26/2018
      Comm2 Date: This should be the next business day after Comm1 Date = 2/27/2018

      THANK YOU!

    • #18767
      Alexander Bautz
      Keymaster

      Hi,
      I’ll try to help you out here, but I’m struggling a bit with the logic for the “GMT Date”. Is what determines if it should be the 2 or 4 which of the dates that are nearest to one month from the end date?

      Moving the tooltips should work with this in the custom css:

      .customTooltip{
          float:none!important;
          display:inline;
          margin-right:5px;
      }
    • #18771
      Charlene
      Participant

      Thanks Alexander! Yes, what determines the ‘GTM Date’ is the nearest Friday to to the 1 month before the end date. If that’s too hard to write in, it could be the following 2nd or 4th Friday’s after 1 month before the end date.

      Thank you so much!

    • #18823
      Alexander Bautz
      Keymaster

      Sorry for the delay. I’ve been busy with other support issues during the weekend and will get back to you later this week with the code snippet.

      Best regards,
      Alexander

      • #18837
        Charlene
        Participant

        No problem at all! Thank you so much!

    • #18878
      Alexander Bautz
      Keymaster

      Hi,
      I have finally found time to write up a function for you. I had to do a bit of thinking – I’ll admit that, and I’m not 100% sure this will work in all scenarios so you will have to test it properly.

      Add this code to the Custom JS in DFFS backend:

      function dffs_getDate(arg){
          var neg = arg.offset.months < 0 || arg.offset.days < 0, date = new Date(arg.date.valueOf()), targetMonth = date.getMonth()+arg.offset.months;
          // offset day
          if(arg.offset.days !== 0){
              date.setDate(date.getDate()+arg.offset.days);
          }
          // offset month
          if(arg.offset.months !== 0){
              if(neg){
                  while(date.getMonth() !== targetMonth){
                      date.setDate(date.getDate()-1);
                  }
              }else{
                  while(date.getMonth() !== targetMonth){
                      date.setDate(date.getDate()+1);
                  }
              }  
          }
          // nearest
          if(arg.key === "nearest"){
              while(date.getDay() !== arg.targetDay.day){
                  if(neg){
                      date.setDate(date.getDate()-1);
                  }else{
                      date.setDate(date.getDate()+1);
                  }
              }
          }
          // nth
          if(arg.key === "nth"){
              while(date.getDay() !== arg.targetDay.day){
                  if(neg){
                      date.setDate(date.getDate()-1);
                  }else{
                      date.setDate(date.getDate()+1);
                  }
              }
              var dateIndexObj = getDateIndexArr(new Date(date.valueOf()),arg.targetDay.day), loopTicker = 0;
              while(jQuery.inArray(String(dateIndexObj[date.toLocaleDateString()]),arg.targetDay.index) < 0){
                  loopTicker += 1;
                  if(loopTicker > 1000){
                      alert("Failed to calculate the date");
                      break;
                  }
                  if(date.getDay() !== arg.targetDay.day){
                      date.setDate(date.getDate() - (7 - date.getDay()));
                  }else{
                      date.setDate(date.getDate() - 7);
                  }
              }
          }
          // businessday
          if(arg.key === "businessday"){
              while(date.getDay() === 0 || date.getDay() === 6){
                  if(neg){
                      date.setDate(date.getDate()-1);
                  }else{
                      date.setDate(date.getDate()+1);
                  }
              }
          }
          return date;
      }
      
      function getDateIndexArr(date,targetDay){
          var month = date.getMonth(), dArr = [], dObj = {};
          while(month === date.getMonth()){
              dArr.unshift(new Date(date.valueOf()).toLocaleDateString());
              date.setDate(date.getDate() - 7);
          }
          jQuery.each(dArr,function(i,d){
              dObj[d] = i+1;
          });
          return dObj;
      }

      Then use this format when calling the function:

      // ************ Days are 0-indexed - use these index numbers in "targetDays" ******************
      // 0 = Sunday
      // 1 = Monday
      // 2 = Tuesday
      // 3 = Wednesday
      // 4 = Thursday
      // 5 = Friday
      // 6 = Saturday
      
      var format = spjs.dffs.getRegionalSettings().DateFormat;
      var start = spjs.dffs.strToDateObj("DateColumn1",format);
      
      // PL Date
      var pl_date = dffs_getDate({
          "date":start,
          "key":"nearest",
          "offset":{
              "months":-2,
              "days":0},
          "targetDay":{
              "index":null,
              "day":4
          }
      });
      console.log("pl_date:"+pl_date);
      
      // GTMDate
      var gtm_date = dffs_getDate({
          "date":start,
          "key":"nth",
          "offset":{
              "months":-1,
              "days":0},
          "targetDay":{
              "index":["2","4"],
              "day":5
          }
      });
      console.log("gtm_date:"+gtm_date);
      
      // Comm1 Date
      var comm1_date = dffs_getDate({
          "date":gtm_date,
          "key":"businessday",
          "offset":{
              "months":0,
              "days":1},
          "targetDay":{
              "index":null,
              "day":null
          }
      });
      console.log("comm1_date:"+comm1_date);
      
      // Comm2 Date
      var comm2_date = dffs_getDate({
          "date":comm1_date,
          "key":"businessday",
          "offset":{
              "months":0,
              "days":1},
          "targetDay":{
              "index":null,
              "day":null
          }
      });
      console.log("comm2_date:"+comm2_date);

      Change the name of the date column from “DateColumn1” to whatever your field has as “FieldInternalName”.

      To set the date in a datepicker, use this format:

      setFieldValue("NameOfDateCol",spjs.utility.dateObjToFormattedString(pl_date,"MM/dd/yyyy")

      Let me know how this works out.

      Best regards,
      Alexander

      • #18904
        Charlene
        Participant

        Thank you so much Alexander! I tried including the 1st and 2nd code you provided above in Custom JS and changed the name of the DateColumn1 to my End Date.

        I was getting an error with the setFieldValue code you have above, so I inserted the following code after console.log instead.

        var pl_date2 = spjs.utility.dateObjToFormattedString(pl_date,"MM/dd/yyyy");
        setFieldValue("PLDateColumn",pl_date2);

        The problem I’m seeing is:
        1. The ‘EndDate’ is not being retrieved. It is pulling in today’s date even though I updated the DateColumn1 to the ‘EndDate’. I’d like this function to trigger when the EndDate is not null or updated and when PLDate, GTMDate, Comm1Date, Comm2Date are empty. Is that possible? Do I need to use rules or just include it all in the Custom JS? Perhaps add: if(“start” == “”){setFieldValue…};?

        2. The year represented is 1969 vs 2017. How do I fix this?

        THANK YOU!

        • This reply was modified 6 years, 4 months ago by Charlene.
    • #18912
      Alexander Bautz
      Keymaster

      You can set a rule to trigger on change of the “EndDate” field, and wrap the code in a function so yo can call it from the rule.

      If your “EndDate” isn’t pulled in right you should try running these lines in the console (hit F12 > Console):

      var format = spjs.dffs.getRegionalSettings().DateFormat;
      var start = spjs.dffs.strToDateObj("EndDate",format);
      console.log(start);

      Is the start logged in the console correctly?

      Alexander

      • #18915
        Charlene
        Participant

        Wrapping the code in a function and calling it from the rule worked beautifully!!!!!! THANK YOU SOOOOOOO MUCH!!!

        And thank you so much for your patience with the troubleshooting! I am not very familiar with JavaScript so your notes for the console helped a TON!!

        And one thing I wanted to note was that I ended up creating 2 rules because there are 2 end dates I’m working with. When I tried cloning the 1st rule, the 2nd rule didn’t work, but when I created them as new rules, the 2nd rule started working. I’m not sure if that’s a bug with the cloning feature, but wanted to bring it up in case it is.

        Thanks again, Alexander!!!! Sending you a few beers for your help!!!

    • #18922
      Alexander Bautz
      Keymaster

      I’m glad you got it up and running – and thank you for the beer 🙂

      Have a nice weekend,
      Alexander

    • #20548
      Chris Diltz
      Participant

      I’ve been trying to modify this to calculate a due date in business days, but with no luck. Any suggestions?

      • #20598
        Alexander Bautz
        Keymaster

        Did you look at the “businessday” key? – it is used in the “comm2_date” function call in the code snippet above.

        Alexander

    • #21604
      Charlene
      Participant

      Hi Alexander! I’ve been noticing the script gets hung up when I try to put in a date in 2019. It works when I put a date in 2018 first, and then change the date to 2019. But if I start with 2019, it gets hung up.

      Do you know why that would be and how to fix it?

      Thank you!

      • This reply was modified 5 years, 8 months ago by Charlene.
      • #21607
        Charlene
        Participant

        Sorry Alexander, I made a rookie mistake. The problem I was having was with the rule I set up to run the function. I changed the trigger to “is changed” and everything is working beautifully. Thank you again for your work on this! 🙂

    • #21626
      Alexander Bautz
      Keymaster

      I’m glad it worked out.

      Alexander

    • #29304
      Bryan Waldrop
      Participant

      Hi Alexander!
      What would “add 3 business days to todays date” look like?

      Thanks!

    • #29308
      Alexander Bautz
      Keymaster

      Try it like this:

      var new_date = dffs_getDate({
          "date":new Date(), // = today
          "key":"businessday",
          "offset":{
              "months":0,
              "days":3},
          "targetDay":{
              "index":null,
              "day":null
          }
      });
      console.log(new_date);

      Alexander

    • #29339
      Bryan Waldrop
      Participant

      Thank you! That works perfectly if today is a Monday or Tuesday. Even Wednesday skips Sat and Sun to generate Monday as the new_date. However, if today is a Thursday or Friday then Monday is also selected as new_date instead of Tue/Wed?

    • #29343
      Alexander Bautz
      Keymaster

      Ah – I actually forgot how this was made (based on the original request). The “offset” of three days is actually applied first, and then it finds the first business day after that day.

      I have changed the code and added a new offset parameter “businessdays” – see example below code snippet.

      function dffs_getDate(arg){
          var neg = arg.offset.months < 0 || arg.offset.days < 0, date = new Date(arg.date.valueOf()), targetMonth = date.getMonth()+arg.offset.months;
          // offset days
          if(arg.offset.days !== 0){
              date.setDate(date.getDate()+arg.offset.days);
          }
          // offset businessdays
          if(arg.offset.businessdays !== undefined && arg.offset.businessdays !== 0){
              var bdCount = 0;
              var found = false;
              while (!found) {
                  if(date.getDay() === 0 || date.getDay() === 6){
                      date.setDate(date.getDate()+1);
                  }else{
                      if(bdCount !== arg.offset.businessdays){
                          date.setDate(date.getDate()+1);
                      }else{
                          found = true;
                      }
                      bdCount += 1;
                  }
              }
          }
          // offset months
          if(arg.offset.months !== 0){
              if(neg){
                  while(date.getMonth() !== targetMonth){
                      date.setDate(date.getDate()-1);
                  }
              }else{
                  while(date.getMonth() !== targetMonth){
                      date.setDate(date.getDate()+1);
                  }
              }  
          }
          // nearest
          if(arg.key === "nearest"){
              while(date.getDay() !== arg.targetDay.day){
                  if(neg){
                      date.setDate(date.getDate()-1);
                  }else{
                      date.setDate(date.getDate()+1);
                  }
              }
          }
          // nth
          if(arg.key === "nth"){
              while(date.getDay() !== arg.targetDay.day){
                  if(neg){
                      date.setDate(date.getDate()-1);
                  }else{
                      date.setDate(date.getDate()+1);
                  }
              }
              var dateIndexObj = getDateIndexArr(new Date(date.valueOf()),arg.targetDay.day), loopTicker = 0;
              while(jQuery.inArray(String(dateIndexObj[date.toLocaleDateString()]),arg.targetDay.index) < 0){
                  loopTicker += 1;
                  if(loopTicker > 1000){
                      alert("Failed to calculate the date");
                      break;
                  }
                  if(date.getDay() !== arg.targetDay.day){
                      date.setDate(date.getDate() - (7 - date.getDay()));
                  }else{
                      date.setDate(date.getDate() - 7);
                  }
              }
          }
          // businessday
          if(arg.key === "businessday"){
              while(date.getDay() === 0 || date.getDay() === 6){
                  if(neg){
                      date.setDate(date.getDate()-1);
                  }else{
                      date.setDate(date.getDate()+1);
                  }
              }
          }
          return date;
      }
      
      function getDateIndexArr(date, targetDay) {
          var month = date.getMonth(),
          dArr = [],
          dObj = {};
          while (month === date.getMonth()) {
              dArr.unshift(new Date(date.valueOf()).toLocaleDateString());
              date.setDate(date.getDate() - 7);
          }
          jQuery.each(dArr, function(i, d) {
              dObj[d] = i+1;
          });
          return dObj;
      }

      Use it like this to offset 3 business days:

      var new_date = dffs_getDate({
          "date":new Date(), // = today
          "key":"businessday",
          "offset":{
              "months":0,
              "days":0,
              "businessdays": 3
          },
          "targetDay":{
              "index":null,
              "day":null
          }
      });
      console.log(new_date);
      

      Let me know how this works out.

      Alexander

    • #29358
      Bryan Waldrop
      Participant

      Thank you sir! This works brilliantly and is something I will be able to reuse in many applications. Piggy Bank utilized!

    • #29360
      Alexander Bautz
      Keymaster

      Thanks!
      Alexander

Viewing 15 reply threads
  • You must be logged in to reply to this topic.