Extract the first column number from an address in VBA - excel

I want to extract the number from the first column of a defined range in VBA. Currently, my code looks like this:
Sub Column_Number()
Sheet1.Range("A1").Value = Sheet1.Range("$C$6:$I$6").Address
End Sub
The expected result in Cell A1 should be 3 because Column C is the first column in the Range("$C$6:$I$6") and the third column in the entire sheet.
I tried to go with the solution from here but could not make it work.
Instead of the column number it returned the value in Cell $C$6.
How do I need to modify my VBA to get the expected result?

Use Column property of Range object. Try below.
Sub Column_Number()
Sheet1.Range("A1").Value = Sheet1.Range("$C$6:$I$6").Column
End Sub

In this way, you will have the column number and its letter, too:
Dim sh As Worksheet, rng As Range
Set sh = Sheet1
Set rng = sh.Range("$C$6:$I$6")
Debug.Print rng.column, Split(rng.Address, "$")(1)

Related

Can not SUM selected cells With SUMIF

I would like to be able to Check for criteria "owners" In column A and SUM cell from the same row column E with the cell above and repeat through the spread sheet where owner is found.
I have tried to use Function =SUMIF(A3,"*owner*",E2:E3) This returns the Value above the cell in the row with owner but does not SUM them.
I have also tried this VBA CODE and it does the same thing.
Sub vba_sumif()
Dim gRange As Range
Dim sRange As Range
Set gRange = Range("A3")
Set sRange = Range("E2:E3")
Range("G2") = _
WorksheetFunction.SumIf(gRange,"*Owner*", sRange)
End Sub
Ideally it would return the summed cells in the above cell. using VBA
Thanks again,
Aaron
Well first of all, I would suggest just using the formula unless you have a reason not to:
Formula:: Your first error with the formula is both ranges need to be the same size.
VBA:: Same thing here with range sizes, then you also need to remember to make sure Excel knows what sheet you're referring to. I like to do this with a With My_Worksheet_Namestatement, then include a . before any range from that sheet. Just make sure to change the sheet name to your sheet name
Option Explicit
Sub vba_sumif()
Dim TableSheet As Worksheet
Dim gRange As Range
Dim sRange As Range
Set TableSheet = Worksheets("TableSheet")
With TableSheet
Set gRange = .Range("A2:A13")
Set sRange = .Range("E2:E13")
.Range("G2").Value = _
WorksheetFunction.SumIf(gRange, "*Owner*", sRange)
End With
End Sub

Applying formula to a variable range

I would like to apply a formula to a given range.
However, the number of columns are not fixed and will vary.
Screenshots to visualise what I'm doing.
Screenshot 1: I would like for the code to auto select from column C onwards, and apply the formula in the next image. The number of columns will vary as more students attempt the quiz.
Screenshot 2: This is the formula I wish to apply to the selected range. After that, I would be able to loop through the list of teachers from B31 and below one by one, copy the range of answers for each teacher's students and paste them onto Sheets 3-6 which contain the first set of results I mentioned earlier.
Sub obtainsecond()
Sheets("Question_answers").Select
Range("C31").Select
ActiveCell.Formula2R1C1 = _
"=FILTER(R[-29]C:R[-4]C[3],ISNUMBER(SEARCH(R[-1]C,R[-30]C:R[-30]C[3])))"
End Sub
One approach to solve the problem.
This approach assumes that the last column in row 1 is the last column with a student answer.
Logic:
I check the last column and get the cell reference (i.e. $H1). Then i extract only the column letter. I take the column letter and put it in the formula you want to extend.
Code:
Option Explicit
Sub obtainsecond()
Dim QA_ws As Worksheet 'Declare the worksheet as a variable
Set QA_ws = ActiveWorkbook.Worksheets("Question_answers") 'Decide which worksheet to declare
Dim lCol As Long
Dim LastColumnLetter As String
Dim lColRange As Range
QA_ws.Activate 'Go to the worksheet
lCol = QA_ws.Cells(1, Columns.Count).End(xlToLeft).Column 'Find the last column in the worksheet by checking in row 1
Set lColRange = QA_ws.Cells(1, lCol) 'Set last column to get cell reference, i.e. $H1
'MsgBox lColRange.Address(RowAbsolute:=False) ' $H1
'https://www.exceltip.com/tips/how-to-convert-excel-column-number-to-letter.html (Formula to extract letter: =SUBSTITUTE(ADDRESS(1,B2,4),1,””))
LastColumnLetter = WorksheetFunction.Substitute(lColRange.Address(RowAbsolute:=False), "1", "") 'Get column letter
LastColumnLetter = Replace(LastColumnLetter, "$", "") 'Remove prefix
QA_ws.Range("C31").Formula2 = "=FILTER(C2:" & LastColumnLetter & "27,ISNUMBER(SEARCH(C30,C1:" & LastColumnLetter & "1)))" 'Use relative formula to print in cell (original formula: =FILTER(C2:F27,ISNUMBER(SEARCH(C30,C1:F1))))
End Sub

