Declaring Variables in VBA to analyze Strings (But offset to see numbers!) - vba

In the following code I have declared c to be used, but it seems as though it only works with numbers. I am looking for a string to compare with another string in another table on the same sheet.
The catch that makes this tricky is that I would like to offset the value to the cell adjacent to the left, and then compare one date with another. To make it more clear, my data is formatted like this: (Call it SetA)
A B C D E F G H I
CreateTime LotID AnalysisSet Slot# X Y ResultType TermName ResultName
A few more columns to the right.... Lets call this SetB
Y Z AA AB AC AD AE AF AG
CreateTime LotID AnalysisSet Slot# X Y ResultType TermName ResultName
Here is the code:
Sub AIM36DBOCompare()
Dim n As Integer
n = 2
Dim PasteCount As Integer
Dim test1 As Long
Dim test2 As Long
PasteCount = 41
Range("AD2:AD1000").Copy Destination:=Range("S41" & Lastrow)
Do While n <= 1000
If Cells(26, n) <> 0 Then
'--------------------------------------------
With Worksheets(1).Range("b2:b10000")
Set c = .Find(Cells(n, 26).String, LookIn:=xlValues)
If Not c Is Nothing Then
Do
test1 = Cells(n, 25).Value
test2 = c.Offset(0, -1)
If Abs(Cells(n, 25) - c.Offset(0, -1)) <= 100 Then
c.Offset(0, -1).Copy
Cells(PasteCount, 17).Select
Selection.Paste
PasteCount = PasteCount + 1
Exit Do
End If
Set c = .Find(Cells(n, 26).Value, LookIn:=xlValues)
Loop While Not c Is Nothing
End If
End With
'--------------------------------------------
End If
If Cells(11, n) = 0 Then
Exit Do
End If
n = n + 1
Loop
End Sub
So to be more clear here is the code: Find LotID in SetB, find the first (of multiple) corresponding LotID in SetA. Compare date in SetB to the date in SetA by offsetting the variable by one cell and then subtracting the two (using absolute value).
If it is under 100 days, then do stuff!
Its not doing stuff :(. The date in SetA is showing up as nothing. I think it is because of the variable being used. Please help!
The code fails at Test2 (and consequently) in the "if test" If Abs(Cells(n, 25) - c.Offset(-1, 0)) <= 100 Then

You mentioned that you want to take the cell to the left of c. In the code, you are getting the value from the cell above. To see this, try the code below:
Sub test()
Dim add As String
Dim c As Range
Dim offsetRange As Range
Set c = Range("B2")
Set offsetRange = c.Offset(-1, 0)
add = offsetRange.Address
Debug.Print add
Debug.Print offsetRange.Value
End Sub
Offset takes rows first, then columns, so you would want to swap to 0 and -1, as below:
Sub test2()
Dim add As String
Dim c As Range
Dim offsetRange As Range
Set c = Range("B2")
Set offsetRange = c.Offset(0, -1)
add = offsetRange.Address
Debug.Print add
Debug.Print offsetRange.Value
End Sub
Also, you are declaring and getting the values for the variables test1 and test2, but you are not using these values when doing the comparison.

Related

VBA Excel, Compare strings from cells

i have problem with my VBA app. At the ssheet1 i have names in format Curry,Steph and every name is having an id. At changedNames i have the same names but in other format which is Steph Curry again with optional id which is the same as Curry,Steph. How can i make the names that i enter like Curry,Steph to change to the other type Steph Curry and to be with the same id. Also when i do the removeDuplicates method, its removing a digit from the id but the thing i want its to delete the row. Thanks in advance!
Sub GenerateNames()
Dim ssheet1 As Worksheet
Dim rngen As Worksheet
Dim rnsheet As Worksheet
Dim changedNames As Worksheet
Set ssheet1 = ThisWorkbook.Sheets("Sheet1")
Set rngen = ThisWorkbook.Sheets("RnGen")
Set rnsheet = ThisWorkbook.Sheets("RandomNames")
Set changedNames = ThisWorkbook.Sheets("ChangedNames")
rngen.Range("A3:A70").Copy rnsheet.Range("A3:A70")
ssheet1.Range("B3:B70").Copy rnsheet.Range("B3:B70")
For b = 1 To 70
For c = b + 1 To 70
If Cells(b, 2).Value = Cells(c, 2).Value Then
Cells.RemoveDuplicates
End If
Next c
Next b
End Sub
You could try something like this:
Not tested:
For b = 70 To 1 step (-1)
For c = 70 to b + 1 step (-1)
If Cells(b, 2).Value = Cells(c, 2).Value Then
Cells(c,2).row.delete
End If
Next c
Next b

Find all non-zero cells in a given range and list their addresses in another sheet

I have a gigantic table in excel(720x720) in which I want to find non-zero values. when the value is found I would like to get the first two cells of this row on a new sheet on two columns, the cell in question on a third and the first two cells in the columns of the cell I'm looking for on two other columns.
For example if my values are in E26 R89 and Z9 on sheet 1 I would like to get a table on sheet 2 that would look like this:
A B C D E
1 A26 B26 E26 E1 E2
2 A89 B89 R89 R1 R2
3 A9 B9 Z9 Z1 Z2
Here is what I've tried so far (please bear in mind that you are talking to a beginner)
Sub tests_selection()
Dim r As Worksheet
Dim c As Workbook, f As Worksheet
Set c = Workbooks("classeur1")
Set f = c.Worksheets("feuil1")
Dim a(5200)
Dim b
b = 0
Range("A1:AAU723").Select
For i = 4 To 720
For j = 4 To 723
If f.Cells(i, j).Value <> 0 Then
a(b) = f.Cells(i, j).Adress
b = b + 1
End If
Next j
Next i
Set r = c.Worksheets("result")
For i = 0 To b
r.Cells(i, 1).Value = a(i)
Next i
End Sub
Table example
Result example
First of all you should use meaningful variable names instead of 1 character only. This makes your code much more understandable and readable and therefore results in less bugs.
Also use Option Explicit to force proper variable declaring.
Option Explicit
Sub tests_selection()
Dim SrcWs As Worksheet
Set SrcWs = Worksheets("feuil1") 'source worksheet
Dim ResultWs As Worksheet
Set ResultWs = Worksheets("result") 'result worksheet
Dim rRow As Long
rRow = 2 'start row in result sheet
Dim iCell As Range
For Each iCell In SrcWs.Range("C4:AN40") '<-- make sure to adjust the range to the data only! so header rows are not included
If iCell.Value <> 0 Then
ResultWs.Cells(rRow, 1).Value = SrcWs.Cells(iCell.Row, 1).Value
ResultWs.Cells(rRow, 2).Value = SrcWs.Cells(iCell.Row, 2).Value
ResultWs.Cells(rRow, 3).Value = iCell.Value
ResultWs.Cells(rRow, 4).Value = SrcWs.Cells(1, iCell.Column).Value
ResultWs.Cells(rRow, 5).Value = SrcWs.Cells(2, iCell.Column).Value
rRow = rRow + 1
End If
Next iCell
End Sub

For loop with multiple variables

Here is a excel vba sub procedure example. I have two columns of data, range v and range c - How could I concatenate each cell rows' value with the parallel row call value.
Ideally, what I am trying to do would be this
For Each c,b In v,bb
...
next c,b
Pleas let me further explain: cell G2 value is only related to J2, and G3 with J3
G2 value = Blue
J2 value = Spaghetti
I am trying to return "Blue Spaghetti" with one for loop?
G2 value = Red
J2 value = Noodles
I am trying to return "Red Noodles" with one for loop?
Dim c As Variant
Dim b As Variant
Dim v As Range
Dim bb As Range
Dim brow As Long
Dim vrow as long
Set v = ActiveSheet.Range("G:G")
vrow = v(v.Cells.Count).End(xlUp).Row
Set v = Range(v(2), v(brow))
Set bb = ActiveSheet.Range("J:J")
brow = bb(bb.Cells.Count).End(xlUp).Row
Set bb = Range(bb(2), bb(brow))
For Each c In v
c = Mid(c, 1, 4)
msgbox c
Next c
For each b in bb
msgbox b
next b
Looking at your original post, I'm going to say I'm confused with all the extra stuff. Look at what goes on here, and comment with questions. I think you are over complicating what you are attempting.
Sub ConcatCols()
Dim lastRow As Long
Dim tempValue As String
lastRow = Sheets("Sheet1").Range("A" & Rows.Count).End(xlUp).row
For iRow = 2 to lastRow
tempValue = Sheets("Sheet1").Cells(iRow, "G").Text & " " & _
Sheets("Sheet1").Cells(iRow, "J").Text
MsgBox tempValue
Next iRow
End Sub

Using SUMIFS to add time duration always gives 00:00:00

Sub Add_sumf()
Dim i As Integer
i = 3
Dim cellDate As Integer
cellDate = 0
Dim cellDate1 As Date
cellDate1 = TimeValue("00:00:00")
Dim total As Integer
total = 0
Dim j As Integer
j = 2
Dim k As Integer
k = 2
Set aa = Workbooks("Book3").Worksheets(1)
Set bb = Workbooks("Final_result").Worksheets(1)
Do While bb.Cells(1, k).Value <> ""
For Each y In bb.Range("A:A")
On Error GoTo Label
If UCase(bb.Cells(j, "A").Value) <> "" Then
cellDate1 = WorksheetFunction.SumIfs(aa.Range("F:F"), aa.Range("B:B"), UCase(bb.Cells(1, k).Value), aa.Range("G:G"), UCase(bb.Cells(j, "A").Value))
bb.Cells(j, k).Value = TimeValue(cellDate1)
cellDate1 = TimeValue("00:00:00")
bb.Cells(j, k).NumberFormat = "[h]:mm:ss"
On Error GoTo Label
j = j + 1
Else
Exit For
End If
Next
j = 2
k = k + 1
Loop
Label:
'MsgBox Err.Description
Exit Sub
End Sub
I am using above code to add time duration based upon value of two other columns but I always get 00:00:00 as result.
if i use below code i get the answer but its too slow very slow
Sub add_it_time()
Dim i As Integer
i = 3
Dim cellDate As Integer
cellDate = 0
Dim cellDate1 As Date
cellDate1 = TimeValue("00:00:00")
Dim total As Integer
total = 0
Dim j As Integer
j = 2
Dim k As Integer
k = 2
Set aa = Workbooks("Book3").Worksheets(1)
Set bb = Workbooks("Final_result").Worksheets(1)
Do While bb.Cells(1, k).Value <> ""
'MsgBox bb.Cells(1, k).Value
For Each y In bb.Range("A:A")
On Error GoTo Label
' MsgBox UCase(bb.Cells(j, "A").Value)
If UCase(bb.Cells(j, "A").Value) <> "" Then
For Each x In aa.Range("F:F")
On Error Resume Next
If UCase(aa.Cells(i, "B").Value) = UCase(bb.Cells(j, "A").Value) Then
' MsgBox aa.Cells(i, "F").Text
' total = total + Int(get_Second(aa.Cells(i, "F").Text))
If UCase(aa.Cells(i, "G").Value) = UCase(bb.Cells(1, k).Value) Then
'MsgBox aa.Cells(i, "F").Text
cellDate1 = cellDate1 + TimeValue(aa.Cells(i, "F").Value)
End If
End If
i = i + 1
Next
i = 3
On Error GoTo Label
bb.Cells(j, k).NumberFormat = "h:mm:ss"
bb.Cells(j, k).Value = WorksheetFunction.Text(cellDate1, "[hh]:mm:ss")
total = 0
cellDate1 = 0
j = j + 1
Else
Exit For
End If
Next
j = 2
k = k + 1
Loop
Label:
'MsgBox Err.Description
Exit Sub
End Sub
The source column which contains date is of general formatt
I am new to VBA macros
UPDATED SOLUTION:
After discussion in chat with OP it was decided that pure formula solution is fine - below are formulas / actions to do on the separate sheet starting A1:
Row A will be resulting table header: in A1 I added Agent Name / Release Code, and starting B1 there's a list of all available Release Code values (easily got using Remove Duplicates).
I defined the following named ranges for the simplicity and effectiveness (since initial data is NOT static): AgentNames=OFFSET('Agent State'!$B$2,0,0,COUNTA('Agent State'!$B:$B)-1,1) - this will return the range of names on the initial sheet excluding the header; TimeInStateData=OFFSET(AgentNames,0,4) and ReleaseCodes=OFFSET(AgentNames,0,5) as shifted AgentNames range.
In column A we should obtain the list of names, which should be unique, so select in column A any number of cells which is NOT less that number of unique names - for the sample I used A2:A51, and type that formula: =IFERROR(INDEX(AgentNames,SMALL(IF(MATCH(AgentNames,AgentNames,0)=ROW(INDIRECT("1:"&ROWS(AgentNames))),MATCH(AgentNames,AgentNames,0),""),ROW(INDIRECT("1:"&ROWS(AgentNames))))),"") and press CTRL+SHIFT+ENTER instead of usual ENTER - this will define a Multicell ARRAY formula and will result in curly {} brackets around it (but do NOT type them manually!).
B2: =IF(OR($A2="",SUMPRODUCT(--($A2=AgentNames),--(B$1=ReleaseCodes),TIMEVALUE(TimeInStateData))=0),"",SUMPRODUCT(--($A2=AgentNames),--(B$1=ReleaseCodes),TIMEVALUE(TimeInStateData))) - normal formula, which will return empty value for either empty name or zero time.
Copy formula from B2 to the whole table.
Remarks:
Resulting range for the sum of time values should be formatted as Time.
If the list of names should be expanded in the future - repeat step 3 for the new range, but do NOT drag the formula down - this will result in You cannot change part of an array error.
Sample file: https://www.dropbox.com/s/quudyx1v2fup6sh/AgentsTimeSUM.xls
INITIAL ANSWER:
Perhaps that's too simple and obvious, but at a glance I don't understand why you have that line of code:
cellDate1 = TimeValue("00:00:00")
right after your SUMIFS: cellDate1 = WorksheetFunction.SumIfs(aa.Range("F:F"), ...
Try to remove the first one where you assign zeros to cellDate1.

Excel VBA Loop on columns

when we are going to do a loop in the rows, we can use code like the following:
i = 1
Do
Range("E" & i & ":D" & i).Select
i = i + 1
Loop Until i > 10
but what if we want to do a loop on a column?
Can we use the same method as above?
while the columns in Excel is a complex such as A, B, C, ..., Y, Z, AA, AB, AC, ..., etc.
problems will arise between loop from the "Z" to the "AA".
how we do looping alphabet column from "A" to "Z" and then continued into "AA", "AB" and so on
is there anything that can help?
Yes, let's use Select as an example
sample code: Columns("A").select
How to loop through Columns:
Method 1: (You can use index to replace the Excel Address)
For i = 1 to 100
Columns(i).Select
next i
Method 2: (Using the address)
For i = 1 To 100
Columns(Columns(i).Address).Select
Next i
EDIT:
Strip the Column for OP
columnString = Replace(Split(Columns(27).Address, ":")(0), "$", "")
e.g. you want to get the 27th Column --> AA, you can get it this way
Another method to try out.
Also select could be replaced when you set the initial column into a Range object. Performance wise it helps.
Dim rng as Range
Set rng = WorkSheets(1).Range("A1") '-- you may change the sheet name according to yours.
'-- here is your loop
i = 1
Do
'-- do something: e.g. show the address of the column that you are currently in
Msgbox rng.offset(0,i).Address
i = i + 1
Loop Until i > 10
** Two methods to get the column name using column number**
Split()
code
colName = Split(Range.Offset(0,i).Address, "$")(1)
String manipulation:
code
Function myColName(colNum as Long) as String
myColName = Left(Range(0, colNum).Address(False, False), _
1 - (colNum > 10))
End Function
If you want to stick with the same sort of loop then this will work:
Option Explicit
Sub selectColumns()
Dim topSelection As Integer
Dim endSelection As Integer
topSelection = 2
endSelection = 10
Dim columnSelected As Integer
columnSelected = 1
Do
With Excel.ThisWorkbook.ActiveSheet
.Range(.Cells(columnSelected, columnSelected), .Cells(endSelection, columnSelected)).Select
End With
columnSelected = columnSelected + 1
Loop Until columnSelected > 10
End Sub
EDIT
If in reality you just want to loop through every cell in an area of the spreadsheet then use something like this:
Sub loopThroughCells()
'=============
'this is the starting point
Dim rwMin As Integer
Dim colMin As Integer
rwMin = 2
colMin = 2
'=============
'=============
'this is the ending point
Dim rwMax As Integer
Dim colMax As Integer
rwMax = 10
colMax = 5
'=============
'=============
'iterator
Dim rwIndex As Integer
Dim colIndex As Integer
'=============
For rwIndex = rwMin To rwMax
For colIndex = colMin To colMax
Cells(rwIndex, colIndex).Select
Next colIndex
Next rwIndex
End Sub
Just use the Cells function and loop thru columns.
Cells(Row,Column)