How to count and group using vb.net - vb.net

I have the following data returned from a web service and serialized into a list:
Name Severity Type
John Doe Warning A
John Doe Error A
John Doe Error A
John Doe Error A
Jane West Error B
Mike Smith Warning B
Jack Black Warning A
In vb.net, I want to summarize it into the following:
Name TypeAWarning TypeAError TypeBWarning TypeBError
John Doe 1 3
Jane West 1
Mike Smith 1
Jack Black 1
Using linq, how can I take this collection and summarize it? I tried something like:
Dim data As New List(Of TempData)
data.add(new TempData ({TypeAWarning = from d in data Group d By Name = a.Severity into Group??
I am just not sure if linq is the way to go. Can someone point me in the right direction?
Thanks!

You can use a GroupBy to group items by Name field, then knowing each group contains the key (Name field) and all items of the group, you can use this query to shape the result:
Dim Result = Items.GroupBy(Function(item) item.Name) _
.Select(Function(group) New TempData() With
{
.Name = group.Key,
.TypeAWarning = group.Where(Function(item) item.Type = "A" And item.Severity = "Warning").Count(),
.TypeAError = group.Where(Function(item) item.Type = "A" And item.Severity = "Error").Count(),
.TypeBWarning = group.Where(Function(item) item.Type = "B" And item.Severity = "Warning").Count(),
.TypeBError = group.Where(Function(item) item.Type = "B" And item.Severity = "Error").Count()
}).ToList()

Related

Cross table VB.NET & SQL Server & Linq

I have a table like this:
MAName feldtext
------------------
karl fieldtext1
karl fieldtext2
karl fieldtext1
karl fieldtext3
karl fieldtext4
karl fieldtext2
karl fieldtext5
karl fieldtext3
karl fieldtext3
susi fieldtext1
susi fieldtext4
john fieldtext2
john fieldtext5
john fieldtext5
and I need:
MAName fieldtext1 fieldtext2 fieldtext3 fieldtext4 fieldtext5 FehlerJeMA
karl 2 2 3 1 1 9
susi 1 0 0 1 0 2
john 0 1 0 0 2 3
The columns fieldtext can go from fieldtext1 to fieldtextn, it's dynamic, depending on query.
I was looking here for solutions and found, so my approach:
Dim dt2 As New DataTable
Dim nn As Integer = 0
Dim Zeile As DataRow
dt2.Columns.Add("MAName")
' fieldtext distinct
Dim query2 = (From dr In (From d In newTable2.AsEnumerable Select New With {.feldtext1 = d("feldtext")}) Select dr.feldtext1 Distinct)
For Each Feldtext In query2
dt2.Columns.Add(Feldtext)
Next
column = New DataColumn()
column.DataType = System.Type.GetType("System.Int32")
column.ColumnName = "FehlerJeMA"
dt2.Columns.Add(column)
' MAName distinct
Dim query3 = (From dr In (From d In newTable2.AsEnumerable Select New With {.MAName2 = d("MAName")}) Select dr.MAName2.ToString.ToLower Distinct)
For Each Mitarbeiter In query3
Zeile = dt2.NewRow()
Zeile(0) = Mitarbeiter.ToString.ToLower
MA2 = Mitarbeiter.ToString.ToLower
nn = 1
For Each colName2 In query2
Fehler2 = colName2
Dim AnzahlFehler As String = (From row In newTable2.Rows Select row Where row("MAName").ToString.ToLower = MA2 And row("feldtext") = Fehler2).Count
If AnzahlFehler = 0 Then
AnzahlFehler = ""
End If
Zeile(nn) = AnzahlFehler
nn += 1
If AnzahlFehler <> "" Then
FehlerJeMA += CInt(AnzahlFehler)
End If
Next
Zeile(nn) = FehlerJeMA
dt2.Rows.Add(Zeile)
Next
This works, but is very slow...
It could be the case that in my table has more than 10.000 rows...
So my question is: what is fastest approach to get the result?
Is it some kind of cross table with linq? Other approaches?
In C# you will be able to use the code, try to translate it for your problem:
var pivotData = data.GroupBy(x => new {x.MAName, x.feldtext}, (key, group) => new { MAName = key.Column1, feldtext = key.Column2, count = group.Count() });

in excel how to repeat column for each row in another column

in excel there are city names in sheet 1,
and in sheet 2 person names.
example
City
Achalpur
Achhnera
Adalaj
Adilabad
person name
Name
A
B
C
D
I want the result in sheet 3 like below
city 1 person 1
city 1 person 2
till last person
city 2 person 1
city 2 person 2
Achalpur A
Achalpur B
Achalpur C
Achalpur D
Achalpur E
Achalpur F
Achalpur G
Here is a function that will do it for you. You can modify it slightly, if you can be sure that there will be no empty rows between entries in your city list or the second list.
It also assumes that your data is in Sheet1 and Sheet2 with a header row.
One minor thing to modify, you might just need to set the s3RCtr back 5 for each time the loop finishes, otherwise you get a gap of 5 empty rows in your results.
I hope this helps. Sorry, I've got something urgent to look at atm.
Function DoStuff()
Dim s1ECtr, s1RCtr
Dim s2ECtr, s2RCtr
Dim s3RCtr
s1ECtr = 1
s2ECtr = 1
s1RCtr = 2
s3RCtr = 2
Do While s1ECtr < 5
If (Sheet1.Cells(s1RCtr, 1) <> "") Then
s2RCtr = 2
Do While s2ECtr < 5
If (Sheet2.Cells(s2RCtr, 1) <> "") Then
Sheet3.Cells(s3RCtr, 1) = Sheet1.Cells(s1RCtr, 1) & " " & Sheet2.Cells(s2RCtr, 1)
Else
s2ECtr = s2ECtr + 1
End If
s3RCtr = s3RCtr + 1
s2RCtr = s2RCtr + 1
Loop
s2ECtr = 0
Else
s1ECtr = s1ECtr + 1
End If
s1RCtr = s1RCtr + 1
Loop
End Function

EXCEL 2010: Split Cells using VBA to multiple Cells

I am looking for some help converting my formulas to VBA code.
My data is currently in Column ($T10)
I currently have rows of data similar to:
Jane Doe (doe.jane#___.com)
JOHN DOE, SR (noemail-8858)
first second DE surname surname2 (email#_______.com)
first middle surname (email#_____.net)
Formulas to get the 'normal' names:
[First Surname] =IF($C2678=1,(LEFT(B2684,SEARCH("(",B2684)-1)),"")
[first name] =IF($C4068=1,(LEFT(TRIM(B4074),FIND(" ",TRIM(B4074))-1)),"")
[middle name] =IF($C3888=1,(IF(LEN(TRIM(B3894))-LEN(SUBSTITUTE(B3894," ",""))<>3,"",LEFT(MID(TRIM(B3894),FIND(" ",TRIM(B3894))+1,99),FIND(" ",MID(TRIM(B3894),FIND(" ",TRIM(B3894))+1,99))-1))),"")
[surname] =IF($C4068=1,(TRIM(RIGHT(SUBSTITUTE(TRIM(LEFT(B4074,FIND("(",B4074)-1))," ",REPT(" ",99)),99))),"")
[email] =IF($C4068=1,(MID(TRIM(B4074),FIND("(",TRIM(B4074))+1,FIND(")",TRIM(B4074))-FIND("(",TRIM(B4074))-1)),"")
Results (edited):
| jane Doe | jane | middle | Doe | doe.jane#____.com |
| first surname | first | middle | Surname | noemail-8858 |
I've looked at both TRIM and SPLIT functions, however I haven't been able to find a way to split given the variables (, ( )) in the one cell.
I've used:
http://www.homeandlearn.org/left_and_right_functions.html
http://www.globaliconnect.com/excel/index.php?option=com_content&view=article&id=269:excel-vba-string-functions-left-right-mid-len-replace-instr-instrrev&catid=79&Itemid=475
http://www.exceltrick.com/formulas_macros/vba-split-function/
They aren't really piecing together what I need. I can get some basics, but not the more complex formulas converted to VBA.
Many thanks in advance.
This is an extension of my previous enquiry in 2014, where I was able to get the formulas.
Excel 2010 search for text in IF function - separate cell data
Short of analysing exactly what your formulas are currently doing (i assume you're happy with how they work right?) then I can't see why you can't directly convert them all?
Start point:
=IF($C3888=1,(IF(LEN(TRIM(B3894))-LEN(SUBSTITUTE(B3894," ",""))<>3,"",LEFT(MID(TRIM(B3894),FIND(" ",TRIM(B3894))+1,99),FIND(" ",MID(TRIM(B3894),FIND(" ",TRIM(B3894))+1,99))-1))),"")
Formatted more:
=IF($C3888=1,
(IF(LEN(TRIM(B3894))-LEN(SUBSTITUTE(B3894," ","")) <>3,
"",
LEFT(
MID(
TRIM(B3894),
FIND(
" ",
TRIM(B3894)
) +1,
99
),
FIND(
" ",
MID(
TRIM(B3894),
FIND(
" ",
TRIM(B3894)
)+1,
99
)
)-1
)
)
)
,"")
I think you've got a few too many Mids and Lefts than you need. This is how I've interpreted "Get the word between the first and second spaces of the trimmed value"... Is that right?
VBA-afied:
Function GetMiddleName(rgName As Range) As String
Dim intTrimmed As Integer
Dim intNoSpace As Integer
Dim stTrimmed As String
Dim intFirstSpace As Integer
Dim intSecondSpace As Integer
If rgName.Offset(-6, 1).Value = 1 Then ' This gives the "C3888" from the "B3894"
stTrimmed = Trim(rgName.Value)
intTrimmed = Len(stTrimmed)
intNoSpace = Len(Replace(rgName.Value, " ", ""))
If intTrimmed - intNoSpace <> 3 Then
GetMiddleName = ""
Exit Function
Else
intFirstSpace = InStr(1, stTrimmed, " ")
intSecondSpace = InStr(intFirstSpace + 1, stTrimmed, " ")
GetMiddleName = Mid(stTrimmed, intFirstSpace + 1, intSecondSpace - (intFirstSpace + 1))
Exit Function
End If
Else
GetMiddleName = ""
End If
End Function
Hopefully that gets you started with some ideas for the other formulas... PS the "rept" formula = "string" in VBA (I didn't know there was a rept formula! Nice one!)
That gives me these results:
"Jane Doe (doe.jane#___.com)" = "" (fails the "len - nospaces <> 3" check)
"JOHN DOE, SR (noemail-8858)" = "DOE," (might wanna add a Replace(","...) )
"first second DE surname surname2 (email#_______.com)" = "" (fails the "<>3" check)
"first middle surname (email#_____.net)" = "middle" Works Swimingly?

VBA Getting data to a new worksheet for different format Excel

I'm still new to VBA EXCEL programming.
I need to extract data from one sheet to another in a different format. However, many of the tutorial only seems to extract data rows by rows or range by range to a fresh sheet.
So this is my DataSheet1:
**School Principal Student Student ID**
United College Bill Gates Peter p3214
United College Bill Gates Mary p4213
United College Bill Gates Forge p7621
Beverly High Melin Brad Goge p1111
Beverly High Melin Brad Fred p2222
I want to make the data into a custom format in another datasheet. So here's my desired result:
School United College
Principal Bill Gates
Student Student ID
Peter p3214
Mary p4213
Forge p7621
School Beverly High
Principal Melinda Brad
Student Student ID
Goge p1111
Fred p2222
Below are some of my codes to get from Sheet1 to Sheet2, but the code only shows to get the data from range to range. What are some of the concepts that should be used to extract the data into a custom format? My codes:
Dim secondsheet As Worksheet
Set secondsheet = workbook.Worksheets(2)
Dim firstsheet As Worksheet
Set firstsheet = workbook.Worksheets(1)
secondsheet.Range("A1", "C10").Value = firstsheet.Range("A1", "C10").Value
And the format that I intend to put my data in:
Range(<<call function for range>>).Select
With Selection
.Value = "School"
.Offset(1,0).Value = "Principal"
.Offset(1,0).Font.Bold = True
.Offset(4,1).Value = "Student"
.Offset(4,1).Font.Bold = True
.Offset(4,2).Value = "Student ID"
.Offset(4,2).Font.Bold = True
So the answer I looking for is looping function since it's in this format. Any kind souls are willing to help me understand the concept for vba?
Keep Data in Sheet1 and Run the macro... Small errors are there in my macro.. If u work it out can easily rectify
col1 = Sheet1.Cells(2, 1)
prin1 = Sheet1.Cells(2, 2)
Sheet2.Cells(1, 1) = "School"
Sheet2.Cells(1, 2) = "Principal"
Sheet2.Cells(2, 1) = col1
Sheet2.Cells(2, 2) = prin1
b = 5
c = 1
Sheet2.Cells(b - 1, 1) = "Student"
Sheet2.Cells(b - 1, 2) = "St ID"
a = 3
Do While Sheet1.Cells(a, 1) <> ""
If col1 = Sheet2.Cells(c + 1, 1) Then
Sheet2.Cells(b, 1) = Sheet1.Cells(a, 3)
Sheet2.Cells(b, 2) = Sheet1.Cells(a, 4)
b = b + 1
Else
c = b + 1
b = c + 3
col1 = Sheet1.Cells(a, 1)
prin1 = Sheet1.Cells(a, 2)
Sheet2.Cells(c, 1) = "School"
Sheet2.Cells(c, 2) = "Principal"
Sheet2.Cells(c + 1, 1) = col1
Sheet2.Cells(c + 1, 2) = prin1
Sheet2.Cells(b - 1, 1) = "Student"
Sheet2.Cells(b - 1, 2) = "St ID"
Sheet2.Cells(b, 1) = Sheet1.Cells(a, 3)
Sheet2.Cells(b, 2) = Sheet1.Cells(a, 4)
End If
a = a + 1
Loop

How to create a virtual column on a gridview based on a particular gridview columns

Please i have a project that i query the database using entity framework as my ORM. This is my query
Dim subjectSearch = From subSearch In DemoSchool.EssenceSubjectRegistrations Where subSearch.Session = drpSession.SelectedItem.Text _
AndAlso subSearch.Term = drpTerm.SelectedItem.Text AndAlso subSearch.RealClass.ClassSN = findClassSN.FirstOrDefault AndAlso _
subSearch.SubjectCode = drpSubject.SelectedValue _
Select New With {.SubjectRegSN = subSearch.SubjectRegSN,
.FirstName = subSearch.Student.FirstName,
.Surname = subSearch.Student.Surname,
.CA1 = subSearch.CA1,
.CA2 = subSearch.CA2,
.CA3 = subSearch.CA3,
.CA4 = subSearch.CA4,
.CA5 = subSearch.CA5}
Then i query my result so that i can be able to do some operation on it by doing this
Dim secSubjectSearch = (From jamie In subjectSearch Select jamie).ToList() _
.Select(Function(jamie) New With {.SubjectRegSN = jamie.SubjectRegSN,
.FirstName = jamie.FirstName,
.Surname = jamie.Surname,
.CA1 = jamie.CA1,
.CA2 = jamie.CA2,
.CA3 = jamie.CA3,
.CA4 = jamie.CA4,
.CA5 = jamie.CA5,
.MidTerm = CDbl(jamie.CA1 + jamie.CA2 + jamie.CA3 + jamie.CA4 + jamie.CA5) / 5})
The result of the second query is bounded to the gridview which renders properly as it is suppose to rendered. My problem is that i want to create a virtual column called Rank on the gridview after the .MidTerm bounded column that will display the position of each person record in the search result.
NAME CA1 CA2 CA3 CA4 CA5 MIDTERM RANK
James 50 50 60 40 60 52 3
Essty 100 50 50 50 50 60 2
Markus 100 40 50 60 50 60 2
Code 100 100 100 100 50 90 1
Above is a format of the gridview columns. I want column Rank to be a virtual column that is calculated based on the Midterm score of the students.Code VB scored 90 so his rank so be 1 and so on.Please i don't know how to calculate this rank column and the code to get the highest and the smallest.Really i need help thanks
Two ways.
Use Unbound column and calculate/display the rank
Have a RANK field and pre-calculate it and bound it, something like:
Dim secSubjectSearch = (From jamie In subjectSearch Select jamie).ToList() _
.Select(Function(jamie) New With {.SubjectRegSN = jamie.SubjectRegSN,
.FirstName = jamie.FirstName,
.Surname = jamie.Surname,
.CA1 = jamie.CA1,
.CA2 = jamie.CA2,
.CA3 = jamie.CA3,
.CA4 = jamie.CA4,
.CA5 = jamie.CA5,
.MidTerm = CDbl(jamie.CA1 + jamie.CA2 + jamie.CA3 + jamie.CA4 + jamie.CA5) / 5,
.RANK = -1}).ToList()
dim sorted = secSubjectSearch.Select(function(n) n.MidTerm).Distinct().OrderByDescending(function(n) n).ToList()
for each itm in secSubjectSearch
itm.RANK = sorted.IndexOf(itm.MidTerm) + 1
next
-- Not tested, wrote it with notepad...