Referencing formula for row number in Excel Macro - excel

I'm attempting to make a macro which will autofill a number of pages based on how many is actually needed. Each item, imported from another workbook, would receive its own 'page'. These pages are on one sheet, separated by print area. Currently I have a counter which counts the number of items that need pages (11 in my example), then I have a value for number of rows per page (34). Those are multiplied together to determine how many rows to autofill to (374). The issue is getting the macro to replace the range variable with the number (374).
I've tried to use the Indirect function but receive a compile error: "Expected: List separator or )"
I've also attempted the Offset function but receive the same error.
This is my Macro so far:
Sub Sheet_Fill()
Sheet_Fill Macro
ActiveCell.Range("A1:I34").Select
Selection.AutoFill Destination:=ActiveCell.Range("A1:I68"), Type:= _
xlFillDefault
ActiveCell.Range("A1:I68").Select
End Sub
Essentially, I want to replace the "I68" with something that will autofill the row number of the I column with my formula mentioned earlier. In the example case of 11 parts, the number would be autofilled with "374"

The raw version of your macro should be something like this:
Sub Sheet_Fill()
'Sheet_Fill Macro
Dim rownum As Long
rownum = 374 'Or a range? Where is this number located?
ActiveCell.Range("A1:I34").Select
Selection.AutoFill Destination:=ActiveCell.Range("A1:I" & rownum), Type:= _
xlFillDefault
ActiveCell.Range("A1:I" & rownum).Select
End Sub
Cleaned up a bit (this should work):
Sub Sheet_Fill()
Dim rownum As Long
rownum = 374 'Or a range? Where is this number located?
Range("A1:I34").AutoFill Destination:=ActiveCell.Range("A1:I" & rownum), Type:=xlFillDefault
End Sub
Need some more details from you on where you're storing this 374 - is it in a cell? Can it be calculated from your table setup? Until those answers are given, this is the best I can do.

Try:
Selection.AutoFill Destination:=ActiveCell.Range("A1:I" & lr), Type:= xlFillDefault
Where lr is last row... you would either want to determine this dynamically, or you could assign the to pull a value from a cell, e.g.:
'dynamic
lr = sheets(1).cells(sheets(1).rows.count,1).end(xlup).row
'from a cell
lr = sheets(1).range("A1").value
General comment... avoid using select/activate!

Related

Ignore Blank Cells in VBA [duplicate]

This question already has answers here:
Copy Non Blank Cells From Range to Range
(2 answers)
Closed 2 years ago.
I am having difficulty having this macro copy and paste only the cells that have data in them. I would like the macro to only select and copy the cells in the columns that have data, ignore the empty cells. what I currently have is this
Sub testest()
Sheet4.Activate
'Dim lrow As Long
'lrow = Sheet4.Range("A", Rows.Count).End(xlUp).Row
Sheet4.Range("A2:A40").Select
Selection.Copy
Sheet5.Activate
Sheet5.Range("A2").PasteSpecial
Sheet4.Activate
Sheet4.Range("B2:B40").Select
Selection.Copy
Sheet5.Activate
Sheet5.Range("B2").PasteSpecial
End Sub
If you want them to paste only the cells with data by shifting the other cells up to fill in the blank ones, you should try the following commands after you select your desired copy range:
Selection.SpecialCells(xlCellTypeBlanks).Select
Selection.Delete Shift:=xlUp
This logic mirrors going to "Find and Select" > "Blanks" > "Delete"
This is not an answer to your question, merely a way to show you how to reduce your code, by eliminating the obsolete activation and selection actions:
Sub testest()
Sheet4.Range("A2:A40").Copy
Sheet5.Range("A2").PasteSpecial
Sheet4.Range("B2:B40").Copy
Sheet5.Range("B2").PasteSpecial
End Sub
In fact, why don't you simply do this:
Sheet4.Range("A2:B40").Copy
Sheet5.Range("A2").PasteSpecial
(Ranges can go over different columns)
There are ways to avoid the usage of the clipboard, but then the complexity of the macro increases, which, I believe, is not what you're looking for.
Similar to the answer by #Dominique, but addressing the empty cells and assuming you gave up on the last row method:
Sub testest()
Dim lrow As Long
lrow = Sheet4.Range("A", Rows.Count).End(xlUp).Row
Sheet4.Range("A2:A" & lrow).SpecialCells(xlCellTypeVisible).Copy
Sheet5.Range("A2").PasteSpecial
Sheet4.Range("B2:B" & lrow).SpecialCells(xlCellTypeVisible).Copy
Sheet5.Range("B2").PasteSpecial
End Sub

