Summing records in VBA Collection - linq

I have a VBA collection consisting of DayTots class objects (see below)
I am using a For Each to iterate thru the collection to create a
new collection consisting of summed records, based on Date
Is there some way I could do this with Linq? I suspect maybe I could replace
several lines of code with something much simpler and more straightforward
using a Linq query (maybe using a Group?)
I couldn't find anything on the internet that seemed to address this situation
Thanks in advance for all assistance
input collection
tDate TotTrav TotTrav TotParts
Yes No Accepted
2/27/2017 1 0 1
2/27/2017 1 0 0
2/27/2017 1 0 0
2/27/2017 0 1 0
2/28/2017 1 0 1
2/28/2017 0 1 0
2/28/2017 0 0 1
output collection
DatDate TotTrav TotTrav TotParts
Yes No Accepted
2/27/2017 3 1 1
2/28/2017 1 1 2
Dim cumRecs As DayTots
dim incoll, outcoll as Collection
outcoll = New Collection
For Each irec In incoll
....
outcoll.Add(cumRecs)
Next irec
'Class DayTots
Dim DatDate As Date
Dim TravYes As Integer
Dim TravNo As Integer
Dim PartsAccepted As Integer
Public Property Get tDayDate() As Date
tDayDate = DatDate
End Property
Public Property Let tDayDate(value As Date)
DatDate = value
Weekno = Int(((DatDate - DateSerial(Year(DatDate), 1, 0)) + 6) / 7)
End Property
Public Property Get TotTravYes() As Integer
TotTravYes = TravYes
End Property
Public Property Let TotTravYes(value As Integer)
TravYes = value
End Property
Public Property Get TotTravNo() As Integer
TotTravNo = TravNo
End Property
Public Property Let TotTravNo(value As Integer)
TravNo = value
End Property
Public Property Get TotPartsAccepted() As Integer
TotPartsAccepted = PartsAccepted
End Property
Public Property Let TotPartsAccepted(value As Integer)
PartsAccepted = value
End Property

What you are hoping for can be achieved with Array and WorksheetFunction.Sum Here is a small example:
Option Explicit
Public Sub TestMe()
Dim inColl As New Collection
Dim inArr As Variant
inColl.Add 1
inColl.Add 2
inColl.Add 3
Debug.Print WorksheetFunction.Sum(inColl.Item(1), inColl.Item(2), inColl.Item(3))
inArr = Array(5, 6, 7, 8)
Debug.Print WorksheetFunction.Sum(inArr)
End Sub
The result in the immediate window is 6 and 26. In general, it is not difficult to convert collection to array.

Related

Visual Basic 6.0 disable checkbox on datagrid

I have a datagrid table with a text on first column and a checkbox on second column. I would like to disable this checkbox when first column value is "Others". Is this possible?
Thanks in advance!!
You can set properties for the entire grid. You can set properties for an entire column. You can even set a few properties for a cell, but one of those properties is not an enabled property. The best I was able to come up with was responding to the following event:
Private Sub DataGrid1_RowColChange(LastRow As Variant, ByVal LastCol As Integer)
If DataGrid1.Col = 1 Then
DataGrid1.Col = DataGrid1.Col - 1
If DataGrid1.Text = "Others" Then
DataGrid1.Col = LastCol
DataGrid1.Row = LastRow - 1
Exit Sub
End If
DataGrid1.Col = DataGrid1.Col + 1
End If
End Sub
This logic prevents focus on a cell in column 2 if column 1 is "Others". Keep in mind that rows and columns are 0-based.

How to check if array value exists in Cell?

