Skip to main content
Nintex Community Menu Bar

Sum a repeating section amount, based on the lookup control?

  • May 29, 2018
  • 21 replies
  • 22 views

Forum|alt.badge.img+8

I'm now trying to do basically what was accomplished in this thread below.

 

My problem is I have over 80 choices in the drop down lookup control. I'm trying to find a way to do this without having a calculated value for each and every choice. The only thing I can think of is to parse the XML of the repeater in the workflow and fill the information on the form afterwards. Ideally, I could have it calculated on the form though. Anyone have any ideas?

21 replies

Forum|alt.badge.img+7
  • Nintex Partner
  • May 30, 2018

Hi, 

How do you want to display the result for sum of 80 choices? 

What am meaning you have 80 results to display at least as sum regardless the calculated values for each and every choice.

So it's already complicated.

If you know the set of choices you need to get sum of, it will be easier, otherwise JavaScript will be a better option.

BR,


MegaJerk
Forum|alt.badge.img+14
  • Scholar
  • May 30, 2018

Wait... why would you need a calculated field for every choice? 

Do you have a SharePoint List from where you are generating your choices as shown in the Thread that you linked? 

If so - Do you have a Value column for each of the List Items there? 

If that's the case it's an arbitrary thing to pull that value in using a lookup() function in a formula, resulting in one Calculated Control in your Repeating Section Row just like that example shows. 

However, if you're just using a Choice Control and you have manually entered into it a bunch of choices, I would recommend maybe just throwing them into an actual SharePoint list instead as it's far more flexible. 

If that can't be done, then using a javascript formula inside of a Calculated Control outside of your Repeating Section is the way to go. We can go down that road if needed. 


Forum|alt.badge.img+8
  • Author
  • May 30, 2018

I hope that I don't.

216195_pastedImage_1.png

So with this example, I would ideally be able to show a list that looks like

41030-200 - Food DIET - $2,400(sum of the two rows that have this selected)

41031-200 Snack and Hydration DIET 

etc. 

I want to sum up the values in the Amount field if the Account field is the same selection, and display that on the form.


MegaJerk
Forum|alt.badge.img+14
  • Scholar
  • May 30, 2018

So you'd like to have another Choice Control outside of the Repeating Section that lets you select a G/L Account #, and then if there are any corresponding rows with that same G/L Account # in your Repeating Section, sum their Amounts into a single value? 

Is this correct? 


Forum|alt.badge.img+8
  • Author
  • May 30, 2018

Not exactly. Ideally, selecting a new option in the lookup drop down(Account) would add it to a panel somewhere else and display a running sum of all amounts that are also of that same lookup choice. If possible, it would be better to avoid having to initiate it with a secondary control; such as a choice.


MegaJerk
Forum|alt.badge.img+14
  • Scholar
  • June 4, 2018

Alright. This is a quick and dirty way to maybe accomplish what you'd like. Feel free to edit the answer to your particular desires, or, if you feel that there is something you need further help with, feel free to ask. 

- Form Setup -

There are (3) main controls (excluding the Repeating Section itself), they are as follows

216287_pastedImage_10.png

  1. AccountNumber - Choice Control with a few selections:216282_pastedImage_1.png

    (Easy to copy options:
    10000-200 - Apple
    10001-200 - Apricot
    10002-200 - Avocado
    10003-200 - Banana
    10004-200 - Blueberry
    10005-200 - Cherry
    10006-200 - Coconut) 
  2. CountQuantitiesSingle Line Text Control
    216289_pastedImage_12.png
  3. bulkText - Rich Text Control
    216291_pastedImage_19.png
    For the Default Value of this control, you'll set it to this empty table with labels. 

    <table id="tallyTable" style="width:100%">
      <tbody>
        <tr>
          <th>Account Number</th>
          <th>Instances</th>
          <th>Total Qty</th>
        </tr>   
      </tbody>
    </table>‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍


    Additionally, you should create a new Formatting Rule on the Rich Text Control configured as: 
    216292_pastedImage_20.png

    With the formula code of:

    (function(accountNumbers, countQuantities) {
      var currentStateObject = {};

      /* Number.isNumber polyfill */
      Number.isNaN = Number.isNaN || function(value) {    
          return value !== value;
      };

      accountNumbers.forEach(function(accountNumber, accountIndex) {
        if (!Number.isNaN(accountNumber) && accountNumber) {
          var countQuantity = parseInt(countQuantities[accountIndex]);
          if (Number.isNaN(countQuantity) || countQuantity < 1) {
            countQuantity = 0;
          }

          if (currentStateObject.hasOwnProperty(accountNumber)) {
            currentStateObject[accountNumber].totalQty = currentStateObject[accountNumber].totalQty + countQuantity;
            currentStateObject[accountNumber].totalInstances = currentStateObject[accountNumber].totalInstances += 1;
          } else {
            currentStateObject[accountNumber] = {
              totalQty: countQuantity,
              totalInstances: 1
            };
          }
        }
      });

      var tallyTable = NWF$("#tallyTable");
      tallyTable.find("tr[class]").remove();

      Object.keys(currentStateObject).forEach(function(accountNumber){
        var newTableRow = NWF$("<tr><td></td><td></td><td></td></tr>");
        newTableRow.addClass(accountNumber);
        NWF$(newTableRow.children()[0]).text(accountNumber);
        NWF$(newTableRow.children()[1]).text(currentStateObject[accountNumber].totalInstances);
        NWF$(newTableRow.children()[2]).text(currentStateObject[accountNumber].totalQty);
        tallyTable.find("tbody").append(newTableRow);
      });

      return true;
    }(AccountNumber, CountQuantities))

    /* if the Control represented by 'AccountNumber' is a Lookup Control, you'll need to chagne the passed in arguments to (parseLookup(AccountNumber), CountQuantities) */

    (Please Note: both the {AccountNumber} and {CountQuantites} as shown in the above code (at the bottom), should be replaced by the appropriate NAMED CONTROLS)



