Iterate and Update same Collection in VBA - vba

My requirement is to iterate through a VBA collection , and based on certain
condition update the subsequent records in the same collection.
For example lets say "TMasterList" is a collection which has total of 4 records ,
while 2nd record gets processed in the below loop,
I need to update 3rd and 4th record and then continue with the loop(ie process 3 and 4th).
For Each objEachTmapping In TMasterList
Next
Any suggestions on how to implement it.

Loop over the index, checking the bounds if needed:
Dim i As Long, max As Long
max = TMasterList.Count
For i = 1 To max
TMasterList.Item(i).value = Foo
If i + 1 < max Then TMasterList.Item(i + 1).value = Bar
If i + 2 < max Then TMasterList.Item(i + 2).value = Qux
Next
This assumes that there is a reference in the collection, if its a type it cannot be modified in situ.

Related

Read number of characters in a column of a GuiTableControl object

I'm trying to read the number of characters in column "MRP element data" in tcode MD04.
Below code is giving me 1 but I want it to give 16 or it should give 16 provided that my code is right...If there is one more row with one more Purchase Order it should give 32 etc.
j = 0
Do
session.findById("wnd[0]/usr/subINCLUDE1XX:SAPMM61R:0750/tblSAPMM61RTC_EZ/txtMDEZ-EXTRA[5," & CStr(j) & "]").caretPosition = 0
objSheet.Cells(i, 2) = Len(Cstr(j))
Exit Do
j =j + 1
Loop
You currently calculate the length of the integer variable j which contains the value 0, it's why you get 1.
The table element you show is a GuiTableControl object. You will find the method GetCell to read the content of a cell, and after that you can calculate the length of its value.
Set tableControl = session.findById("wnd[0]/usr/subINCLUDE1XX:SAPMM61R:0750/tblSAPMM61RTC_EZ")
MsgBox Len(tableControl.GetCell(1,5).Text)
(row 1 = second row; column 5 = sixth column)

I'm trying to sum the number of rows that are not nothing. IF the row count is 2, but LastNAme (row 2) is Nothing, i need to return 1

I'm trying to get an accurate count of borrowers on a loan. The system I'm working in automatically creates 2 rows for each application we enter. I want to return the sum of rows that are not nothing.
I'm looking at the borrower last name. So if we have two applications on the loan file, our system automatically creates 4 rows. However, the borrower last name field in row 4 is nothing. I want to return 3 since the borrower last name field in rows 1, 2 and 3 is not nothing
I'm fairly new to VB.NET and am trying to use a For Loop to count each row when the last name is not nothing.
Dim i As Integer
Dim BrwrCT = GetFieldRowCount(144)
For i = 1 To BrwrCT
If GetFieldValue(144,i) IsNot Nothing
Return 1 + BrwrCT
Else Return BrwrCT
End If
Next i
For this example, the loan file has 3 borrowers and the result should be returning 3, however, I am receiving 5 (BrwrCT + 1)
In your For/Next loop you set the max loop to be BrwrCT and then inside of the loop you are modifying the value of that same variable BrwrCT. You should avoid modifying the loop range inside of the loop doing that range. You should also not use the Return statement inside of the loop unless you actually want to leave that loop immediately without performing all of the iterations of that loop. In your sample code, this loop would only ever execute once and then immediately exit (aka Return).
I recommend creating a second variable that will have the count you are looking for:
Dim i As Integer
Dim BrwrCT = GetFieldRowCount(144)
Dim totalBorrowers As Integer
For i = 1 To BrwrCT
If GetFieldValue(144,i) IsNot Nothing Then
totalBorrowers += 1
End If
Next i
Return totalBorrowers

Ranking a dynamic table range by size