I am new to vbscript and I am creating a script to reduce my day by day duplicate efforts. I have a column in an excel sheet which holds values. There are certain cells under this column where multiple values exists. Now I have an array which has some values which needs to be looked up / searched within each row under this column and delete the row if array values are not present within the row.
I tried to search the array values in the rows using InStr function and it worked if cell contains only one value. Code is attached below.
This sub is not working as expected if cell contains multiple values. e.g. Project 1 [ALT + ENTER] Dummy Project
Hence I tried to use Find and Search methods. I am unable to get the expected results using these methods too.
Fix Version/s
Row 1 - Project 3 a
Row 2 - Project 2 'spaces at the end
Row 3 - Project 4
---------
Project 1
Row 4 - Project 5
Row 5 - Project 1
Find method - No rows deleted
Replace method - Getting syntax error where I used Search method in place of InStr function as below,
If objWorksheet1.Cells(iDelCnt, fixVerColNum).Search(objWorksheet1.Cells(iDelCnt, fixVerColNum).Value, projectFilter(jDelCnt)) <> 0 Then
Please assist. Thanks in advance.
Expected - I expect row 'x' to be deleted if array value doesn't exists in Cells(x,y)
Dim objExcel, objWorkbook, objWorksheet1
Dim iDelCnt, jDelCnt, projectFilter, lRow, fixVerColNum, tempCell, deleteCounter, InStrTest
Set objExcel = CreateObject("Excel.Application")
objExcel.Application.Visible = True
Set objWorkbook = objExcel.Workbooks.Open(filePath) ' Location of the file on drive
Set objWorksheet1 = objWorkbook.Worksheets(1)
projectFilter = Array("Project 1","Project 2", "Project 3")
fixVerColNum = objExcel.Match("Fix Version/s", objWorksheet1.Range("A1:T1"), 0) 'Identify "Fix Version(s)" column number
lRow = objWorksheet1.Range("A1").CurrentRegion.Rows.Count
deleteCounter = 0
For iDelCnt = lRow to 2 Step -1
For jDelCnt = LBound(projectFilter) to UBound(projectFilter)
If InStr(1, objWorksheet1.Cells(iDelCnt, fixVerColNum).Value, projectFilter(jDelCnt), 1) <> 0 Then
deleteCounter = 1
Exit For
Else
deleteCounter = 0
End If
Next
If deleteCounter = 0 Then
objWorksheet1.Rows(iDelCnt).EntireRow.Delete
End If
Next

Filter generic list (comma separated values)

I want to filter list as below. I have a class & I want to filter values from that are in my filter string. I have achieved my result by a for loop but need a way without for loop.
Public Class WorkStationDetails<br><br>
Property CountryId As Integer<br>
Property CountryName As String<br>
Property TotalWrkStn As Integer<br>
Property ExistingWrkStn As Integer<br>
Property RemainingWrkStn As Integer<br><br>
End Class
Dim WrkStnDtl As List(Of WorkStationDetails)
Dim FilterWrkStnDtl As List(Of WorkStationDetails)
Dim Numbers As String()
Numbers = "1,5,6,2,9".Split(",")
For i As Integer = 0 To Numbers.Length - 1
FilterWrkStnDtl.AddRange(WrkStnDtl.FindAll(Function(p) (p.CountryId = Numbers(i))))
Next
Note: I want to achieve it like subquery in sql server.
I think you want something like this"
var numbers = "1,5,6,2,9".Split(',');
var selected = WrkStnDtl.Where(w => numbers.Contains(w.CountryId)).ToList();

strange behaviour of linq usage

