How to apply Autofill function for a dynamic range in VBA? - excel

I'm in the process of creating a macro that should return 3 results:
adds 3 columns to the right after column C
implements characters per line counting formula which returns number of characters per line from column C in newely created column D
implements total characters count formula in column E (counts sum of characters count returned from column D)
Future Result: As current code gives formula results in cells D2 and E2 I want it to run Autofill function so that no matter the number of rows in the spreadsheet it gives results for all of them (just like double-clicking in the bottom right corner of a cell with formula).
This is how code looks like now:
Sub AutoFillTest
Columns("D:F").Insert Shift:=xlToRight, _
CopyOrigin:=xlFormatFromLeftOrAbove '
Range("D2").Select
ActiveCell.Formula = "=Len(Left(C2, IfError(Find(Chr(10), C2, 1), 99))) & IfError("" ,"" &
Len(Mid(C2, Find(Chr(10), A2, 1) + 1, 99)), """")"
#Here goes Autofill part which I'm looking for#
Range("D2,E2").Select
Range("E2").Activate
ActiveCell.Formula = "Len("C2")"
#Here goes Autofill part which I'm looking for#
End Sub

You can use autofill like this:
Set SourceRange = Worksheets("Sheet1").Range("A1:A2")
Set fillRange = Worksheets("Sheet1").Range("A1:A20")
SourceRange.AutoFill Destination:=fillRange
Then what you would need to is find the last row for the columns you need.
UPDATE
With your need for dynamic last row, something simple like this might work:
Add a function:
Public Function GetLastRow(str_TabName As String, lng_Column As Long, lng_Row As Long) As Long
 
Sheets(str_TabName).Select
'Range(str_Column & lng_Row).Select
Cells(lng_Row, lng_Column).Select
Selection.End(xlUp).Select
 
GetLastRow = ActiveCell.Row
 
End Function
Then amend the code like this:
Sub AutoFillTest
'' Get last row
Dim lng_LastRow as Long
'' Pass argument as required sheet, the column as a number, and the last row to start from
lng_LastRow = GetLastRow("Sheet1", 4, 100000)
Columns("D:F").Insert Shift:=xlToRight, _
CopyOrigin:=xlFormatFromLeftOrAbove '
Range("D2").Select
ActiveCell.Formula = "=Len(Left(C2, IfError(Find(Chr(10), C2, 1), 99))) & IfError("" ,"" &
Len(Mid(C2, Find(Chr(10), A2, 1) + 1, 99)), """")"
#Here goes Autofill part which I'm looking for#
Set SourceRange = Worksheets("Sheet1").Range("D2:D2")
Set fillRange = Worksheets("Sheet1").Range("D3:D" & lng_LastRow )
SourceRange.AutoFill Destination:=fillRange
Range("D2,E2").Select
Range("E2").Activate
ActiveCell.Formula = "Len("C2")"
#Here goes Autofill part which I'm looking for#
'' apply from the example above and see if it works for you
End Sub
Note I haven't checked your formulae

Related

VBA that will count number of rows until it hits a dark blue cell? (RGB = 93, 123, 157)