Countif with reference to different sheet

Hello I will need help with problem I am facing right now and even Google couldn't help me.
I would like to add to field AS2 a COUNTIF formula with source information from different sheet.
This COUNTIF should jump to sheet ee_lpk and then take a range from column A2 down to the end of last used row. and compare that with criteria from field D.
so for AS2 will be comparing with D2 for AS3 with D3.
When I recorded that it showed:
ActiveCell.FormulaR1C1 = COUNTIF(ee_lkp!R[-143]C[-44]:R[217]C[-44],R[-143]C[-41])"
this is working but just in case that there is on ee_lpk page same number or rows what is changing from day to day.
Any help will be much appreciated.
Martin
You need to break this problem down using variables. Try something like this:
sub Answer()
Dim srcRng as Range
Dim srcLength as Long
'First find how many rows on sheet ee_lpk and store it as a variable
srcLength = Sheets("ee_lkp").UsedRange.Rows.Count
'Then use that variable to get your range
Set srcRng = Range(Cells(2,1), Cells(srcLength, 1))
'Or another viable option would be:
'Set srcRng = Range("A2:A" & srcLength)
'Then put that in your Countif formula
ActiveCell.FormulaR1C1 = _
"=COUNTIF(ee_lkp!" & srcRng.Address(True, True, xlR1C1) & ", R[-143]C[-41])
End Sub

Autofill Dynamic Column

Trying to Autofill Column X and Column Y with text
Where Column Z determines the table length
Starting cell for column Z is "Z3" but column "X and Y" are dynamic
Last filled cell in column "X & Y" carries the text required.
Current Last cells is "X56" and "Y56"
Current last cell in column Z is "Z89"
I can easily get to x56 or y56 using
Range("Y3").Select
Selection.End(xlDown).Select
Selection.AutoFill Destination:=Range("Y56:Y89")
Range("Y56:Y89").Select
Range("X56").Select
Selection.AutoFill Destination:=Range("X56:X89")
Range("X56:X89").Select
However the solution eludes me to remove absolute references due to the dynamic nature of the information being imported and added to the column of previous information.
I tried this code i read through my research but couldn't make it work
lastRow = Range("Y3").End(xlDown).Row
Selection.AutoFill Destination:=Range("Y3:Y" & lastRow), Type:=xlFillDefault
Any assistance would be really appreciated as this appears to be the lynch pin to completing this task
Cheers
Mick
with I am trying to stack reports generated on a 12 hourly basis.
into an accrued 24 data table. This will then be accrued into a monthly data table.
As base information is downloaded in csv format. The four reports are formatted differently so i also have to stack the four reports in two table separated and itemised by date and shift.
This then allows the use of lookups, countifs sumifs etc to populate my outputs.
The four reports are dynamic and open to the potential of having a number of blank cells throughout.
I have written code that is robust enough to achieve this short of this one issue.
As the four reports do not have time stamps i am forced to use file names (column A:A) to populate the Date and Shift ranges (column A:B) as well as (Column X:Y) but need to drag the text down to cover all rows of information
Range("Y3").Select
Selection.End(xlDown).Select
Selection.AutoFill Destination:=Range("Y56:Y89")
Range("Y56:Y89").Select
Range("X56").Select
Selection.AutoFill Destination:=Range("X56:X89")
Range("X56:X89").Select
Autofill Columns with text without absolute references to allow for dynamic column range and without known starting point on the column
Do not use xlDown to find the last row. You may want to have a look at this Finding Last Row
Is this what you are trying? I have given you two option. Take your pick.
Option Explicit
Sub SampleA()
Dim ws As Worksheet
Dim lRow As Long
'~~> Change this to the relevant sheet
Set ws = Sheet1
With ws
'~~> Get last row in Col Z
lRow = .Range("Z" & .Rows.Count).End(xlUp).Row
'~~> Autofill formula in 1 go
.Range("X3:X" & lRow).Formula = .Range("X3").Formula
.Range("Y3:Y" & lRow).Formula = .Range("Y3").Formula
End With
End Sub
Sub SampleB()
Dim ws As Worksheet
Dim lRow As Long
Dim rng As Range
'~~> Change this to the relevant sheet
Set ws = Sheet1
With ws
'~~> Get last row in Col Z
lRow = .Range("Z" & .Rows.Count).End(xlUp).Row
Set rng = .Range("X3:Y3")
rng.AutoFill Destination:=.Range("X3:Y" & lRow)
End With
End Sub

