Averaging numerous values in a class - vba

I have a class with a lot of parameters as it takes in all the columns in Excel, since this is the first step I usually do when building a macro. Then I started to think about how to actually accomplish what I'm trying to do and I think I just wasted a couple of hours of coding.
What I am trying to do is average each of the parameters inside the class as well as trying to get minimum and maximum values. There are about 100000 rows in these excel files.
My plan was to put everything into a collection and then I was thinking there was going to be some sort of averaging function or a min and max function for the collection parameter, or a way to send an array to a function that can calculate min or max.
What would be ideal:
Dim collectionOfRecords as new collection
for each row in sheet.rows
Dim r as New RmmRecord
call r.PopulateClass(row)
collectionOfRecords.add r
next row
Then get the average from the collection somehow like this:
dim parameter1Average as double
parameter1Average = collectionOfRecords.Parameter1.Average '(ha, I wish)
OR:
parameter1average = GetAverageFromCollection(collectionOfRecords, Parameter1)
Public Function GetAverageFromCollection(records as Collection, parameterToAverage as something??)
for each record in records
sum = record.parameterToAverage + sum
next record
GetAverageFromCollection = sum / records.count
end function
Thank you!

Related

inquiry Data from data table to datagridview with filters

i have datatable "dataitems" contain 98000 Rows And Datagridview have 11000 row
want to add the quantity form the datatable to the datagridview every item in it's row in the datagrid view
i am using this code but its take too too too much time to run and sometimes stop responding i need ideas to make it faster to run
Dim dt As New DataTable = najrndataset.dataitems
Dim Total As Integer
for x = 0 to datagridview1.rows.count -1
Dim b = datagridview1.rows(x).cells(1)
Dim c = 3
Total = (From r As DataRow In dt.AsEnumerable
Where r.Field(Of String)("Item_Number") = b And r.Field(Of Integer)("SOP_Type") = c
Select r.Field(Of Integer)("Quantity")).Sum
datagridview1.Rows(x).Cells(0).Value = Total
next
Hopefully you appreciate that if you have 11000 rows in a datagridview (terrible idea, by the way) and 98000 rows in a datatable, and you're running a loop that searches the table for each of the 11K items, and it does this by starting at number 1, and searching 98000 items for it, then going to 2 and searching 98000 items for it til you reach 11000 and searching 98000 items for it... At the end of the operation you're going to have performed 11000 x 98000 operations.. i.e. you're going to have performed 1.078 BILLION operations. This is why "its take too too too much time to run and sometimes stop responding" :)
You can speed this up by using a dictionary to track the sums, and it'll probably be fastest to index the 98000 items then set the dictionary from them:
Dim d as New Dictionary(Of String, Integer)
For Each di In najrndataset.dataitems.Where(Function(r) r.SOP_Type = 3)
If Not d.ContainsKey(di.Item_Number) Then
d(di.Item_Number) = di.Quantity
Else
d(di.Item_Number) += di.Quantity
End If
Next di
Then edit your grid (ugh; this isn't how datagridview are supposed to be used)
datagridview1.SuspendDrawing()
For x = 0 to datagridview1.rows.count - 1
Dim b = datagridview1.rows(x).cells(1)
Dim s As Integer
If d.TryGetValue(b, s) Then
datagridview1.rows(x).cells(0) = s
End If
Next x
datagridview1.ResumeDrawing()
You could also have a logic of "loop over the datagrid, putting 11000 items in the dictionary, loop over the datatable accumulating sums into the dictionary if the keys are present in the dictionary, loop over the datagriview putting the sums into the datagridview".
Not an answer, but too long for a traditional comment. I'm working to provide an answer separately.
I can't tell you how many times I've seen code like this:
Dim someVariable As New SomeObject
someVariable = someMethodToReturnSomeObject()
This pattern is bad code!
The New operator in the first line tells the compiler you want to allocate memory and run the constructor for your type. However, the next line assigns a new object... it throws away and forgets the memory and constructor work from the previous line. That's wasteful.
Instead, you want this:
Dim someVariable As SomeObject = someMethodToReturnSomeObject()
Worse, this speaks to a profound lack of understanding of the difference between a reference and an object, and what the computer is doing with your code in memory. This is a core principle of how many programming environments work. Code like the first example gives me big doubts of the capability of the programmer who writes it.

Can I use a method that returns a list of strings in SSRS report code as the headers in a tablix?

I have table that needs to contain 50 columns for each half hour in the day (+2 for daylight savings). So each column will be HH1, HH2, HH3... HH50.
I have written this piece of code in the report properties code section.
Function GetHH() As List(Of String)
Dim headers As List(Of String) = new List(Of String)
For index As Integer = 1 to 50
headers.Add("HH" & index)
Next
return headers
End Function
Is there a way to use the output of this function as the headers of my tablix? Or will I need to add the headers to some sort of dataset in the database and add it from there?
The column group functionality would be well suited for this. As you mentioned, you would need to write a SQL statement to return these values in a dataset. Then you can set your column group to group on these values. This way your table always gets the right number of columns and you don't have to add them manually.

Excel Summing over Rows with for loop - Type mismatch error

so I am currently working on an Excel sheet where I have to calculate confidence intervals. Long story short, I think the only way I can do this automatically, is to write vba code. The first step would be to calculate the average of the cells in a column for several columns in the sheet. What I did:
Dim temp As Double
temp = 0
Dim it_row As Long
for it_row = 1 to 100
if IsBlank(Sheet.Cells(it_row,it_col)) then
temp = temp + 0
else
temp = temp + Sheet.Cells(it_row,it_col).Value
end if
next it_row
Dim Average As Double
Average = temp/100
'writing average in another cell
This code does not work, as the compiler returns Type missmatch, error code 13
in the line
temp = temp + Sheet.Cells(it_row,it_col).Value
I tried to do a CDouble(Sheet.Cells(it_row,it_col).Value) but that did not work.
Any help is appreciated, as I am quite desperate because googling did not really help me.
I should mention that I do have to use vba and this code because this is part of a bigger automated process and my supervisor said I must use vba for automation in the next step.
The Average and Sum Excel Functions ignore text, boolean, and empty values:
Average = Application.Average(Sheet.Cells(1, it_col).Resize(100))
Check
Sheet.Cells(it_row,it_col).Value
...with
if isnumeric(Sheet.Cells(it_row,it_col).Value)
...before adding it to a double type value. If that check fails, then you can chose to skip it or treat it as sth. else.
I would've added this as a comment, but I don't have enough rep. to add comments.

Use formula for multiplication?

I have two fields on a record ("Qty" and "Harga").
How do I multiply the two and save result into another field in a ListView?
The ListView control has no built-in ability to perform calculations for you, like a spreadsheet. It just displays whatever data you give it to display. If you want it to display the product of a multiplication equation, you will need to do that calculation yourself in the code and then add the result to the ListView column. For instance:
Public Sub AddItem(description As String, total As Integer, count As Integer)
Dim i As ListViewItem = ListView1.Items.Add(description)
i.SubItems.Add(total.ToString())
i.SubItems.Add(count.ToString())
Dim product As Integer = total * count
i.SubItems.Add(product.ToString())
End Sub

Function does not read last value

I am developing a program for a chain of restaurants, they should normally be able to calculate their guestcount and sales through a vb.net application with a connection to dbf files.
My dataset gets filled in correctly as is my datatable (checked by filling in datarowview = right data)
But then I get a problem, in all my functions using my datatable, the datatable skips the final value, in this case it is all values from a month so it either skips 31 or day 30.
Tried while, Tried for each, debugged alot (how i found it was the last value). But now I have no idea why the last value isn't used by the function
Public Function Getgctakeout(ByVal i_table As DataTable)
table = i_table
i = 0
gctakeout = 0
For Each row As DataRow In i_table.Rows
gctakeout = gctakeout + Convert.ToDouble(row(4))
Next row
'MessageBox.Show(gctakeout)
Return gctakeout
End Function
This function does not use the value of the last row to calculate gctakeout
what in the name of the lord is wrong :)
Assuming that your DataTable is really filled correctly, you have two other options to get the sum.
Use the old DataTable.Compute method which works also with .NET < 2.0
Use Linq-To-DatSet and it's Enumerable.Sum
1)
Dim Sum = CType(table.Compute("Sum(ColumnName)", Nothing), Double)
2)
Dim Sum = table.AsEnumerable().
Sum(Function(row)row.Field(Of Double)("ColumnName"))