How to use Rows(x:x) .select in IF statement

I have a spreadsheet where I have a macro built to whittle down the amount of data to something manageable. The next step is to compare the value of a column cell to a predefined number determined in the macro and placed in another cell away from the data. If the value is less than the predetermined value, I want to delete the entire row, then go on to the next row and do it again. In the end, all I should have left is the rows where that column is greater than the predetermined value.
Let's say the column is C and the predetermined value is in M1. How would I do this?
BTW, the macro to date has filtered the data based on Column C from largest to smallest, so I'm basically looking to find the first value in C to be less than the other value, then highlight everything underneath and delete it.
Thanks for any help.
You didn't specify if you had a Header row or not, but for your exact request here you go.
Option Explicit
Sub DeleteRows()
Dim ws As Worksheet, myVal As Double
Dim Cell As Range, RngC As Range, CompRng As Range
Set ws = ThisWorkbook.Worksheets(1)
Set RngC = ws.Range("C:C")
Set CompRng = ws.Range("M1")
myVal = CDbl(CompRng.Value)
For Each Cell In RngC
If CDbl(Cell.Value) < myVal Then
Cell.EntireRow.Delete
End If
Next Cell
End Sub

Select discontinuous range based on column A

I have data in columns A:I. The data in column A will always go through to the last row, but other rows in other columns will sometimes be blank. How do I select the range based on the last row in column A? For example, sometimes column A will have 40 rows of data but column I will be blank after row 3. I would still want to select A1:I40.
Ultimately, I want to use VBA to format and put a filter on this range, so I am hoping to not include any blank rows after the last used row in column A.
Consider:
Sub qwerty()
Dim N As Long
N = Cells(Rows.Count, "A").End(xlUp).Row
Range("A1:I" & N).Select
End Sub
Gary's Student gave you the answer
maybe you're interested in expanding the feature and want to consider the last row with at least one non blank cell in the whole columns range (columns "A:I" in your example), irrespective of which column has it, than you could use:
Function LastRow(sht As Worksheet, columnsStrng As String) As Long
With sht
With Intersect(.UsedRange, .columns(columnsStrng)).SpecialCells(xlCellTypeConstants)
LastRow = .Areas(.Areas.Count).Row
End With
End With
End Function
and here follows an example of how to use it
Option Explicit
Sub main()
Dim ws As Worksheet
Set ws = Worksheets("mysheet1")
ws.columns("A:I").Resize(LastRow(ws, "A:I")).Select
End Sub
This assumes your data are constants (i.e. actual cells content is not a "formula").
But it can be easily enhanced to consider "formula" data as well

Visual Basic 2007 Adding values

To start with I'm not really a wise man. So I was trying to add up two values and display them in a third (that's easy) but I also wanted it to repeat an infinite amount of times (namely that it does the same for every row, let's say I place the result in I5, I want also, on every I under it (I6, I7, I8, etc...)
Should it be:
Private Sub Worksheet_Change()
if IsNumeric(Range("B1").sort) And IsNumeric(Range("B2").sort) then
Dim value1 As Single
Dim value2 As Single
range(I5).sort = value+1 + value2
End Sub
Or as I think I'm horribly mistaken?
You're using the .Sort property of Range where you should be using .Value.
There's a couple of ways to achieve what you're looking to do. First option is to iterate through the range and add the relevant value to each cell like so:
Public Sub addCells()
Dim rng As Range, cell As Range
'Set the sheet name
With ThisWorkbook.Worksheets("Sheet_Name")
'Set the range below:
Set rng = .Range("I1:I10")
'Loop through range and add cells together
For Each cell In rng
cell.Value = cell.Offset(0, 2) + cell.Offset(0, 1)
Next cell
End Sub
Another way to do it if the values to be added is ordered in for example column A and B would be:
Public Sub addCells()
Dim rng As Range, cell As Range
'Set the sheet name
With ThisWorkbook.Worksheets("Sheet1")
'Add the first formula to the sheet
.Range("C1").Value = "=SUM(A1+B1)"
'Change the range below to the range to be filled
.Range("C1").AutoFill Destination:=.Range("C1:C10")
End With
End Sub

Resources