- Results -

Once all of the above is in place, it's rather straight forward. 

Selecting an Account Number from the Choice Control will add it to the Display Table along with the Instances (the number of times that particular Account Number has been selected) as well as the current total of all similar Account Numbers. 

When running in Edit Mode it looks like: 

216293_pastedImage_31.png

While in Display / View Only Mode it looks like: 

216294_pastedImage_32.png

Hopefully this accomplishes what you are trying to do. Because this data is being saved to the Item / Form, you can also probably use it in other ways (like in a Workflow using a Query XML action or drawn as a table in SharePoint proper). 



Forum|alt.badge.img+8
  • Author
  • June 5, 2018

Instead of a drop down, I have a lookup control, and instead of quantity(integer) I have amount(currency). 

At first I tried it with these fields. The error I received was "Object doesn't support property or method 'isNaN'". 

Thinking it might be ab issue with the lookup, I added a choice control and used that instead of the lookup and got the same error. This is happening when opening the form, or selecting options in controls. This happens if I type in the name of the field, or select it from the Formula Builder.

So I tried this out on a new form and was getting the same error. Am I supposed to change the variable names throughout the code, or just the last line?

Screenshots below:

216317_pastedImage_1.png

216318_pastedImage_2.png

216319_pastedImage_3.png

(function(accountNumbers, countQuantities) {
  var currentStateObject = {};
  accountNumbers.forEach(function(accountNumber, accountIndex) {
    if (!Number.isNaN(accountNumber) && accountNumber) {
      var countQuantity = parseInt(countQuantities[accountIndex]);
      if (Number.isNaN(countQuantity) || countQuantity < 1) {
        countQuantity = 0;
      }

      if (currentStateObject.hasOwnProperty(accountNumber)) {
        currentStateObject[accountNumber].totalQty = currentStateObject[accountNumber].totalQty + countQuantity;
        currentStateObject[accountNumber].totalInstances = currentStateObject[accountNumber].totalInstances += 1;
      } else {
        currentStateObject[accountNumber] = {
          totalQty: countQuantity,
          totalInstances: 1
        };
      }
    }
  });

  var tallyTable = NWF$("#tallyTable");
  tallyTable.find("tr[class]").remove();

  Object.keys(currentStateObject).forEach(function(accountNumber){
    var newTableRow = NWF$("<tr><td></td><td></td><td></td></tr>");
    newTableRow.addClass(accountNumber);
    NWF$(newTableRow.children()[0]).text(accountNumber);
    NWF$(newTableRow.children()[1]).text(currentStateObject[accountNumber].totalInstances);
    NWF$(newTableRow.children()[2]).text(currentStateObject[accountNumber].totalQty);
    tallyTable.find("tbody").append(newTableRow);
  });

  return true;
}(parseLookup(choice1), parseLookup(txt1)))

216320_pastedImage_4.png

Am I supposed to hand type the names of the controls, or select them from the builder?


MegaJerk
Forum|alt.badge.img+14
  • Scholar
  • June 5, 2018

You should be selecting them from the Named Controls tab of your formula builder. 


Forum|alt.badge.img+8
  • Author
  • June 5, 2018

I must be missing a piece then. All I get is this:

216321_pastedImage_1.png


MegaJerk
Forum|alt.badge.img+14
  • Scholar
  • June 5, 2018

Do you know how to use the Chrome Developer Tools? Could you press F12 and see what error it's throwing (if any) when you load the form up? 

It might be helpful in understanding why this would work for me but not for you. 


MegaJerk
Forum|alt.badge.img+14
  • Scholar
  • June 5, 2018

which browser are you using? 


Forum|alt.badge.img+8
  • Author
  • June 5, 2018

Running in IE11. here's the console:

216322_pastedImage_1.png

In Chrome the only error I get is talking about failing to apply a stylesheet. It still does not populate the text box, but also does not give an error(In Chrome).


MegaJerk
Forum|alt.badge.img+14
  • Scholar
  • June 5, 2018

I didn't realize that Number.isNaN was not available in IE at all. I have updated the code with a polyfill to make it work across all browsers. 