Starting in cell B8, I want to count the number of rows down until we hit a cell that is filled with the RGB 93, 123, 157.
I tried using the autofill formula feature while recording, but the cell references stayed absolute: Selection.AutoFill Destination:=ActiveCell.Range("A1:A182")
This will only work if the report has 182 rows, which they won't all have.
I was also given this to try:
Sub Test()
Dim i As Long, bluerow As Long
For i = 1 To 10000
If Cells(i, 2).Interior.Color = RGB(93, 123, 157) Then
bluerow = i
Exit For
End If
Next i
Range("B6").AutoFill Destination:=Range("B6:B" & bluerow), Type:=xlFillDefault
End Sub
But it doesn't put any numbers in column B.
This could work by itself.
Sub NumRws()
'"Cells(5, 2)" is a reference to B5(for some reason, shouldn't it be B8? in that case it should say "Cells(8, 2)")
'"Cells(Rows.Count, 1).End(xlUp)" refers to the last used cell(a cell with any value) in column A
'".Offset(-1, 1)" offsets the second reference to column B and now also one row up("-1,")
'..and "Range(...)" combines the two
'".FormulaR1C1 = "=ROW()-4"" applies the formula which results in row number minus 4(if you change to B8 it should be -7)
Range(Cells(5, 2), Cells(Rows.Count, 1).End(xlUp).Offset(-1, 1)).FormulaR1C1 = "=ROW()-4"
'..Also if you just want the result of the formula do the following instead
With Range(Cells(5, 2), Cells(Rows.Count, 1).End(xlUp).Offset(-1, 1))
.FormulaR1C1 = "=ROW()-4"
.Value = .Value
End With
End Sub
The code below uses Find to get the first cell in column B that matches the color criteria, and then subtracts 7 from the row number.
Sub FindtheFirstColoredCellCountRowsfromRow8()
'Find the first cell in Column(2) with specific interior color and count number of rows
Dim fndCel As Range, cnt As Long
ActiveCell.Interior.Color = RGB(93, 123, 157) 'colors any cell to use in "Find"
Application.FindFormat.Interior.Color = ActiveCell.Interior.Color 'store cell color in find
'set the find range variable to find the first cell that matches the color in Column B
Set fndCel = ActiveSheet.Columns(2).Find("", , , , , xlNext, , , True)
cnt = fndCel.Row - 7 'set the count variable by subtracting 7 from the fndCell row
MsgBox cnt
Application.FindFormat.Clear 'reset FindFormat
ActiveCell.Interior.Color = xlNone 'clear the cell you used to set the color to find
End Sub
Not exactly sure what you're asking for? You want the row number to appear on every cell from B8 till the row where it appears? in that case use:
range("B8:B" & bluerow) = bluerow
This will type the row number where the RGB value is found, starting from B8, down to where the RGB was found. If this is not what you need please explain your problem further.
EDIT: Oh, my bad. Then use this:
For i = 1 To 10000
If Cells(7 + i, 2).Interior.Color = RGB(93, 123, 157) Then
Exit For
Else
Cells(7 + i, 2) = i
End If
Next i
I would suggest finding the last row, though, instead of using "to 10000", you can use:
LastRow = cells(rows.count,2).end(xlup).row

Inserting Excel formula that refers to alternative columns

I am trying to insert the following formula ='External Costs B0'!F73 in the same row of a sheet in consecutive columns, however with the cell reference "F73" in worksheet "External Costs" referring to alternate columns e.g F73, H73, J73, L73 etc.
Here is a screen shot of the spreadsheet with formula commented
Screen Capture of formula sheet
This is the code I have tried but I am struggling to figure how to get the alternative column reference working.
Dim CostColumns As Long
'Select cell to start inserting the formula from
Range("E26").Select
'Start from column F (6) in the "External Costs B0" sheet and step to every alternate column
For CostColumns = 6 To 600 Step 2
ActiveCell.Formula = "= ""'External Costs B0'!"" & Rows(73)Columns(CostColumns)"
Move to the next cell to insert the formula in and advance the column reference by 2 columns
ActiveCell.Offset(0, 1).Select
Next CostColumns
The net result is the same error I have seen in many posts:
Application-defined or object-defined error.
Here are many other syntax's for the formula insert I have tried with no success. Any help is greatly appreciated. The below refers to row 40 instead of row 73 in the External Costs B0 sheet as per the example above.
Range("E26").Select
For CostColumns = 6 To 66 Step 2
'ActiveCell.FormulaR1C1 = "= worksheets("""External Costs B0""").Cells(40,6).Value"
'ActiveCell.FormulaR1C1 = "='External Costs B0'!R[14]C[CostColumns]"
'Range("E26:AK26").FormulaR1C1 = "='External Costs B0'!R[14]C[CostColumns]"
'ActiveCell.FormulaR1C1 = "= worksheets('External Costs B0')!" & " Rows(40)Columns(CostColumns)"
'Range("E26:AK26").FormulaR1C1 = "='External Costs B0'!R[14]C[+2]"
'Range("E26:AK26").FormulaR1C1 = "=Wksht.Cells(40,CostColumns) &"
'Range("E26:AK26").Formula = "=worksheets('External Costs B0'!)" & ".Cells(40,6)"
'ActiveCell.Formula = "= worksheets('External Costs B0'!).Cells(40,6).Value"
ActiveCell.Offset(0, 1).Select
Next CostColumns
Use this:
ActiveCell.Formula = "='External Costs B0'!" & Cells(73, CostColumns).Address(0, 0)
The problem with that is that Rows(73) and Columns(CostColumns) both return a Range object which you can't concatenate to a string.
Its way easier, if you use FormulaR1C1 and no selects like in the following sub:
(please change R, RowOffset and FormulaUntilColumn to your needs)
Sub Formulas()
Dim I As Integer
Const R As Long = 9 'row
Const RowOffset As Integer = -8
Const ForumulaUntilColumn As Long = 7
For I = 1 To ForumulaUntilColumn
Cells(R, I).FormulaR1C1 = "=R[" & RowOffset & "]C[" & I - 1 & "]"
Next I
End Sub
P.S.: add workbook and table name as in any other formula between '=' and 'R['
This code will place your formula in cells Sheet1!A1:AD1.
The formula in A1 will be ='External Costs B0'!$A$73.
In B1 it will be ='External Costs B0'!$C$73 and so on up to ='External Costs B0'!$BG$73 in cell AD1.
Sub PasteFormula()
Dim CostColumns As Long
Dim y As Long
'Starting column for External Costs reference
CostColumns = 1
With ThisWorkbook.Worksheets("Sheet1")
For y = 1 To 30
.Cells(1, y).FormulaR1C1 = "='External Costs B0'!R73C" & CostColumns
CostColumns = CostColumns + 2
Next y
End With
End Sub
To update the code change Sheet1 to whichever sheet you need to
formula to appear in.
Change CostColumn=1 to the correct column
number you want the formula to refer to.
Change y = 1 To 30 to
the correct columns you want the formula to appear in.
The code uses R1C1 syntax as it's easier to update a formula if you only need to deal with row & column numbers R73C2 is row 73, column 2 for example.