I have a dynamic table range of certain values (amounts). These amounts are generated into the table through a macro I've created.
What I want to do: Rank these amounts into the empty column by number.
eg. the cell in Column G next to 89k would be ranked as 1, one next to 77k would be 2 etc.
I also already have other functions defined, which I'm not going to explain here for readability reasons, but all you need to know: there are two variables obtained through functions
tbl_first = (int) Index of the ListRow of the first table item (so in this case it would be the row with 89k = 1st row so in this example 1)
tbl_last = (int) same as above, but indexes the last row (77k) in this example as 7
so my code is the following
' sets the tbl variable to the red table in the picture
Dim tbl As ListObject: Set tbl = Sheets("Summary").ListObjects("time_top")
Dim pos As Integer, diff as integer
diff = tbl_last - tbl_first
For j = tbl_first To tbl_last ' loops through all the added rows
For n = 1 to diff' indexing for the large function
' index the pos through the excel large function for our values (should return the k-th position from the largest value)
pos = Application.WorksheetFunction.Large(Range(Cells(tbl_first, 6), Cells(tbl_last, 6)), n)
With tbl.ListRows(1)
.Range(j, 6) = pos ' add the value to the column G to the right
End With
Next n
Next j
So the expected result would look like this:
I also keep getting the following error, which is caused by me incorrectly assigning the pos value.
Either way, probably multiple of things wrong here and much more elegant solution is out there, that just didn't hit me yet.
Think you need Rank (watch out for equal ranks). Large returns the nth largest value of a set.
Here is a simple example on a two column table which perhaps you can adapt. The rank is added in the second column.
Sub xx()
Dim tbl As ListObject: Set tbl = Sheets("Summary").ListObjects("time_top")
Dim r As Range
For Each r In tbl.ListColumns(1).DataBodyRange
r.Offset(, 1) = WorksheetFunction.Rank(r, tbl.ListColumns(1).DataBodyRange)
Next r
End Sub

excel macro filter, delete and sort

I want a create a macro that filters,deletes & sorts values.
Let there be 4 columns:
Serial No
Data
Amount
ID (Numeric)
The macro should
delete all rows having amount=0.
Reassign serial no because now there are fewer rows than before.
Sort the data according to ID
Unable to proceed with creation. Help will be greatly appreciated!
This seems to be a basic question, and it does not seem to need a universal solution, but rather 2 loops and then as sort call... Try looping (for or while) over the records to delete rows such as:
Sub macro1()
ColumnWithSerial = 1
ColumnWithID = 4
ColumnWithAmounts = 3
'loop over column with IDs
Dim i As Long, tempID As Long
i = 3 'variable to loop = set to 1st row with data (after header)
tempID = 1 'variable to update IDs
Do While Len(Sheets("Sheet1").Cells(i, ColumnWithID).Value) > 0
Sheets("Sheet1").Cells(i, ColumnWithSerial).Value = tempID
If Sheets("Sheet1").Cells(i, ColumnWithAmounts).Value = 0 Then
Sheets("Sheet1").Cells(i, ColumnWithAmounts).EntireRow.Delete
Else
tempID = tempID + 1
End If
i = i + 1
Loop
'now call sort method (easy to record and then adapt) (make sure to use sort and not filter)
End Sub
This should generally do the job, unless there is some parameter that needs specifying...

vb excel keep 1 instance of duplicate items in a range

Hi I am using VB to populate data in excel. In the sheet, the column G has many cells with same numbers(and they are repeated without following any pattern). First I would like to find which entries are not unique and then keep the first occurrence in the column & delete the entire rows where repetitions are encountered. Here's an example:
As can be seen from the image, in the column G, numbers 1000 & 2200 are repeated. So need to delete entire rows 3 and 6 (keeping rows 1 & 2 where 1000 & 2200 appear first).
Here's the code which I can't get to work:
Sub Dupli()
Dim i As Long, dic As Object, v As Object
dic = CreateObject("Scripting.Dictionary")
i = 1
For Each v In sheet.UsedRange.Rows
If dic.exists(v) Then sheet.Rows(v).EntireRow.Delete() Else dic.Add(v, i)
i = i + 1
Next v
End Sub
Try something like this. I don't think you need a dictionary (unless there is some other need for it elsewhere in your code). When deleting objects, it's usually necessary to iterate backwards over the collection. This method just uses the CountIf function to test whether the cell value in column G of a specific row occurs more than once in all of column G, and deletes the row if that condition is true.
Sub Dupli()
Dim i As Long
Dim cl as Range
i = 1
For i= sheet.UsedRange.Rows.Count to 1 Step -1
Set cl = sheet.Cells(i,7) '## Examine the cell in Column G
If Application.WorksheetFunction.CountIf(sheet.Range("G:G"),cl.Value) > 1 Then
sheet.Rows(i).EntireRow.Delete
Next
End Sub
Put this in H1:
=COUNTIF(G$1:G1;G1)
Fill down to end
Make an autofilter on column G
Filter out values of 1
Select the remaining rows by row header
Right click on row header > click Delete ...