SSRS expression - query from dataset, with group - sql

Let's say for each student, I have a note of an exam and I need to calculate the percentile rank... of each question, each group of question and total exam (each student).
Do to that I need, for each question, group of question, and total exam:
1) x = the score (That I have of course)
2) the count of score above x
3) the count of score equal to x
4) the count total of score
Do to that it looks like I need to use sub-select for me, in a T-SQL query. Calculate everything inside a big dataset and use it.
Is there a way to acheive that inside SSRS?

I found that interesting post about the percentile function in SSRS, I will give it a try.
https://www.katieandemil.com/ssrs-percentile-function-2008-r2-calculation-custom-code-example?tab=article
I had to create another function to return the rank, but the main idea was there:
Public Shared Dim values As System.Collections.ArrayList
Public Shared Function AddValue(ByVal newValue As Decimal) As Decimal
If (values Is Nothing) Then
values = New System.Collections.ArrayList()
End If
values.Add(newValue)
AddValue = values.Count
End Function
Public Shared Function GetRankPercentile(ByVal CurrentValue As Decimal) As Decimal
Dim countTotal As Integer = values.Count 'nombre total de données
Dim countGreater As Integer = 0
Dim countEqual As Integer = 0
Dim iLoop As Integer
Dim tmpArray as system.array
tmpArray = values.ToArray()
For iLoop = LBound(tmpArray) To UBound(tmpArray)
If tmpArray(iLoop) CurrentValue Then countGreater = countGreater + 1
If tmpArray(iLoop) = CurrentValue Then countEqual = countEqual + 1
Next
GetRankPercentile = Math.Ceiling((countGreater + (countEqual / 2)) / countTotal * 5)
End Function

Related

how to sum values of same id in datagridview?

i am trying to sum values of same id in datagridview and trying to update sql database table. how to do it?
For i As Integer = 0 To DataGridView2.Rows.Count - 1
If Convert.ToInt32(DataGridView2.Rows(i).Cells(0).Value) = Convert.ToInt32(DataGridView2.Rows(i).Cells(0).Value) Then
y += Convert.ToInt32(DataGridView2.Rows(i).Cells(3).Value)
End If
Next
As you have been already told, the if statement you are coding is comparing a cell with itself, which doesn't make sense, because it Will always return true.
I'm guessing that you need to compare all cells that share the same id and sum the result, but you would need to elaborate the question better, so we can understand what your actuall purpose is.
you can use Dictionary to check and group id with sum values
Dim totals As Dictionary(Of String, Integer) = New Dictionary(Of String, Integer)()
For i As Integer = 0 To DataGridView2.Rows.Count - 1
Dim group As String = Convert.ToInt32(DataGridView2.Rows(i).Cells("id").Value)
Dim qty As Integer = Convert.ToInt32(DataGridView2.Rows(i).Cells("value").Value)
If totals.ContainsKey(group) = False Then
totals.Add(group, qty)
Else
totals(group) += qty
End If
Next
or use group with LINQ:
Dim totals = DataGridView2.Rows.Cast(Of DataGridViewRow)().GroupBy(Function(row) row.Cells("id").Value.ToString()).[Select](Function(g) New With {Key
.id= g.Key, Key
.SumValues = g.Sum(Function(row) Convert.ToInt32(row.Cells("value").Value))
})

optimization vba as part of original function

I need to perform an optimization in VBA. I would like to get it as a part of a function. How can I do it?
This is my function:
Function TirNoPer360(Cash, Dates As Range)
Dim i, n As Integer
Dim sum, rate, tolerance As Double
Dim Inicio As Date
Dim rate as Variant
tolerance = 0.00001
Initial = Dates(1, 1)
sum = 0
For i = 1 To Cash.Rows.Count
sum = sum + Cash(i) / ((1 + rate) ^ (Application.WorksheetFunction.Days360(Initial, Dates(i)) / 360))
Next i
TirNoPer360 = sum
End Function
I´d like to get the value of rate (using root finding algo) thats makes TirNoPer360 = 0.
How can I do it as part of this function? Any guidance would be hepful

Add integer to another integer in vb.net?

How can I add an integer to another integer in vb.net?
This is what I need to do:
Given integer: 2187 ->
Converted integer: 2018
I need to add a 0 in between the first and second number, and drop the last digit. This will give me the year.
Here is the code that I have:
Protected Function GetYear(ByVal term As Integer) As Integer
Dim termYear As String = Convert.ToString(term)
termYear.Substring(0, 2)
termYear.Insert(1, "0")
Dim convertedYear As Integer
Int32.TryParse(termYear.ToString, convertedYear)
convertedYear = convertedYear / 10
Return convertedYear
End Function
In general strings are immutable. So you'd have to create a new string out of the addition of substrings. Check this possible solution.
Function GetYear(ByVal term As Integer) As Integer
Dim termYear As String = Convert.ToString(term, Globalization.CultureInfo.InvariantCulture)
Dim result As String = termYear.Substring(0, 1) + "0" + termYear.Substring(1, 2)
Return Int32.Parse(result)
End Function
Strings are immutable, when you do any changes with one of their method, you need to get the returned string.
termYear = termYear.Insert(1, "0")
This question deserves a math based solution. The below code specifies the zero insertion point relative to the number's right side instead of the left as stated in the problem statement. So for a 4 digit number the insertion point is 3 versus 2. It also allows you to change the insertion point.
Private Function GetYear(ByVal term As Integer, Optional zeroDigitPosition As Integer = 3) As Integer
If zeroDigitPosition > 0 Then
Dim divisor As Integer = 1
For i As Integer = 1 To zeroDigitPosition - 1
divisor *= 10
Next
Dim ret As Integer = term \ 10 ' drop one's place digit, remaining digits shift to right
Dim rightShiftedDigits As Integer = ret Mod divisor
Dim remainder As Integer = Math.DivRem(ret, divisor, rightShiftedDigits)
' shift the remainder to the left by divisor * 10
' (remember first right shift invplved \ 10) and add
' rightShiftedDigits to yield result
Return (remainder * divisor * 10) + rightShiftedDigits
Else
Throw New ArgumentOutOfRangeException("zeroDigitPosition must be greater then zero")
End If
End Function

