Calculate product of a field across repeating elements in InfoPath - infopath

It is easy to calculate a sum, an average or a maximum accross set of fields using built-in xpath functions.
But is it possible to calculate a product?
Assuming I have repeating elements like
<my:table>
<my:row>
<my:value>10</my:value>
</my:row>
<my:row>
<my:value>20</my:value>
</my:row>
<my:row>
<my:value>30</my:value>
<my:row>
</my:table>
(the number of my:rows may vary).
i need to have a formula multiplying all my:values: 10*20*30 (and working with any number of rows).
Any ideas?
Please do not suggest code solutions, I need this for a restricted form.

Using conditional hack described here, I finally assembled the solution.
Inside my:row, create a running product field my:valueCumul, populated using a formula to refer to previous row, and leveraging the conditional hack to override NaN for the first row:
../my:value *
concat(
(count(../preceding-sibling::my:row[1]) = 0) * 1,
substring(../preceding-sibling::my:row[1]/my:valueCumul, 1, (count(../preceding-sibling::my:row[1]) = 1) * string-length(../preceding-sibling::my:row[1]/my:valueCumul))
)
Outside the table you can easily refer to my:valueCumul in the last row to get total product:
../my:row[count(../my:row)]/my:valueCumul
The nice features of this solution are:
Works in a browser form in any sharepoint environment
Is not impacted by "16 calculations" threshold
The formula is robust to row removal and shifts

You can't with the built in functions in InfoPath.
However, don't write off a code solution so fast. If you only access data elements in the form itself (nothing EXTERNAL) then you can leave the form as restricted security and the code will run with no problems - the user doesn't know the difference.
It is fairly trivial to attach to the right event, grab the nodes, and loop through them while multiplying. You don't even have to use managed code - use one of the script options. Comment back (or update your original post) if you run into any troubles and we can help resolve them.

Related

MS Project: How to set daily actual work for a task using a JavaScript Add-In?

I want to synchronize data for actual work from a web-based application of my company with MS Project. I am currently developing an Add-In with JavaScript in order to achieve this:
The red circle in my screenshot shows the data that I want to set programmatically. However, I have no idea how to achieve this.
I understand that I can get Task GUIDs and then set task fields using the task GUID and the field ID. This way I can save the cumulative actual work, but not per day like in my screenshot.
The API Docs on the MS Office Website are rather hard to read and navigate. Any help would be apprechiated!
Let's first separate the language from the operation.
Operationally, based on your circle, you want to set work for a task to happen on individual days? This is done using timeScaleData, see https://learn.microsoft.com/en-us/previous-versions/office/developer/office-2003/aa206255(v=office.11) . When I did something similar (in VBA), I had to (1) get an array of time scale values, then (2) walk/iterate through that array and set work to those days:
set timeScaleValsArry = myTask.Assignments(1).TimeScaleData(startDay, endDay, pjAssignmentTimeScaledWork, daily)
for a = 1 to timeScaleValsArry.Count
timeScaleValsArry[a].value = hoursToWorkThatDay
next
Breaking down the elements above:
myTask is the task (of type task) I want to manipulate.
Assignments is an array representing each resource assigned to the task; for my purposes, I only ever had 1 resource assigned, hence the index of (1).
TimeScaleData is the function that returns the the array starting on the day startDay (whatever you want that to be), endDay, pjAssignmentTimeScaledWork which tells this function what data we want to work with (being work, but there are alternates ), and daily which is the frequency you want to work with (for instance you can go down to minutes, or up to years).
Then the returned array timeScaleValsArry is walked, and inside the loop the daily assignment for each value is manipulated. You'd need to customize this part to meet your needs; alternatively, you don't even need to loop if you always had three days: just hard code the array indices.
As far as language, clearly this is do-able in VBA. Doing this in C# as a VSTO addin has very similar syntax. I'd presume for JavaScript (what are you using, ScriptLab?) would also have similar syntax.

Graphite Percentage Calculation with groupby/Wildcards for alerting Target Function

I am trying to create a seyren alert for my page render metric stored in graphite.
My render stats are collected by ststsD and stored in graphite. The structure is following:
stats.counters.renderCompleted.display.<country>.<placement_id>.<page_version>.count
e.g.
stats.counters.renderCompleted.display.US.123456.v1_1_03.count
stats.counters.renderCompleted.display.US.123456.v1_1_09.count
stats.counters.renderCompleted.display.US.654321.v2_1_05.count
stats.counters.renderCompleted.display.US.654321.v2_1_07.count
stats.counters.renderCompleted.display.UK.123456.v1_1_09.count
...
...
I want to create a seyren alert with graphite function whenever the current render count for ANY PLACEMENT ANY VERSION (e.g. group by placement_id, page_version) falls below certain % of its (for that placement's and version's) previous day average.
I did search graphite functions but it's bit confusing probably because I don't have background in time-series data processing. Will truly appreciate any help. I tried with many combinations including the following, but not able to get it correct...
asPercent(sumSeriesWithWildCards(movingAverage(scaleToSeconds(
stats.counters.renderCompleted.display.US.*.*.count, 1),'10min'), 6),
sumSeriesWithWildCards(movingAverage(scaleToSeconds(timeShift(
stats.counters.renderCompleted.display.US.*.*.count, '1d'), 1), '10min'), 6))
Please note, I want to create only one alert (hence using WildCard function like sumSeriesWithWildCards) which should serve the purpose, not multiple alerts for individual placements and versions and we keep on adding these.
Thanks in advance.

Is it possible to filter the list of fields when outputting a Full Dataset?

