Formula help

Derek Williams May 21, 2014

Hello All,

I'm trying to get a percentage formula to work in the calculated number field, but it is not displaying.

I know the field works because this formula works:

<!-- @@Formula:
if (issue.get("customfield_16606").equals("Pass"))
return 1;
-->

When I set custom field 16606, labeled "Attribute 1", the number "1" shows up and the Custom Field label shows up. However, when I try to use my more complex formula it does not work, here is the formula:

<!-- @@Formula: 
int maxAttCount = 5;
Object att1 = issue.get("customfield_16606");
Object att2 = issue.get("customfield_16608");
Object att3 = issue.get("customfield_16609");
Object att4 = issue.get("customfield_16610");
Object att5 = issue.get("customfield_16611");
int failCount = 0;
int passCount = 0;
int fyiCount = 0
int totalCount = 0;
float percentage = 0;
 
if (att1 == null && att2 == null && att3 == null && att4 == null && att5 == null)
{
	percentage = 0
}
else
{
	Class c = Class.forName("attList");
	for (int i=0; i < maxAttCount; i++) {
		Field f = c.getField("att" + i);
		if (f.equals("Fail")) {
			totalCount = totalCount + 1;
		}
		else if (f.equals("Pass")) {
			passCount = passCount + 1;
			totalCount = totalCount + 1;
		}
		else if (f.equals("FYI")) {
			fyiCount = fyiCount + 1;
			totalCount = totalCount + 1;
		}
		else if (f.equals("NA")) {
			
		}
	}
	
	if (totalCount == 0) {
		percentage = 0
	}
	else {
		percentage = ((passCount + fyiCount) * 100/totalCount);
	}
}
 
return percentage;
-->

Typically I code in C# so am a little unfamiliare with the Java syntax. What I would like to do is have a set of defined attributes at the top of the formula and then loop through them to calculate a percentage given to me by the business. I am not 100% sure that I am looping through the variables correctly. I would like to be able to add attributes to the top without changing the percentage calculation.

Any help or tips would be much appreciated.

2 answers

1 accepted

0 votes
Answer accepted
David _old account_
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 21, 2014

The first thing to do is to look into atlassia-jira.log for errors. It is likely a compilation issue.

In your code, I see you're trying to get a class named "attList", but I don't see where that is coming from.

You should instead use a Java array to hold your 5 custom field values and then iterate through the array.

Derek Williams May 21, 2014

Correct, in the examples I found it looked like this was a way to set up a dummy class to store the "Field" data. Atleast, that is what I thought it would do. Looking into using an array instead, I'll post my results.

Derek Williams May 21, 2014

Cleaned it up a little bit, and switched to an array, but still not working:

<!-- @@Formula: 
int maxAttCount = 5;
Object att1 = issue.get("customfield_16606");
Object att2 = issue.get("customfield_16608");
Object att3 = issue.get("customfield_16609");
Object att4 = issue.get("customfield_16610");
Object att5 = issue.get("customfield_16611");
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add(att1.toString());
arrayList.add(att2.toString());
arrayList.add(att3.toString());
arrayList.add(att4.toString());
arrayList.add(att5.toString());
int failCount = 0;
int passCount = 0;
int fyiCount = 0
int totalCount = 0;
float percentage = 0;
 
for (int i=0; i < maxAttCount; i++) {
	if (arrayList.get(i).equals("Fail")) {
		totalCount = totalCount + 1;
	}
	else if (arrayList.get(i).equals("Pass")) {
		passCount = passCount + 1;
		totalCount = totalCount + 1;
	}
	else if (arrayList.get(i).equals("FYI")) {
		fyiCount = fyiCount + 1;
		totalCount = totalCount + 1;
	}
	else if (arrayList.get(i).equals("NA")) {
		
	}
}

if (totalCount == 0) {
	percentage = 0
}
else {
	percentage = ((passCount + fyiCount) * 100/totalCount);
}
 
return percentage;
-->

Edit: Still trying to access the logs, I was just given a web address, not sure where the physical log file is. Is there any way to see the log remotely from within JIRA? System -> Logging appears to only be settings and not the actual log.

David _old account_
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 21, 2014

Any error in the logs?

Derek Williams May 22, 2014
Sorry, log has the latest errors on the bottom, here is the latest error:
 
2014-05-22 13:15:21,791 http-bio-8080-exec-20 ERROR dywillia 795x11298x2 5t6vmz 10.105.95.48 /secure/EditAction!default.jspa [innovalog.jmcf.fields.CalculatedNumberField] CalculatedNumberField: error evaluating formula: Parse error at line 17, column 1.  Encountered: int
 
Edit: forgot a semi-colon, wow, re-testing.
Derek Williams May 22, 2014

UPDATE:

2014-05-22 13:21:46,667 http-bio-8080-exec-6 ERROR dywillia 801x11357x1 5t6vmz 10.105.95.48 /secure/IssueAction.jspa [innovalog.jmcf.fields.CalculatedNumberField] CalculatedNumberField: error evaluating formula: Sourced file: inline evaluation of: ``   int maxAttCount = 4;  Object att1 = issue.get("customfield_16606");  Object a . . . '' : Error in method invocation: Method Equals( java.lang.String ) not found in class'java.lang.String'
Formula in it's current state:
<!-- @@Formula: 
int maxAttCount = 4;
Object att1 = issue.get("customfield_16606");
Object att2 = issue.get("customfield_16608");
Object att3 = issue.get("customfield_16609");
Object att4 = issue.get("customfield_16610");
Object att5 = issue.get("customfield_16611");
ArrayList list = new ArrayList();
list.add(att1);
list.add(att2);
list.add(att3);
list.add(att4);
list.add(att5);
int failCount = 0;
int passCount = 0;
int fyiCount = 0;
int totalCount = 0;
float percentage = 0;
 
for (int i=0; i < maxAttCount; i++) {
	if (list.get(i).Equals("Fail")) {
		totalCount = totalCount + 1;
	}
	else if (list.get(i).Equals("Pass")) {
		passCount = passCount + 1;
		totalCount = totalCount + 1;
	}
	else if (list.get(i).Equals("FYI")) {
		fyiCount = fyiCount + 1;
		totalCount = totalCount + 1;
	}
	else if (list.get(i).Equals("NA")) {
		
	}
}

if (totalCount == 0) {
	percentage = 0
}
else {
	percentage = ((passCount + fyiCount) * 100/totalCount);
}
 
return percentage;
-->

 I'm thinking it has to do with these lines: list.get(i).Equals("Fail")
As that is the only reference to "Equals", I will test a different qualifier.
David _old account_
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 22, 2014
Indeed. It's "equals" or equalsIgnoreCase. The java convention calls for a lowercase first letter for method names.
Derek Williams May 22, 2014

Thank you!!!

That was it, lower case "e" fixed the rest. I now have a percentage result, it is a little bit off, but I think I can work with it.

Question: would it be better to return a double or float? Does it matter?

Full formula in case somebody else wants to use it:

<!-- @@Formula:

int maxAttCount = 4;

Object att1 = issue.get("customfield_16606");

Object att2 = issue.get("customfield_16608");

Object att3 = issue.get("customfield_16609");

Object att4 = issue.get("customfield_16610");

Object att5 = issue.get("customfield_16611");

ArrayList list = new ArrayList();

list.add(att1);

list.add(att2);

list.add(att3);

list.add(att4);

list.add(att5);

int failCount = 0;

int passCount = 0;

int fyiCount = 0;

int totalCount = 0;

float percentage = 0;

for (int i=0; i < maxAttCount; i++) {

if (list.get(i).toString().equals("Fail")) {

totalCount = totalCount + 1;

}

else if (list.get(i).toString().equals("Pass")) {

passCount = passCount + 1;

totalCount = totalCount + 1;

}

else if (list.get(i).toString().equals("FYI")) {

fyiCount = fyiCount + 1;

totalCount = totalCount + 1;

}

else if (list.get(i).toString().equals("NA")) {

}

}

if (totalCount == 0) {

percentage = 0;

}

else {

percentage = ((passCount + fyiCount) * 100/totalCount);

}

return percentage;

-->

David _old account_
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 22, 2014
Double has more precision than float. But it won't make a huge difference in your case.
0 votes
Derek Williams May 22, 2014

Updated Version of the script with minor bug fixes and added a percentage format:

&lt;!-- @@Formula: 
int maxAttCount = 5;
Object att1 = issue.get("customfield_16606");
Object att2 = issue.get("customfield_16608");
Object att3 = issue.get("customfield_16609");
Object att4 = issue.get("customfield_16610");
Object att5 = issue.get("customfield_16611");
ArrayList list = new ArrayList();
list.add(att1);
list.add(att2);
list.add(att3);
list.add(att4);
list.add(att5);
int passCount = 0;
int fyiCount = 0;
int totalCount = 0;
double percentage = 0;
 
for (int i=0; i &lt; maxAttCount; i++) {
	if (list.get(i).toString().equals("Fail")) {
		totalCount = totalCount + 1;
	}
	else if (list.get(i).toString().equals("Pass")) {
		passCount = passCount + 1;
		totalCount = totalCount + 1;
	}
	else if (list.get(i).toString().equals("FYI")) {
		fyiCount = fyiCount + 1;
		totalCount = totalCount + 1;
	}
	else if (list.get(i).toString().equals("NA")) {
		
	}
}

if (totalCount == 0) {
	percentage = 0;
}
else {
	percentage = ((passCount + fyiCount) * 1.00/totalCount);
}
 
return percentage;
--&gt;

&lt;!-- @@Format:
import java.text.NumberFormat;
NumberFormat defaultFormat = NumberFormat.getPercentInstance();
defaultFormat.setMinimumFractionDigits(2);
defaultFormat.format(value);
--&gt;

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events