I have two tables (t1 and t2) and I select two fields from this tables (f1 and f2).
The list Queries contains the selected data. In this case there are 2 entry with 2 rows.
This is the code:
Dim FieldIndexes As New List(Of Integer)
Dim Queries As New List(Of IEnumerable(Of Object()))
For i = 0 To _SqlSyntaxChecker.QueriedTables.Count - 1
FieldIndexes.Clear()
For j = 0 To _SqlSyntaxChecker.DataFields.Count - 1
If _SqlSyntaxChecker.QueriedTables(i).TableName = _SqlSyntaxChecker.DataFields(j).TableName Then FieldIndexes.Add(_SqlSyntaxChecker.DataFields(j).FieldIndexInDataTable)
Next
Dim query = _SqlSyntaxChecker.QueriedTables(i).Rows.Select(Function(Row) FieldIndexes.Select(Function(FieldIndex) Row.Item(FieldIndex)).ToArray)
Queries.Add(query)
For Each item In Queries(i)
_OutputDataTable.Rows.Add(item)
Next
Next
And this is the result:
As you see, everything is ok, I expected this result (it is now not important, that I have on the image 4 rows in one column).
Originally, I wanted to populate the _OutputDataTable outside the for cykle, like so:
Dim FieldIndexes As New List(Of Integer)
Dim Queries As New List(Of IEnumerable(Of Object()))
For i = 0 To _SqlSyntaxChecker.QueriedTables.Count - 1
FieldIndexes.Clear()
For j = 0 To _SqlSyntaxChecker.DataFields.Count - 1
If _SqlSyntaxChecker.QueriedTables(i).TableName = _SqlSyntaxChecker.DataFields(j).TableName Then FieldIndexes.Add(_SqlSyntaxChecker.DataFields(j).FieldIndexInDataTable)
Next
Dim query = _SqlSyntaxChecker.QueriedTables(i).Rows.Select(Function(Row) FieldIndexes.Select(Function(FieldIndex) Row.Item(FieldIndex)).ToArray)
Queries.Add(query)
Next
For Each q In Queries
For Each item In q
_OutputDataTable.Rows.Add(item)
Next
Next
But as you see, the result is wrong:
The result should be the same.
What can cause this?
Your query is linked to i field (using closures). But queries are execute after first cycle, so i already have its last value when query is executed.
You can check "Access to modified closure" topic over internet (mainly it's about delegates but actually same thing works for expression trees).

Excel VBA Macro for Pivot Table with Dynamic Data Range

CODE IS WORKING! THANKS FOR THE HELP!
I am attempting to create a dynamic pivot table that will work on data that varies in the number of rows. Currently, I have 28,300 rows, but this may change daily.
Example of data format as follows:
Case Number Branch Driver
1342 NYC Bob
4532 PHL Jim
7391 CIN John
8251 SAN John
7211 SAN Mary
9121 CLE John
7424 CIN John
Example of finished table:
Driver NYC PHL CIN SAN CLE
Bob 1 0 0 0 0
Jim 0 1 0 0 0
John 0 0 2 1 1
Mary 0 0 0 1 0
Code as follows:
Sub CreateSummaryReportUsingPivot()
' Use a Pivot Table to create a static summary report
' with model going down the rows and regions across
Dim WSD As Worksheet
Dim PTCache As PivotCache
Dim PT As PivotTable
Dim PRange As Range
Dim FinalRow As Long
Dim FinalCol As Long
Set WSD = Worksheets("PivotTable")
'Name active worksheet as "PivotTable"
ActiveSheet.Name = "PivotTable"
' Delete any prior pivot tables
For Each PT In WSD.PivotTables
PT.TableRange2.Clear
Next PT
' Define input area and set up a Pivot Cache
FinalRow = WSD.Cells(Application.Rows.Count, 1).End(xlUp).Row
FinalCol = WSD.Cells(1, Application.Columns.Count). _
End(xlToLeft).Column
Set PRange = WSD.Cells(1, 1).Resize(FinalRow, FinalCol)
Set PTCache = ActiveWorkbook.PivotCaches.Add(SourceType:= _
xlDatabase, SourceData:=PRange)
' Create the Pivot Table from the Pivot Cache
Set PT = PTCache.CreatePivotTable(TableDestination:=WSD. _
Cells(2, FinalCol + 2), TableName:="PivotTable1")
' Turn off updating while building the table
PT.ManualUpdate = True
' Set up the row fields
PT.AddFields RowFields:="Driver", ColumnFields:="Branch"
' Set up the data fields
With PT.PivotFields("Case Number")
.Orientation = xlDataField
.Function = xlCount
.Position = 1
End With
With PT
.ColumnGrand = False
.RowGrand = False
.NullString = "0"
End With
' Calc the pivot table
PT.ManualUpdate = False
PT.ManualUpdate = True
End Sub
They changed the object model for PivotCaches. The method you need in 2007-2010 (that use VBA version 7 instead of version 6) is
PivotCaches.Create
Any reason you are using VBA other than the changing number of rows?
If you are using Excel 2007 / 2010, create a regular table /list (Ctrl-L) from your original data. You can give it a name as well. Then create a Pivot Table and use the table name as the data source. As you add rows your table will expand and you can then just refresh the Pivot Table (F5, or using VBA).
If you are in Excel 2003, you can create dynamic named ranges as well. It's slightly more complex (and a lot more ugly) but I can walk you through it if you are stuck on an older version.

Resources