Additionally, for some reason I became really aggressive with the 'parseLookup' functions for the passed arguments. Because the Qty (or dollar value in your case) isn't coming from a lookup, you can simply use the Named Control reference proper. 

I also remove the parseLookup on the 1st passed in argument of AccountName, but you will need to use a parseLookup function in the case of your own form where you are indeed using a Lookup Control. I have added a comment to show this. 



Forum|alt.badge.img+8
  • Author
  • June 5, 2018

It works! This is great. Thank you nmarples‌! I appreciate this so much. 


MegaJerk
Forum|alt.badge.img+14
  • Scholar
  • June 5, 2018

Not a problem. It was a really interesting problem and was one of those strange things that just might come in handy to solve other things! 

Ultimately I'm just glad that it worked! 

Happy Coding! 


Forum|alt.badge.img+8
  • Author
  • June 5, 2018

One last question. Do you have any idea where it's finding 8 line breaks at? The default value of the field is correct, and the code for the rule is copy and pasted plainly. I even took the extra blank lines out of the rule code. 

216330_pastedImage_2.png

216329_pastedImage_1.png


MegaJerk
Forum|alt.badge.img+14
  • Scholar
  • June 5, 2018

I have not ever seen that before. 

Would is just so happen that you have the Rich Text Control actually linked to a SharePoint column? That's the only thing that would immediately come to mind. 

The only information I could find in a quick search is from here (Pitfalls when editing the SharePoint Rich Text using JavaScript – TheSharePoint.nl ) so someone out there is bound to know more. 



Forum|alt.badge.img+8
  • Author
  • October 4, 2018

N M‌ hopefully you'll allow me one more question. This project was put on pause for awhile and I've come back to it now.

The only thing that isn't working 100% is that I'm calculating currency with this and it drops any part of it that is not a whole number. Do you know what's causing that? 


MegaJerk
Forum|alt.badge.img+14
  • Scholar
  • October 8, 2018

Up there in my code you will see the following line: 

var countQuantity = parseInt(countQuantities[accountIndex]);

That is what's forcing everything into an Integer. If you'd like it to be Floating Point, then you can change that to either:

var countQuantity = parseFloat(countQuantities[accountIndex]);

or:

var countQuantity = Number(countQuantities[accountIndex]);

------WARNING------

Because you have now entered the world of Floating Point Math, remember that you now must deal with making sure things are tallied correctly! If you are using this data with the intention of consuming it in an Accounting System, or even if you're using it as some type of Ledger or Record, I would HIGHLY recommend that you spend some time learning about the ins and outs of dealing with Floating Point with Currencies. Additionally there are a few JavaScript libraries which are designed to handle Floating Point math and make it easier on you, but it is always up to you (or me, or whoever is working with this stuff) to make sure that it works and works well, because free JS Libraries aren't liable for our enterprise code happy.png

(ps: I didn't write the above to suggest that you don't know any of this, but I figured the disclaimer was need in the event that anyone else comes here and reads this in the future!)


Forum|alt.badge.img+8
  • Author
  • October 9, 2018

I see what you're talking about... I can tell this is going to be a lot of fun happy.png 

219437_pastedImage_2.png


Forum|alt.badge.img+8
  • Author
  • October 11, 2018

In case someone comes looking for this later on. Here's the final code that deals with the decimal a little bit better.

(function(accountNumbers, countQuantities) {
    var currentStateObject = {}; /* Number.isNumber polyfill */
    Number.isNaN = Number.isNaN || function(value) {
        return value !== value;
    };
    accountNumbers.forEach(function(accountNumber, accountIndex) {
        if (!Number.isNaN(accountNumber) && accountNumber) {
            var countQuantity = parseFloat(countQuantities[accountIndex])*100;
            if (Number.isNaN(countQuantity) || countQuantity < 1) {
                countQuantity = 0;
            }
            if (currentStateObject.hasOwnProperty(accountNumber)) {
                currentStateObject[accountNumber].totalQty = currentStateObject[accountNumber].totalQty + countQuantity;
                currentStateObject[accountNumber].totalInstances = currentStateObject[accountNumber].totalInstances += 1;
            } else {
                currentStateObject[accountNumber] = {
                    totalQty: countQuantity,
                    totalInstances: 1
                };
            }
        }
 
    });
    var tallyTable = NWF$("#tallyTable");
    tallyTable.find("tr[class]").remove();
    Object.keys(currentStateObject).forEach(function(accountNumber) {
        var newTableRow = NWF$("<tr><td></td><td></td><td></td></tr>");
        newTableRow.addClass(accountNumber);
        NWF$(newTableRow.children()[0]).text(accountNumber);
        NWF$(newTableRow.children()[1]).text(currentStateObject[accountNumber].totalInstances);
        NWF$(newTableRow.children()[2]).text(currentStateObject[accountNumber].totalQty/100);
        tallyTable.find("tbody").append(newTableRow);
    });
    return true;
}(parseLookup(choice1), txt1))‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