I am very new to vba coding .
In the worksheet I am trying to add an additional column using macros-column (Q)by checking conditions in simultaneous columns J,K,O).So if certain conditions pass in each of the columns I want a value to be entered in Q column for the respective row. This is the piece of code I put together .
Option Explicit
Sub Button2_Click()
Sheet1.Activate
Dim i As Long
For i = 2 To .Cells(.Rows.Count, "B").End(xlUp).Row
'Check so that we only process non-empty cells
'(just in case there is an empty cell part-way through the data)
If Cells(i, 10).Value = "No" And Cells(i, 15) <= 0 Then
Cells(i, 17) = "Pending with employee"
Else
If Cells(i, 10).Value = "No" And Cells(i, 15) >= 0 And Cells(i, 11) = "No Action Pending" Then
Cells(i, 17) = "Pending with employee"
Else
If Cells(i, 10).Value = "No" And Cells(i, 15) >= 0 And Cells(i, 11) = "Pending With Manager" Then
Cells(i, 17) = "Pending with Manager"
Else
If Cells(i, 10).Value = "Yes" And Cells(i, 15) >= 0 And Cells(i, 11) = "No Action Pending" Then
Cells(i, 17) = "All Done"
'If Not IsEmpty(.Cells(i, "B").Value) Then
' If .Cells(i, "E").Value = "NA" Then'
'ThisWorkbook.Worksheets("CTCto TCC Conversion").Cells(i, "F").Value = "NA" '
End If
End If
End If
End If
Next i
End With
MsgBox "Column Created"
End Sub
It throws me an error Invalid or unqualified reference .Please help me if there any errors that need to be rectified for the code to run .
Thanks
Using the With Statement
BigBen has already answered your question. Here's an example with a little extra.
Check the two lines containing .Cells(i, 15).Value. One of them should probably have the equal sign removed.
If you write several conditions in one line of code, all of them will be evaluated even if the first one is already True (or False) making it less efficient than writing each condition in a new line. In practice, you most often won't feel a difference. I cannot decide which one is more readable or maintainable for you though.
Option Explicit
Sub Button2_Click()
With Sheet1
Dim i As Long
For i = 2 To .Cells(.Rows.Count, "B").End(xlUp).Row
If .Cells(i, 10).Value = "No" Then
If .Cells(i, 15).Value <= 0 Then
.Cells(i, 17).Value = "Pending with employee"
Else
If .Cells(i, 11).Value = "No Action Pending" Then
.Cells(i, 17).Value = "Pending with employee"
ElseIf .Cells(i, 11).Value = "Pending With Manager" Then
.Cells(i, 17).Value = "Pending with Manager"
End If
End If
ElseIf .Cells(i, 10).Value = "Yes" Then
If .Cells(i, 15).Value >= 0 Then
If .Cells(i, 11).Value = "No Action Pending" Then
.Cells(i, 17).Value = "All Done"
End If
End If
End If
Next i
End With
MsgBox "Column Created"
End Sub
Related
I m trying to create a button and fill the value for column on.5 based on the value in column no.4.
here is the code:
Private Sub CommandButton1_Click()
Dim x As Integer
For x = 3 To 1000
If Cells(x, 4).Value = "Regular" Then
Cells(x, 5).Value = Today()
ElseIf Cells(x, 4).Value = "Temporary" And Cells(x, 5).Value = "" Then
Cells(x, 5).Value = "To be assigned"
Else
Cells(x, 5).Value = ""
End If
End Sub
This gives me the errors that sub or function is not defined.
I am new to VBA and trying to solve this, but could not do it.
Thanks.
VBA is ignoring the End Sub, because you haven't finished closing all of the clauses before it:
Private Sub CommandButton1_Click()
Dim x As Integer
For x = 3 To 1000
If Cells(x, 4).Value = "Regular" Then
Cells(x, 5).Value = Today() 'This should be Now()
ElseIf Cells(x, 4).Value = "Temporary" And Cells(x, 5).Value = "" Then
Cells(x, 5).Value = "To be assigned"
Else
Cells(x, 5).Value = ""
End If
'You are missing a "Next x" here
End Sub
Since the Sub is not complete, it does not count it as valid, so it cannot find it at compile time.
I am trying to edit my excel table with VBA but an error appears while compiling. It doesnt recognize line 2 and line 10.
Sub IfThenElse()
Dim i As Integer = 23
While Not IsNull(Cells(i, 35).Value)
If Cells(i, 35).Value > 1E+16 Then
Cells(i, 4).Value = Cells(i, 35).Value / 10
Else
Cells(i, 4).Value = Cells(i, 35).Value
i = i + 1
End If
End While
End Sub
You cannot declare a variable and set a value at the same time Dim i As Integer = 23
Row counts are of type Long not Integer, Excel has more rows than Integer can handle.
Dim i As Long
i = 23
While … End While is no valid syntax, you need to use Do While … Loop (see Do...Loop statement).
It is very unlikely that a cell value is Null if you are looking for an empty cell use IsEmpty or check for vbNullString
Do While Not IsEmpty(Cells(i, 35).Value) 'or Do While Not Cells(i, 35).Value = vbNullString
If Cells(i, 35).Value > 1E+16 Then
Cells(i, 4).Value = Cells(i, 35).Value / 10
Else
Cells(i, 4).Value = Cells(i, 35).Value
i = i + 1
End If
Loop
Not sure what exactly you are doing but i = i + 1 might need to come after End If.
Please I have an issue, everytime a change occcurs on the sheet it affects all the rows instead of the row (i) concerned. Confused. Don't for-loops work for worksheet_change ? Pls help. Thanks.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim LR As Long
'create a variable for last row of column C, LR
LR = Cells(Rows.Count, "C").End(xlUp).Row
For i = 2 To LR
If Cells(i, 6) = "Yes" And Cells(i, 7).Value = "Full" Then
Target.Value = Cells(i, 3).Value
Cells(i, 9).ClearContents
Cells(i, 10).Value = Cells(i, 8).Value + Cells(i, 9).Value
End If
If Not Intersect(Target, Range("G" & i & ":G" & LR)) Is Nothing And Range("F" & i) = "Yes"
And Target.Value = "Full" Then
Application.EnableEvents = False
Cells(i, 8).Value = Cells(i, 3).Value
Cells(i, 9).ClearContents
Cells(i, 10).Value = Cells(i, 8).Value + Cells(i, 9).Value
Application.EnableEvents = True
End If
If Not Intersect(Target, Range("G" & i & ":G" & LR)) Is Nothing And Range("F" & i) = "Yes" And
Target.Value = "Portion" Then
Application.EnableEvents = False
Cells(i, 8).Value = Cells(i, 3).Value
Cells(i, 10).Value = Cells(i, 8).Value + Cells(i, 9).Value
Application.EnableEvents = True
End If
Next i
End Sub
It seems you need to launch this event for the columns A-E. So, you can start your macro with:
IF Target.Column <= 5 THEN
...
END IF 'at the end of your macro
Like this, when you launch code like Cells(i, 8).Value = ..., Cells(i, 10).Value = ..., ... this macro will be called but it will be stopped immediately.
Apparently you are checking on column, maximum 10, which is in the range of the cells you are changing within your macro. Let's go for another approach:
At the very beginning of your macro, put this line:
Application.EnableEvents = False
At the very end of your macro, put this line:
Application.EnableEvents = True
(and remove the other occurences).
This will make sure you don't call your macro while running it.
I wrote the following code to search column A for the date of a document that I am trying to import and if not found then insert a new row and import the data:
' If the document date is earlier than the date in the first line of the spreadsheet search for the date in the A column
ElseIf strSheetDate > strFileNameDate Then
Set rngSheetDate = WS1.Range("A:A").Find(strFileNameDate)
' If the date is found in A column then add the data to that row
If Not rngSheetDate Is Nothing Then 'when rng <> nothing means found something'
If WS2.Cells(2, 2).Value <> "" Then WS1.Range(rngSheetDate.Address).Offset(0, 1).Value = WS1.Range(rngSheetDate.Address).Offset(0, 1).Value + WS2.Cells(2, 2).Value
If WS2.Cells(3, 2).Value <> "" Then WS1.Range(rngSheetDate.Address).Offset(0, 3).Value = WS1.Range(rngSheetDate.Address).Offset(0, 3).Value + WS2.Cells(3, 2).Value
Else
' If it is not found then look for dates either side of the document date and then insert a new line for that record
iRow2 = WS1.Cells(Rows.count, 1).End(xlUp).Row
Set rngSheetDate2 = WS1.Range("A2:A" & iRow2)
For Each cell In rngSheetDate2
If cell.Value > strFileNameDate And cell.Offset(1, 0).Value < strFileNameDate Then
WS1.Range(cell.Offset(1, 0), cell.Offset(1, 4)).Insert shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
cell.Offset(1, 0).Value = strFileNameDate
If WS2.Cells(2, 2).Value <> "" Then
cell.Offset(1, 1).Value = WS2.Cells(2, 2).Value
Else
cell.Offset(1, 1).Value = 0
End If
If WS2.Cells(3, 2).Value <> "" Then
cell.Offset(1, 3).Value = WS2.Cells(3, 2).Value
Else
cell.Offset(1, 3).Value = 0
End If
Exit For
End If
Next
End If
End If
There must be a better way to search for a string in column 1 of the table and if not found then add a new line in the middle of the table or add to the bottom.
any advice ?
If all you want is for the code to be condensed, you can remove a lot of the superfluous .Value etc...
Also the If-ElseIf can be recoded ass they are simple using the IIf function
Normally setting code within 'With' statements also helps shorten code as well as being more efficient - but there isn't really much here that warrants it
For example:
' If the document date is earlier than the date in the first line of the spreadsheet search for the date in the A column
ElseIf strSheetDate > strFileNameDate Then
Set rngSheetDate = WS1.Range("A:A").Find(strFileNameDate)
' If the date is found in A column then add the data to that row
If Not rngSheetDate Is Nothing Then 'when rng <> nothing means found something
If WS2.Cells(2, 2) <> "" Then rngSheetDate.Offset(0, 1) = rngSheetDate.Offset(0, 1) + WS2.Cells(2, 2)
If WS2.Cells(3, 2) <> "" Then rngSheetDate.Offset(0, 3) = rngSheetDate.Offset(0, 3) + WS2.Cells(3, 2)
Else
' If it is not found then look for dates either side of the document date and then insert a new line for that record
iRow2 = WS1.Cells(Rows.Count, 1).End(xlUp).Row
Set rngSheetDate2 = WS1.Range("A2:A" & iRow2)
For Each Cell In rngSheetDate2
If Cell > strFileNameDate And Cell.Offset(1, 0) < strFileNameDate Then
WS1.Range(Cell.Offset(1, 0), Cell.Offset(1, 4)).Insert shift:=xlDown, CopyOrigin:=xlFormatFromLeftOrAbove
Cell.Offset(1, 0) = strFileNameDate
Cell.Offset(1, 1) = IIf(WS2.Cells(2, 2) <> "", WS2.Cells(2, 2), 0)
Cell.Offset(1, 3) = IIf(WS2.Cells(3, 2) <> "", WS2.Cells(3, 2), 0)
End If
Next
End If
End If
I am trying to write a code that will take one cell and then iterate through another column to find a match, once it has found a match it will then match two other cells in that same row and return the value of a 5th and 6th cell. However, it is not working! any suggestions??
Sub rates()
Dim i As Integer
For i = 2 To 2187
If Cells(i, 1).Value = Cells(i, 11).Value Then
If Cells(i, 2).Value = Cells(i, 12).Value Then
Cells(i, 20) = Cells(i, 1).Value
Cells(i, 21) = Cells(i, 11).Value
Cells(i, 22) = Cells(i, 4).Value
Cells(i, 23) = Cells(i, 16).Value
Else
Cells(i, 24) = "No match"
End If
End If
Next i
End Sub
Try fully qualifying your cell objects i.e. sheet1.cells(i,1).value etc or encase within a with statement i.e.
with sheet1
if .cells(i,X) = .cells(i,Y) then
'...etc
end with
I think the default property for a range is "Value" but try putting .Value on to the end of all those Cell lines too... like you have for half of them :)
[EDIT/Addition:]
... failing that, you're not actually searching a whole column at any point: try something like:
Sub rates()
Dim i As Integer
Dim rgSearch As Range
Dim rgMatch As Range
Dim stAddress As String
Dim blMatch As Boolean
With wsSheet
Set rgSearch = .Range(.Cells(x1, y1), .Cells(x2, y2)) ' Replace where appropriate (y = 1 or 11 i guess, x = start and end row)
End With
For i = 2 To 2187
Set rgMatch = rgSearch.Find(wsSheet.Cells(i, y)) ' y = 1 or 11 (opposite of above!)
blMatch = False
If Not rgMatch Is Nothing Then
stAddress = rgMatch.Address
Do Until rgMatch Is Nothing Or rgMatch.Address = stAddress
If rgMatch.Offset(0, y).Value = Cells(i, 12).Value Then
Cells(i, 20) = Cells(i, 1).Value
Cells(i, 21) = Cells(i, 11).Value
Cells(i, 22) = Cells(i, 4).Value
Cells(i, 23) = Cells(i, 16).Value
blMatch = True
Else
End If
Set rgMatch = rgSearch.FindNext(rgMatch)
Loop
End If
If Not blMatch Then
Cells(i, 24) = "No match"
End If
Next i
End Sub
I've made a lot of assumptions in there and there's a few variables you'll have to replace. You could also probably use application.worksheetfunction.match but .find is quicker and more awesome