I have a DataTable that I'm passing to a FlexCel report. It contains a variable number of columns, so I'm using the Full Dataset feature (e.g. <#table_name.*>).
However, only a subset of the fields are dynamically generated (I have a variable number of attachments). The column name for each attachment field starts with a common word (e.g. "Attachment0", "Attachment1", etc).
What I would like to do is output the known finite set of fields and then the variable number of attachments. It would be nice if I could write something like <#table_name.Attachment*> (and <#table_name.Attachment**>). Is there any way in FlexCel Reports I can achieve the same result?
A side benefit to such a solution means that I could keep the formatting for the known/finite set of fields.
Update
I added place holder columns to the document, each with a <#delete column> tag, so that the un-wanted columns/data are removed.
Although this works, it's not ideal. For example, if I want to see how the columns fit in the page width (in print preview), then I need to hide the columns. Then I have to remember to un-hide them again, so other developers can see/understand my handy work.
It would be much more straight forward if I could filter the fields before they're output to the document.
I realised there's an alternate way around this problem. I broke up the data into two sets of data - <#table_name.*> and <#table_name_attachments.*>.
The fixed set of fields are in the first table and the variable set of fields is in the second table (all the "Attachment*" fields). When the report is run, I place them next to each other (in the same order) in the same worksheet. This means I have two table ranges - "_table_name_" and "_table_name_attachments_" on the one sheet.
Now I'm able to run my print preview without hiding/re-showing the columns-to-be-deleted. I've also eliminated human error - it was all to easy to accidentally set the wrong number of padded/delete columns.

"Calculated columns cannot contain volatile functions like Today and Me" error message on Sharepoint

I try to add a new calculated column to sharepoint list that will show elapsed day. I enter name and write a formula like;
=ABS(ROUND(Today-Created;0))
The data type returned from this formula is: Single line of text
When I want to save I get an error like
Calculated columns cannot contain volatile functions like Today and
Me.
Calculated Column Values Only Recalculate As Needed
The values in SharePoint columns--even in calculated columns--are stored in SharePoint's underlying SQL Server database.
The calculations in calculated columns are not performed upon page load; rather, they are recalculated only whenever an item is changed (in which case the formula is recalculated just for that specific item), or whenever the column formula is changed (in which case the formula is recalculated for all items).
(As a side note, this is the reason why in SharePoint 2010 you cannot create or change a calculated column on a list that has more than the list view threshold of 5000 items; it would require a mass update of values in all those items, which could impact database performance.)
Thus, in order for calculated columns to accurately store "volatile" values like "Me" and "Today", SharePoint would need to somehow constantly recalculate those column values and continuously update the column values in the database. This simply isn't possible.
Alternatives to Calculated Columns
I suggest taking a different approach entirely instead of using a calculated column for this purpose.
Conditional Formatting: You can apply conditional formatting to highlight records that meet certain criteria. This can be done using SharePoint Designer or HTML/JavaScript.
Filtered List views: Since views of lists are queried and generated in real time, you can use volatile values in list view filters. You can set up a list view web part that only shows items where Created is equal to [Today]. Since you can place multiple list view web parts on one page, you could have one section for today's items, and another web part for all the other items, giving you a visual separation.
A workflow, timer job, or scheduled task: You can use a repeating process to set the value of a normal (non-calculated) column on a daily basis. You need to be careful with this approach to ensure good performance; you wouldn't want it to query for and update every item in the list if the list has surpassed the list view threshold, for example.
I found some conversations about this issue. Many people suggest to creating a new Date Time column, visible is false, default value is Today's Date and it will be named as Today. Then we can use this column in our formulas.
I tried this suggestion and yes error is gone and formula is accepted but calculated columns' values are wrong. I setted column Today is visible and checked, it was empty. Default value Today's Date was not working. When I looking for a solution for this issue I deleted column Today carelessly. Then I realized calculated columns' values are right.
Finally; I don't know what is trick but before using Today keyword in your formulas if you create a column named as Today and after your formula saving if you delete Today column, it is working.
UPDATE
After #Thriggle's answer I realized this approach doesn't work like a charm. Yes, formula doesn't cause an error when calculated column saving but it works correctly only first time, in the next day the calculated column shows old values, because its values are static as Thriggle explained.

Simple calculator using Drupal?

I need to create a simple form which asks two values from the user, and when she submits the form shows a value calculated based on those values.
For example, user could be shown something like this:
1st number:
2nd number:
Result:
Calculate!
The only editable fields are 1st and 2nd number. After giving the numbers and clicking Calculate!, she sees the following page:
1st number: 15
2nd number: 20
Result: 35
Calculate!
She can now modify the numbers and reclick Calculate! It is OK to submit and reload the page, the values don't need to be updated in-place.
Do I have to do this using JavaScript injection, or is there another way?
Take a look at Computed Field module.
You don't have to do something like this with JavaScript, but that would be the quickest and easiest solution. Especially since you have jQuery available. You don't even have to let users click calculate.
example code:
$("#input_1, #input_2").change(function(){
$("#result").text(parseInt($("#input_1").val(), 10) + parseInt($("#input_2").val(), 10));
});
given two input fields with id input_1 and input_2 and a span/div etc. to display the result with id result the above code automatically calculate the two values whenever something is new is entered into them.
I see here several possible options:
1) You can even create a simple form and, using JavaScript, calculate the data entered in the fields, you can even use simple jQuery, as already suggested in one of the answers.
2) Search for ready-made modules on the official Drupal website, for example:
WebForm Calculator
Simple Calculator
True, everything will probably have to be refined, but I think it will not take many lines of code.
3) Use the builder uCalc - it does not require programming and all actions occur in the visual editor. You just throw the necessary widgets into the form and do the calculation for the values ​​you need. Very useful thing and saves time.
4) There are a few more websites that can be downloaded ready-made scripts of such calculators, but they will need to be seriously developed.

Resources