Variable for Excel Columns. Column Assigned to Variable

I have a macro that inserts 2 columns on my current sheet and pastes information from another sheet.
I want to create 2 variables that are assigned to each column that would change the next time I run the macro to paste the information in the next two columns.
Columns("BO:BO").Select
Selection.Insert Shift:=xlToRight
Range("BO2").Select
ActiveCell.FormulaR1C1 = "Feb weekly-wk 2"
Range("BO19").Select
ActiveCell.FormulaR1C1 = _
"=VLOOKUP(Comparison!RC2,'Jan16 wk4'!R3C15:R34C24,9,FALSE)"
Range("BO19").Select
Selection.AutoFill Destination:=Range("BO19:BO47"), Type:=xlFillDefault
Range("BO19:BO47").Select
Columns("BP:BP").Select
Selection.Insert Shift:=xlToRight
Range("BP2").Select
Selection.Style = "20% - Accent6"
Range("BP2").Select
ActiveCell.FormulaR1C1 = "Diff"
Range("BP19").Select
ActiveCell.FormulaR1C1 = "=RC[-2]-RC[-1]"
My idea is to set up a variable that I would replace my current "BO" and "BP" code with.
Dim X as String, Y as String
X = "BO"
y = "BP"
When I run the macro it would change the variable for this example "BO" to "BQ" and "BP" to "BR". Next time I run the macro would change the "BQ" to "BS" and "BR" to "BT".
I just cleaned your code a little:
Dim ColBO As Integer
Dim ColBP As Integer
Dim StrBO As String
Dim StrBP As String
StrBO = "BO"
StrBP = "BP"
ColBO = ActiveWorkbook.Range(StrBO & 1).Column 'instead of StrBO you could directly write ("BO" & 1)
ColBP = ActiveWorkbook.Range(StrBP & 1).Column 'Then you wouldnt need these two variables
Columns(ColBO).Insert Shift:=xlToRight
'Columns(ColBO).Select ' Trying to avoid selection but not sure if this works here...
'Selection.Insert Shift:=xlToRight
Range(1, ColBO).FormulaR1C1 = "Feb weekly-wk 2"
Range(19, ColBO).FormulaR1C1 = "=VLOOKUP(Comparison!RC2,'Jan16 wk4'!R3C15:R34C24,9,FALSE)"
Range(19, ColBO).AutoFill Destination:=Range("BO19:BO47"), Type:=xlFillDefault
Columns(ColBP).Insert Shift:=xlToRight 'Same here as above
Range(2, ColBP).Style = "20% - Accent6"
Range(2, ColBP).FormulaR1C1 = "Diff"
Range(19, ColBP).FormulaR1C1 = "=RC[-2]-RC[-1]"
For the future: If you can, try to avoid .Select/Selection/.Activate if possible. The code can mostly run without such commands and without activating a cell. ;)
If you are not actually writing BO/BP to the range you are transforming I would go with two ints, stored in a hidden sheet. Read/write each time you run the macro.
This is, in my opinion, the easier solution, other places to go would be global variables or storing it to a file.
If you want to use numeric variables you can change approach and use Cells instead of Range:
'You can use the rows below to know the column number
Range("BO1").Activate
ActiveCell.Value = ActiveCell.Column 'This way you get the column number into the cell
ColNum = ActiveCell.Column 'This way you get the column number into the variable
'So now you know that BO column number is 67 and you can use
Cells(1, 67) = "OK"
'Or, using variables:
RowNum = 1
ColNum = 67
Cells(RowNum, ColNum) = "You Got It!"
This makes you able to loop columns simply using a for ... next
If you need to loop from BO to BR you can use
For ColNum = 67 To 70
Cells(1, ColNum) = "OK"
Next ColNum
Hope it helps.