Excel VBA - For Each - In & end(xltoright)

So here's what I got so far:
Sub SortByGen()
Dim Gen As Range
For Each Gen In Worksheets("Sheet1").Range("B3:G3")
If Gen.Value = "XXX" Then
Gen.EntireColumn.Copy _
Worksheets("XXX").Range("A2").End(xlToRight).Offset(0, 1).EntireColumn
If Gen.Value = "YYY" Then
Gen.EntireColumn.Copy _
Worksheets("YYY").Range("A2").End(xlToRight).Offset(0, 1).EntireColumn
End If
Next Gen
End Sub
I'm trying to sort certain columns from one worksheet to multiple worksheets based on a certain criterion. I accidentally placed a values on
Worksheets("XXX").Range("B2") and Worksheets("YYY").Range("B2")
so when the
.end(xltoright)
ran, the code worked. Now when I try to get rid of the values in B2, the code will get an error.
If you use xlToRight and you're starting from the last occupied cell in that row then it will go to the very end of the row: you can't offset 1 more column from there...
Use this instead:
Gen.EntireColumn.Copy _
Worksheets("XXX").Cells(2, Columns.Count).End(xlToLeft).Offset(0, 1).EntireColumn

adding new rows in excel without breaking a vba macro that uses Range.Value

I've written a macro in VBA that simply fills in a given cell's value from another cell in that sheet. I do this for lots of cells in the sheet, and I'm doing it like so:
Range("B3").Value = Range("B200")
Range("B4").Value = Range("B201")
'etc.
Now, I am often adding values by inserting new rows, so I might insert a new row
between B200 and B201, which will break the macro because it doesn't autoupdate when
I insert the new row.
How can I code the macro so it autoupdates the cell references when I insert new rows or columns?
My suggestion would be to make sure the ROW you want to retrieve values from has a unique value in it that you can .FIND anytime you want, then grab your values from column B of that found cell's row. So right now you want to get a value in B200 and A200 always has the text in it: "Final Total" and that is unique.
Dim MyRNG As Range
Set MyRNG = Range("A:A").Find("Final Total", LookIn:=xlValues, LookAt:=xlWhole)
Range("B3").Value = Range("B" & MyRNG.Row)
Range("B4").Value = Range("B" & MyRNG.Row + 1)
This is not an answer but an alternative.
Naming your range is the way to go as Shiin suggested but then if you have 500 cells then like I mentioned earlier, naming 500 cells and using them in your code can be very painful. The alternative is to use smart code. Let's take an example
Let's say you have a code like this
Sub Sample()
Range("B3").Value = Range("B200")
Range("B4").Value = Range("B201")
Range("B5").Value = Range("B201")
' And
' So On
' till
Range("B500").Value = Range("B697")
End Sub
The best way to write this code is like this
Sub Sample()
Dim i As Long
For i = 200 To 697
Range("B" & i - 197).Value = Range("B" & i)
Next i
End Sub
and say if you insert a line at say row 300 then simply break the above code in two parts
Sub Sample()
Dim i As Long
For i = 200 To 299
Range("B" & i - 197).Value = Range("B" & i)
Next i
For i = 301 To 698
Range("B" & i - 197).Value = Range("B" & i)
Next i
End Sub
So every time you insert a row, simply break the for loop into an extra part. This looks tedious but is much better than naming 500 cells and using them in your code.
If you are planning to use the macro only once (i.e for 1 time use) then read ahead.
If you are worried that when the user inserts the row then the cells are not updated then you can instead of assigning a value, assign a formula.
For example
Range("B3").Formula = "=B200"
This will put a formula =B200 in cell B3. So next time when you insert a row so that the 200th row moves it's position, you will notice that the formula automatically gets updated in cell B3
HTH
Try giving a name to the range. If you refer to the range by name Excel searches for it and retrieves the rows that defines it. Range names update their definition when new rows are added.
Adding to the above, i think this tutorial illustrates my point:
http://www.homeandlearn.co.uk/excel2007/excel2007s7p6.html this is how to define the name of the range.
This tutorial explains how to use it on macros and vba:
http://excel.tips.net/T003106_Using_Named_Ranges_in_a_Macro.html
I hope this helps :D

Resources