Using a wildcard with a cell reference. What am I missing? - vba

In Sheet A are a list of names. I am attempting to count the different names on Sheet A in a table on Sheet B, Column B. The names are not exact and I will be referring to the cell and not writing in the name. The sub below almost works but I think I am not using the wildcqard correctly. Please help if you can. thanks in advance.
Sub Countif_Crr_Cnt_Until_LastRow()
Dim LastRow As Long
Dim wb1 As Workbook
Set wb1 = Workbooks("macro all client v.01.xlsm")
LastRow = wb1.Sheets("A").Range("A:A").Find("Overall - Total", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
For i = 21 To LastRow
Cells(i, 10) = Application.CountIfs(wb1.Sheets("B").Range("B:B"), "*" & Cells(i, 3) & "*")
Next
End Sub

I believe the issue is the unqualified references when you use just Cells(). VBA needs to know what sheet you expect that to be on, when using multiple sheets. I'm assuming that the Cells(i,10) and Cells(i,3) are to be on Sheet "A". If not, just change the sheet name:
wb1.Sheets("A").Cells(i, 10) = Application.CountIfs(wb1.Sheets("B").Range("B:B"), "*" & wb1.Sheets("A").Cells(i, 3) & "*")
As you can see, that's kind of long and a little tricky to read. An alternative way of doing that, is use With:
With wb1.Sheets("A")
.Cells(i,10) = Application.CountIfs(wb1.Sheets("B").Range("B:B"), "*" & .Cells(i,3) & "*")
End With
So, wherever you see a simple .Cells() without anything before the ., it's going to use what follows With. So it's the equivalent of the formula above...does that make sense?

Related

VBA - Copy / Paste to multiple columns with variable row start (array)

I'd like to shorten my code by putting multiple columns to one command.
I'm copying formulas from one row but specified columns and want to paste to another sheet in the same wksht. Just the row number is a variable. Maybe do this by an array?
As an example I'm pasting below not working code with only 3 columns.
Sub Copy()
Dim LastrowQ As Long
Dim LastrowR As Long
LastrowQ = Cells(Rows.Count, "B").End(xlUp).Row
LastrowR = LastrowQ + 1
Workbooks(Rep1).Worksheets("Formula").Range("A2, C2:F2, N2, V2:AD2").Copy
*Workbooks(Rep1).Worksheets("Report").Range("A" & LastrowR, "C" & LastrowR & ":F" & LastrowR, "N" & LastrowR, "V" & LastrowR & ":AD" & LastrowR).PasteSpecial Paste:=xlPasteFormulas*
End Sub
Could you please help to modify the code in paste part as it doesn't work right now? This would allow to make original code much shorter and hopefully faster.
What if I'd like to propagate function in second sheet from variable row till the specified row at the same time? ("A" & LastrowR & ":A" & LastrowS,...)
Thanks in advance

VBA script to insert INDEX/MATCH formula with dynamic reference/arrays

I'm looking to simply insert an INDEX/MATCH formula in the column next to an existing selection (this will be part of a larger Sub). The reference/look-up array in the formula needs to be dynamic.
So far I've managed to successfully insert the formula. However, the reference/lookup-arrays have been manually input by me as I know the current Range (which is likely to change):
Selection.Offset(0, 1) = "=INDEX($J$3:$J$31,MATCH(INDIRECT(""RC[-2]"",0),$H$3:$H$31,0))"
How can I amend the $J$3:$J$31 and the $H$3:$H$31 to update dynamically? I've had success separately with something like 'Range("J3", Range("J3").End(xlDown))', but I can't seem to work it into the code above.
You can integrate variables into the formula, it becomes a bit tricky, and I imagine there are better ways to accomplish this, but it's the method I use when I need dynamic ranges in formulas in VBA. I'll provide an example below that should help:
I'm assuming the J3 and H3 will remain the same, but the end of the range is what you expect to change. If this is not the case, let me know.
You're essentially replacing the "31" in your range reference with " & [variable] & " (quotes included).
EDIT: I use Sheet1 as an example for the row count; so just update that to whatever the applicable sheet & range would be.
Dim rCount As Long
rCount = Sheet1.Range("A" & Rows.Count).End(xlUp).Row
Selection.Offset(0, 1) = "=INDEX($J$3:$J$" & rCount & ",MATCH(INDIRECT(""RC[-2]"",0),$H$3:$H$" & rCount & ",0))"

Excel VBA: Formula Syntax to refer to Worksheet Index Number (Relative Instead of Name)

I am working on a macro that will filter a database (updated daily) and compute specific formulas. Each time the macro is ran, a new sheet (uniquely named) will be created with the filtered information, and the calculations will be performed on an additional sheet.
I am having trouble creating a macro with the correct syntax. Each time the macro is run, the filtered data I need to reference is located on worksheet #3 (uniquely named). I'm new to VBA and don't understand the syntax I need to reference the worksheet(index) as the worksheet in an R1C1 formula. Right now, my code looks like this:
Dim LR As Long
LR = Worksheets(3).Cells(Rows.Count, 1).End(x1Up).Row
Range("G6").Select
ActiveCell.FormulaR1C1 = _
"=COUNTIF(='Worksheets(3)'!R6C5:R" & LR &"C5,R[-1]C"
The code is counting if a column of Years (of a variable length) is equal to R[-1]C, which is a cell that contains a certain year, and will display the count in cell G6.
Is it possible to use a worksheet(index) reference in this context? How else could I accomplish the task of referencing a worksheet without name? Would I need to reference a "name" variable?
You had an extra = sign in there and you seem to be missing a closing bracket but .Address external:=true produces a nice range reference.
Dim LR As Long, str as string
with Worksheets(3)
LR = .Cells(Rows.Count, 1).End(xlUp).Row
str = .range(.cells(6, 5), .cells(lr, 5)).address(external:=true, ReferenceStyle:=xlR1C1)
end with
Range("G6").FormulaR1C1 = _
"=COUNTIF(" & str & ", R[-1]C)"

Excel Referencing cell entries for use in formula

I'm not sure exactly what to call what I'm trying to do, so searching it has been tough. Basically I have a table of equations, each row has a different equations/references a different column, but all of them reference the same range of rows. i.e. Eq. A = average(A200:A400), Eq. B = sum(C200:C400), etc...
From file to file the range of rows changes, so what I want to do is be able to do is enter the start and end rows into cells and have them auto populate the equations. If anyone could tell me how to do it just for one cell and not an entire table, I could figure it out from there.
Thanks!
Sounds like the INDIRECT function would accomplish this. It allows you to enter in text to be interpreted as a cell reference.
For instance, lets say you wanted the range to cover A200:A400 for a given sheet, and you wanted that desginated in cell A1 of that sheet. In cell A1 you would just type in "A200:A400" then, in the actual equations, you would have:
=AVERAGE(INDIRECT(A1))
You can obviously split this further down, but thats the concept of it.
You could create a form with a few text boxes. Enter the start and end row. Then your code could go through and enter the formula.
Something like this.
Dim lRow as long
Dim lEnd as long
lRow = val(txtBoxStartRow.text)
lEnd = val(txtBoxEndRow.text)
ws.Range("A" & lEnd + 1).Formula = "=average(A" & lRow & ":A" & lEnd & ")"
ws.Range("C" & lEnd + 1).Formula = "=average(C" & lRow & ":C" & lEnd & ")"
This should do:
=AVERAGE(INDIRECT(ADDRESS($B$1;ROW())):INDIRECT(ADDRESS($B$2;ROW())))
In that code I'm assuming cells B1 and B2 contain the limits (you can replace these references with hard number), to use your example: B1 = 200 and B2 = 400.
If you then place this code in any row, you'd get average("rowNumber"200:"rowNumber"400).
Address() gives you the right range reference
Indirect() makes a range out of it
Then you can wrap it in whatever function you like.

Code not looping through sheets

The following code is deleting too much on first sheet and then not looping to second sheet?? Error appearing on .FindNext statement.
Sub FindAndExecute3()
Dim Loc As Range
Dim sh As Worksheet
For Each sh In ThisWorkbook.Worksheets
With sh.UsedRange
Set Loc = .Cells.Find(What:="AUTO.WHSE.")
If Not Loc Is Nothing Then
Do Until Loc Is Nothing
Rows(ActiveCell.Row & ":" & (ActiveCell.Row + 2)).Delete
Set Loc = .FindNext(Loc)
Loop
End If
End With
Set Loc = Nothing
Next
End Sub
You have to fully qualify your Ranges.
This issue shows up once and again (e.g., this).
What does this mean? Do not use Cells, Range, Rows or Columns without specifying which Worksheet they belong to, unless you specifically want to do that (and even in that case, explicitly using ActiveSheet improves readability and reduces the chances of errors, similar to using Option Explicit).
For instance, replace
Rows(ActiveCell.Row & ":" & (ActiveCell.Row + 2)).Delete
with
sh.Rows(sh.<something>.Row & ":" & (sh.<something>.Row + 2)).Delete
I am assuming the Range to be deleted spans Row numbers taken from something related to sh.
Note 1: In this case, even without qualifying Ranges, code continues execution and the mistake may go unnoticed, as it produces a valid result. In other cases, code without fully qualified Ranges will throw an error (e.g., with something like sheet1.Range(Cells(..., when sheet1 is not the ActiveSheet).**
Note 2: You can work with the ActiveCell only when the Worksheet that it is on is the ActiveSheet [MSDN].