Excel VBA - Loop through range and set formula in each cell

I've got a workbook where I have one worksheet which contains a lot of data.
My goal is to create a macro that inserts a formula in a separate sheet to copy the data from the first sheet. Lets call the first sheet "Numbers1" and the second sheet "TidyNumbers1".
In the sheet "TidyNumbers1" I want to loop through each cell from column A to M and rows 1 to 60. So I've got a macro that so far looks like this:
Sub updateFormulasForNamedRange()
Dim row, col, fieldCount As Integer
colCount = 13
RowCount = 60
For col = 1 To colCount
For row = 1 To RowCount
Dim strColCharacter
If col > 26 Then
strColCharacter = Chr(Int((row - 1) / 26) + 64) & Chr(((row - 1) Mod 26) + 65)
Else
strColCharacter = Chr(row + 64)
End If
Worksheets("TidyNumbers1").Cells(row, col).Formula = "=IF(Numbers1!E" & col & "<>0;Numbers1!" & strColCharacter & row & ";"")"
Next row
Next col
End Sub
But the formula is supposed to looks like this for Column A, row 2:
IF(Numbers1!E2<>0;Numbers1!A2;"")"
And the formula in Column A, row 3 should look like this:
IF(Numbers1!E3<>0;Numbers1!A3;"")"
Formula in Column B, row 2 should look like this:
IF(Numbers1!E2<>0;Numbers1!B2;"")"
In other words, the formula looks to see if the value in Column E, row % is anything but 0 and copies it if conditions are met.
But, I see that I need to translate my integer variable Row with letters, because the formula probably needs "A" instead of 1. Also, I get a 1004 error (Application-defined or object-defined error) if I just try to use:
Worksheets("Numbers1").Cells(row, col).Formula = "=IF(Numbers1!E" & row & "<>0;Numbers1!" & col & row & ";"")"
I clearly see that the integer row should be translated to letters, if that's possible. Or if anyone has any other suggestions that might work. Also, the 1004 error is unclear to me why happens. I can define a string variable and set the exact same value to it, and there's no error. So it's probably the formula bar that whines about it I guess?
Here is a former post of mine containing functions for conversion of column numbers to letters and vice versa:
VBA Finding the next column based on an input value
EDIT: to your 1004 error: Try something like this:
=IF(Numbers1!E" & row & "<>0,Numbers1!A" & row & ","""")"
(use ; instead of ,, and "" for one quotation mark in a basic string, """" for two quotation marks).
Would not it be easier to get the cell address with the Cells.Address function?
For example:
MsgBox Cells(1, 5).Address
Shows "$E$1"
Best Regards

Excel macro - please xplain this code

If data_version < 2.11 Then
Range("A10").Select
Selection.Copy
Range("A17").Select
ActiveSheet.Paste
ActiveCell.FormulaR1C1 = "Resume Path Information"
Range("A12:B12").Select
Selection.Copy
Range("A18").Select
ActiveSheet.Paste
ActiveCell.FormulaR1C1 = "Server Path:"
Range("B18") = ""
Dim formula As String
Dim cu_row As Integer
cu_row = 5
Do
'Fix cell to add resume server path
If Len(Trim(Worksheets("People").Cells(cu_row, ResumeFile).Value)) > 0 Then
formula = "=Process!B$18 & """ & Right(Worksheets("People").Cells(cu_row, ResumeFile).Value, Len(Worksheets("People").Cells(cu_row, ResumeFile).Value) - 2) & """"
Worksheets("People").Cells(cu_row, ResumeFile).formula = formula
'Else be sure it is blank
Else
Worksheets("People").Cells(cu_row, ResumeFile).ClearContents
End If
cu_row = cu_row + 1
Loop Until Worksheets("People").Cells(cu_row, 1) = ""
Range("A1").Select
End If
Well, strictly it doesn't do anything because you've got a trailing End If that doesn't match any earlier If. But ...
It looks at successive rows of the worksheet called "People", starting in row 5 and stopping when it finds a row with nothing in the first column. For each row, it looks in the column whose number is in variable ResumeFile. If there's nothing but whitespace there, it clears it completely. Otherwise, it throws away the first two characters, and interpolates the rest into the magic string Process!B$18 & "VALUE_GOES_HERE", which it stores (as a formula) into the same cell. Here, & performs string concatenation.
Finally, it selects cell A1 for some reason.
So, if that column of the worksheet contained "Fred", "Jim" and "Sheila" before, and if cell B18 of the "Process" worksheet contains "Boo!", then you'll get "Boo!ed", "Boo!m" and "Boo!eila".

Resources