VBA. "Type mismatch: array or user-defined type expected"

I am completely new to VBA. I need to write a program, which will generate an array of integer and will find an index of the minimal element. I got this error
"Type mismatch: array or user-defined type expected." I looked into many similar questions, but couldn't figure out what is wrong.
Function random_integer(Min As Integer, Max As Integer)
random_integer = Int((Max - Min + 1) * Rnd + Min)
End Function
Function generate_array(Size As Integer)
Dim Arr(Size)
For i = 0 To UBound(Arr)
Arr(i) = random_integer(i - 10, i + 10)
Next
generate_array = Arr
End Function
Function find_index_of_min_elem(ByRef Arr() As Variant)
Dim Min As Integer
Min = Arr(0)
Dim MinIndex As Integer
MinIndex = 0
For i = 1 To UBound(Arr)
If Arr(i) < Min Then
Min = Arr(i)
MinIndex = i
End If
Next
find_index_of_min_elem = MinIndex
End Function
Sub task6()
A = generate_array(20)
IndexOfMinElemInA = find_index_of_min_elem(A)
MsgBox IndexOfMinElemInA
End Sub
The problem is the function Function find_index_of_min_elem(ByRef Arr() As Integer) is expecting an Integer as a parameter and you are passing a as a Variant
a = generate_array(20)
IndexOfMinElemInA = find_index_of_min_elem(a)
The next error that you will get is on Dim Arr(Size) As Integer. You cannot dimension an array like that.
I would recommend reading up on arrays.
There may be other errors but I have not checked those.
What about this? Make a second column of index numbers (in sequence from small to large) and then order the two rows by your original column. I've included the example below to illustrate:
A = the original column of numbers,
B = the column of index numbers
D & E are the result of sorting A & B by column A
The answer is then: the lowest number "0" was at index 7

Datagridview, how to get min, max, and average on certain range

I have a DataGridView which contains 1000 data points. I have successfully calculated the min, max, and average of the values in my DataGridView, but now I want to get the min, max, and average values only from a certain range. For example, data in 101 to 200 or 201 to 300 .
For i As Integer = 0 To dataGridView1.Rows.Count() - 1 Step +1
sum_tmp = sum_tmp + dataGridView1.Rows(i).Cells(2).Value
If i = 0 Then
max_tmp = dataGridView1.Rows(i).Cells(2).Value
min_tmp = dataGridView1.Rows(i).Cells(2).Value
End If
If max_tmp < dataGridView1.Rows(i).Cells(2).Value Then
max_tmp = dataGridView1.Rows(i).Cells(2).Value
End If
If min_tmp > dataGridView1.Rows(i).Cells(2).Value Then
min_tmp = dataGridView1.Rows(i).Cells(2).Value
End If
Next
avg_tmp = sum_tmp / dataGridView1.Rows.Count()
Above is my code to get the value. I have tried using integer variable that changed by selecting combobox but still always get 0 value on min. Sadly it shows the right value on the average. How is it possibly wrong?
You can use a LINQ expression to get an enumerable collection of the values you want to process, then use built-in functions to get the max, min, and average
Define a struct which will hold the resulting calculations
Private Structure ResultsStruct
Public Min As Single
Public Max As Single
Public Average As Single
Public Sum As Single
End Structure
This function returns the struct when called. Pass in the first row index and last row index.
Private Function getResults(firstRow As Integer, lastRow As Integer) As ResultsStruct
Dim skipRows = firstRow - 1
Dim takeRows = lastRow - skipRows
Dim values = DataGridView1.Rows.
OfType(Of DataGridViewRow)().
Select(Of Single)(Function(r) Single.Parse(r.Cells(0).Value.ToString())).
Skip(skipRows).
Take(takeRows)
Dim max = values.Max()
Dim min = values.Min()
Dim avg = values.Average()
Dim result As New ResultsStruct() With {.Max = values.Max(),
.Min = values.Min(),
.Average = values.Average(),
.Sum = values.Sum()}
Return result
End Function
How it's called
Dim result = getResults(firstRow:=201, lastRow:=300)
MessageBox.Show(String.Format("Max: {0}, Min: {1}, Avg: {2}, Sum: {3}",
result.Max, result.Min, result.Average, result.Sum))
Replace 201 and 300 in the example with the range you are interested in, whether it is from the user selecting the grid or some other means of input.