I am writing and Excel VBA if statement, but I can't figure out why it is not working.
I have 1 Sheet called "Data" and I want to check if some variables in column I are the same as in my ActiveSheet row 2, column B (which is number 2). I used the following code which ends automatically because it is not working. Anybody an idea?
Example:
Sub test()
If Sheets("Data").Range("I:I") = ActiveSheet(2, 2) Then
MsgBox ("Yes")
Else
MsgBox ("No")
End If
End Sub
You should create a loop in column I if you want to validate every item in that column; use a flag to bail out as soon as you find a mismatching value, so as to avoid looping through all cells once you already know the outcome:
Dim x as long, result As Boolean
result = True
For x = 1 to 100 'let's say up to row 100
If Worksheets("Data").Range("I" & x).value <> ActiveSheet.Cells(2, 2).value Then
result = False
End If
If Not result Then Exit For
Next x
If result Then
MsgBox "Yes"
Else
MsgBox "No"
End If
You compare a whole column (i.e. 1048576 values) with a single value which obviously does not work. Furthermore if you want to access a specific cell you have to use the Cells-collection of your worksheet i.e. ActiveSheet.Cells(2,2)
If you want to compare each cell in column I individually, use a Loop. If you only want to know if the search-value exists somewhere within the column, you can use the Range.Find method.
Related
I was working on an Excel project with multiple Tabs.
One of the worksheets has a column called "Names". My users usually move the columns every now and then. So to extract the correct column I have used this particular VBA code.
HEADER = Sheets("WORKSHEET").Range("A1:Z1").Address
SourceDataColumn = Application.WorksheetFunction.Match("Name", HEADER, 0)
SourceColumnLetter = Split(Cells(1, SourceDataColumn).Address(True, False), "$")(0)
Example: In this case, the output would be [ SourceColumnLetter = C ] containing the "Names"
It works fine, I was just wondering if there is a way to set the 'SourceColumnLetter' as a global variable so that I don't have to use the same whole block of code again and again.
Any help would be appreciated.
Thanks in Advance.
Make a function GetColumnNumberByTitle that finds the column number for you. You can then easily access it by its number.
You can use GetColumnNumberByTitle("Name") in any of your procedures now to get the column by its title. Note that it returns 0 if it does not find the "Name".
See example below:
Option Explicit
Public Sub test()
Dim ColNo As Long
ColNo = GetColumnNumberByTitle("Name") 'get the column number by its title in row 1
If ColNo <> 0 Then
'access the column by its number
Debug.Print ThisWorkbook.Worksheets("WORKSHEET").Cells(1, ColNo)
'this should return the column name
Debug.Print ThisWorkbook.Worksheets("WORKSHEET").Cells(2, ColNo)
'this should return the columns first value
Else
MsgBox "Column Name was not found."
End If
End Sub
Public Function GetColumnNumberByTitle(ByVal ColumnTitle As String) As Long
On Error Resume Next 'next line errors if title is not found
GetColumnNumberByTitle = Application.WorksheetFunction.Match(ColumnTitle, ThisWorkbook.Worksheets("WORKSHEET").Rows(1), 0)
On Error GoTo 0 're-enable error reporting!
'if title was not found this function returns 0
End Function
Another approach could be using formatted tables (ListObjects):
And you can then easily access a column by its title with the following code:
Worksheets("Sheet1").ListObjects("Table1").ListColumns("Name").Range.Select
or to select a specific row
Worksheets("Sheet1").ListObjects("Table1").ListColumns("Name").Range(3).Select
'selects row 3 in column "Name"
Any variable (even Global, Public etc.) must receive somehow a value...
If columns are inserted or deleted its reference is changed even if it has been defined on, let us say, Workbook_Open event.
I would suggest you to make it a named range. Select it, go to the left formula bar side (Name Box), write the name you need (HD, for instance) and press Enter.
Than, you can use it like:
SourceColumnLetter = Split(Range("HD").Address(True, False), "$")(0)
or better try using Cells instead of Range, doing it in the next way (without the column letter):
Cells(x, range("HD").Column)
without any preliminary calculation...
i have this worksheet called Test. In that worksheet i want to export to pdf then print cells G1 to cells H17. Next i want to print G1 to cells I17 skipping column H meaning without column H. In another word column G is kind of like the header and the columns that follow the result. So print Header column+ results column and so on until column CM. Below each printing page i want to also export to pdf column C18, column D18 and Column H18 if cells I18 to cells I27=500. I started the code but couldn't go on to finish it since i am not really versed in vba
Sub SetPrintArea()
Dim ws As Worksheet
Dim x As Long, result As Boolean
result = True
For x = 18 To 128
If Worksheets("AR-MD").Range("H" & x).Value <> ActiveSheet.Cells(8, 19).Value Then
result = False
End If
If Not result Then Exit For
Next x
Set ws = ThisWorkbook.Sheets("AR-MD")
ws.PageSetup.PrintArea = Union(ws.Range("g1:g17"), ws.Range("i1:i17"),ws.Range("Result").Address
End Sub
I want to be able to print the result condition but i dont know how to include it in the statement
Use the Union method:
ws.PageSetup.PrintArea = Union(ws.Range("g1:g17"), ws.Range("i1:i17")).Address
I'm not very good at loops.
I'm trying to use VBA to loop through a column to look for any value, and then delete the entire row if it doesn't find anything (It's essentially a way of deleting rows of data that I've marked (or unmarked in this case)).
I've tried various things. My most recent attempt is below but its just deleting every row regardless of whether that cell has a value or not. Any suggestions?
Dim i as Long
For i = 1 To 50
If Cells(i, 1).Value = "" Then
Selection.EntireRow.Delete
Else
i = i + 1
End If
Next i
End Sub
There are several issues here:
When deleting rows in a loop work backwards, if going forward your row number changes as you delete.
There is no need to increment variable "i" next i already does this
Use the Worksheet object to delete the row rather than Selection
I would rewrite like this:
Sub delete()
Dim i As Long
For i = 50 To 1 Step -1
If Cells(i, 1).Value = "" Then
Worksheets("Sheet1").Rows(i).EntireRow.delete
End If
Next i
End Sub
I am trying to input a value into the next empty row in a column.
I tried using rows.count and off setting it like you would with a paste but it doesn't work. I was able to get it to change the value in the first cell but not to look for the next empty and change its value.
Private Sub CommandButton1_Click()
Dim wbCount As Workbook
Set wbEntry = ThisWorkbook
wbEntry.ActiveSheet.Range("B3").Copy
Set wbCount = Workbooks.Open("U:\MO# Count.xlsm")
Worksheets("Golf Cart").Paste _
Destination:=Worksheets("Golf Cart").Range("V5")
Worksheets("Golf Cart").Range("C2").Value = 1
wbEntry.Activate
Application.CutCopyMode = False
wbEntry.ActiveSheet.Range("O1").Select
End Sub
What I have works except for not searching for the next empty cell in "C" and changing the value to "1".
I'm confused, why would you think it searches for an empty cell?
Leaving the rest of the macro alone for now, this line:
Worksheets("Golf Cart").Range("C2").Value = 1
Does not search for an empty cell, it just writes a "1" into Cell C2. If you would like it to find the first empty cell in column C and then write a 1 into it, then this should do the trick:
Worksheets("Golf Cart").Cells(Sheets("Golf Cart").Cells(Rows.Count, 3).End(xlUp).Row + 1, 3) = 1
I'm not sure thats what you want tho, please clarify. This finds the last used row in column C and then goes to the next one down to write a "1" into it. It doesnt work if you want to find empty cells in an otherwise value-filled column. But you wrote something about rows.count or something, so I thought I'd post that way?
I have an excel with predefined column headers.The problem is these column headers can be at any position for every iteration that is only column headers are fixed not their position(index). So, I need to get the column index based on the column name for further processing.
I found another way to access the column as described in the question, so I though I should change my first answer accordingly. But I thought maybe that answer works for other cases.
Here is a quicker way to get hold of a column containing the value:
Sub Macro1()
ColumnByValue("age").Offset(5, 0).Value = "17"
End Sub
Function ColumnByValue(col As String) As Range
Set ColumnByValue = Range("1:1").Find(col)
End Function
Use .Find() to locate the cell containing the column you are looking for.
I wrote the following example to add a value at a certain column, on a specified row number. You might want to change the code so that it adds the value to the bottom of the existing values instead. For simplicity, the code below will find the column, go down to the specified row and change the value to the value specified by the caller.
Sub Macro1()
Dim result As Boolean
result = add_value_to_column("age", atRow:=3, newValue:=17)
'was that successful?
If result = True Then
MsgBox "value was added"
Else
MsgBox "value NOT added. maybe column does not exist"
End If
End Sub
Function add_value_to_column(col_name As String, _
atRow As Integer, _
newValue As String) As Boolean
Dim c As Range
'Assuming the header row is the first row at the top (1:1)
With Range("1:1")
'try to find the column specified in the function parameters
Set c = .Find(col_name, LookIn:=xlValues)
'If the column was found then it will not be nothing
'NOT NOTHING = THING :)
If Not c Is Nothing Then
'access the row specified in the parameter, at the column,
'and set the value for that location
Cells(atRow, c.Column).Value = newValue
'Optioal: inform the caller that the value was set
add_value_to_column = True
Else
'optional: inform the caller that column was not found
add_value_to_column = False
End If
End With
End Function
Here is an image showing a sample data set. Running the code above has added the value 17 to the age column for the row number 3