Use an input variable inside a formula in macro - variables

I want to use a user input inside a formula as follows:
Sub example()
Dim StockDays As Integer
StockDays = InputBox(Prompt:="How many days?")
Range("AG2").FormulaR1C1 = "=ROUNDUP(RC[-6]*" & StockDays & "/90, 0)"
Range("AG2").Select
Selection.AutoFill Destination:=Range(Cells(2, 33), Cells(1500, 33))
End Sub
When run, the above code throws an error at the ROUNDUP line.
Run-time error 1004.
Application-defined or object-defined error.
I think the problem is related to the variable StockDays.
How can I arrange the code so that I can make it work?

I have commented the code so you shouldn't have any problem understanding it :)
Option Explicit
Sub example()
Dim StockDays As Integer
'~~> Type:=1 will ensure that the user enters only numbers
StockDays = Application.InputBox(Prompt:="How many days?", Type:=1)
'~~> No Need to autofill. You can fill all the range in one go
Thisworkbook.Sheets("Sheet1").Range("AG2:AG1500").FormulaR1C1 = _
"=ROUNDUP(RC[-6] * " & StockDays & "/ 90, 0)"
'OR this as mentioned in your comment
Thisworkbook.Sheets("Sheet1").Range("AG2:AG1500").FormulaR1C1 = _
"=ROUNDUP((RC[-6]* " & StockDays & "/90),0)"
End Sub

I think this should work
Range("AG2").FormulaR1C1 = "=ROUNDUP(RC[-6] * " & StockDays & " / 90, 0)"
the mistake u did was, you where applying a formula but forgot to replace the variable u used with the value in the varaiable

Related

VBA Excel delete multiple rows

This works
mySheet.Rows(CStr(activeRow) & ":" & CStr(activeRow + deletedRowAmount)).Delete
This does not work
mySheet.Columns(CStr(columDelete) & ":" & CStr(columDelete + deletedRowAmount)).Delete
What I am missing here?
ERROR is VBA Runtime Error 1004 “Application-defined or Object-defined error”
Columns are A,B,C,... when used in a string as you are using them. If they are numbers you will need to do it slightly different:
With mySheet
.Range(.cells(1,columDelete), .cells(1,columDelete + deletedRowAmount)).EntireColumn.Delete
End With
In general, what Scott Craner says is quite enough, but here is a way to go around it and make it easier:
Sub TestMe()
Columns(GetColumnRange(2, 5)).Delete
End Sub
Public Function GetColumnRange(colStart As Long, colEnd) As String
GetColumnRange = Split(Cells(1, colStart).Address(True, False), "$")(0) & _
":" & Split(Cells(1, colEnd).Address(True, False), "$")(0)
End Function
Try the TestMe function, it should delete the columns from 2(B) to 5(E).

Detecting last column in sheet

I am trying to use the Lastcolumn from Sheet D in a formula in Sheet M. This is the code I have: D!R[8]C " & LastColumn1 & .
But it looks like the code is using the last column number in sheet M.
Can you please check what is wrong with this code?
Sub misc()
Dim LastColumn1 As Long
LastColumn1 = ActiveWorkbook.Worksheets("D").Range("a12").End(xlToRight).Column
End Sub
Sub try()
Sheet1.Select
Range("A4").Select
ActiveCell.End(xlToRight).Offset(-2, 1).Value = counter & "Qtr"
Do While ActiveCell.Value <> ""
ActiveCell.End(xlToRight).Offset(0, 1).Formula = "=IFERROR(D!R[8]C " & LastColumn1 & " *(1+INDEX(A!R3C4:R418C27,MATCH(M!R2C,A!R2C4:R2C27,0))),0)"
ActiveCell.Offset(1, 0).Select
Loop
End Sub
You need a function for this.
Function LastColumn() as long
LastColumn = ThisWorkbook.Worksheets("D").Range("a12").End(xlToRight).Column
end function
And then you call that function directly from your code:
Sub try()
Sheet1.Select
Range("A4").Select
lastCol = LastColumn '## Calling the function from above
ActiveCell.End(xlToRight).Offset(-2, 1).Value = counter & "Qtr"
Do While ActiveCell.Value <> ""
ActiveCell.End(xlToRight).Offset(0, 1).Formula = "=IFERROR(D!R[8]C " & lastCol & " *(1+INDEX(A!R3C4:R418C27,MATCH(M!R2C,A!R2C4:R2C27,0))),0)"
ActiveCell.Offset(1, 0).Select
Loop
End Sub
Can you please check what is wrong with this code?
You have an undeclared/uninitialized variable called LastColumn1 which you are using in a formula string. This variable has no value at runtime, which causes the error.
How to resolve it:
If you had simply used Option Explicit, you would be informed of a compilation error. LastColumn1 variable is undeclared within the scope of the try() procedure.
Since you are not using Option Explicit (which requires that all variables be declared), the compiler initializes undeclared variables as type Variant, with an empty/0/null-string value.
So, what you have essentially is an obvious error with:
ActiveCell.End(xlToRight).Offset(0, 1).Formula = _
"=IFERROR(D!R[8]C " & EMPTY & " * _
(1+INDEX(A!R3C4:R418C27,MATCH(M!R2C,A!R2C4:R2C27,0))),0)"
Because the result of that concatenation is: D!R[8]C and that is an invalid Range (without a column index), it is undefined/cannot exist as such.
Using #iDevelop's function above will probably suffice for most ordinary, simple cases, however you may want to review the more robust methods described here:
Error in finding last used cell in VBA

Excel Macro IF replace formula

I am trying to replace the value in a cell so if it has 0 to hide it.
The excel formula is the following IF(A1=0;"";A1).
I am trying to this automaticaly but I am having problems.
So far I came up with this:
Sub apply_Error_Control()
Dim cel As Range
For Each cel In Selection
If cel.HasFormula Then
cel.Formula = Replace(cel.Formula, "=", "=IFF(") & "=0" & ";" & "")"
End If
Next cel
End Sub
Give this link a view:
Three ways to hide zero values
I'd still strongly recommend going down the cell formatting route:
Sub apply_Error_Control()
Dim rngCurrent As Range
If TypeName(Selection) = "Range" Then
Set rngCurrent = Selection.SpecialCells(xlCellTypeFormulas)
rngCurrent.NumberFormat = "0;-0;;#"
End If
End Sub
But if you insist on the formula-based approach, please at least employ the method I've outlined so that you avoid running the code on (for example) an embedded chart or button and you'll immediately hit those cells with a formula - looping through to find those with a formula is tedious and slow.
Give this a try (note the Selection.Cells so it'll only work in the Range that you selected manually) :
Sub apply_Error_Control()
Dim cel As Range, _
RangeInForumla As String
For Each cel In Selection.Cells
If cel.HasFormula Then
RangeInForumla = Replace(cel.Formula, "=", "",1,1)
cel.Formula = "=IF(" & RangeInForumla & "=0," & Chr(34) & Chr(34) & "," & RangeInForumla & ")"
End If
Next cel
End Sub

Looping a Cell Reference in a match function

I'm pretty new to VBA and was wondering why my formula doesnt work?
I'm trying to loop the cells Sheets("Summary").Cells(11 + X, 13) in my match function but it doesn't seem to work. Am I doing something wrong?
Sub Reset()
Dim X As Integer
For X = 0 To 19
Sheets("Summary").Cells(11 + X, 13).Select
Selection.Formula = "=INDEX(YMAX!$A:$W,MATCH(Summary!$J$4&"" ""&Summary!$J$5&"" ""&11,YMAX!$B:$B,0),MATCH(sheets("Summary").cells(11 + x,9),YMAX!$1:$1,0))"
Next X
End Sub
It looks like you have the following errors
&'s are in the wrong places (should be outside of the quotes when concatenating text, inside the quotes when concatenating cell references)
Variables (i.e. your reference to a cell on the "Summary" sheet) do
not need to be in quotes when building a string in VBA
(not an error, per say) You don't need to do .Select as you can
set the formula of the cell directly.
Update your code with the following
Sub Reset()
Dim X As Integer
For X = 0 To 19
' Broken up on several lines for clarity
Sheets("Summary").Cells(11 + X, 13).Formula =
"=INDEX(YMAX!$A:$W,MATCH(Summary!$J$4" & " " & _
"Summary!$J$5" & " " & _
"11,YMAX!$B:$B,0),MATCH(" & _
Sheets("Summary").Cells(11 + X,9).Address & _
",YMAX!$1:$1,0))"
Next X
End Sub
I'm not sure if that's the formula you want exactly, but it's what i interpreted given your current code. Let me know if that works for you.

How do I get a range's address including the worksheet name, but not the workbook name, in Excel VBA?

If I have a Range object--for example, let's say it refers to cell A1 on a worksheet called Book1. So I know that calling Address() will get me a simple local reference: $A$1. I know it can also be called as Address(External:=True) to get a reference including the workbook name and worksheet name: [Book1]Sheet1!$A$1.
What I want is to get an address including the sheet name, but not the book name. I really don't want to call Address(External:=True) and try to strip out the workbook name myself with string functions. Is there any call I can make on the range to get Sheet1!$A$1?
Only way I can think of is to concatenate the worksheet name with the cell reference, as follows:
Dim cell As Range
Dim cellAddress As String
Set cell = ThisWorkbook.Worksheets(1).Cells(1, 1)
cellAddress = cell.Parent.Name & "!" & cell.Address(External:=False)
EDIT:
Modify last line to :
cellAddress = "'" & cell.Parent.Name & "'!" & cell.Address(External:=False)
if you want it to work even if there are spaces or other funny characters in the sheet name.
Split(cell.address(External:=True), "]")(1)
Ben is right. I also can't think of any way to do this. I'd suggest either the method Ben recommends, or the following to strip the Workbook name off.
Dim cell As Range
Dim address As String
Set cell = Worksheets(1).Cells.Range("A1")
address = cell.address(External:=True)
address = Right(address, Len(address) - InStr(1, address, "]"))
The Address() worksheet function does exactly that. As it's not available through Application.WorksheetFunction, I came up with a solution using the Evaluate() method.
This solution let Excel deals with spaces and other funny characters in the sheet name, which is a nice advantage over the previous answers.
Example:
Evaluate("ADDRESS(" & rng.Row & "," & rng.Column & ",1,1,""" & _
rng.Worksheet.Name & """)")
returns exactly "Sheet1!$A$1", with a Range object named rng referring the A1 cell in the Sheet1 worksheet.
This solution returns only the address of the first cell of a range, not the address of the whole range ("Sheet1!$A$1" vs "Sheet1!$A$1:$B$2"). So I use it in a custom function:
Public Function AddressEx(rng As Range) As String
Dim strTmp As String
strTmp = Evaluate("ADDRESS(" & rng.Row & "," & _
rng.Column & ",1,1,""" & rng.Worksheet.Name & """)")
If (rng.Count > 1) Then
strTmp = strTmp & ":" & rng.Cells(rng.Count) _
.Address(RowAbsolute:=True, ColumnAbsolute:=True)
End If
AddressEx = strTmp
End Function
The full documentation of the Address() worksheet function is available on the Office website: https://support.office.com/en-us/article/ADDRESS-function-D0C26C0D-3991-446B-8DE4-AB46431D4F89
I found the following worked for me in a user defined function I created. I concatenated the cell range reference and worksheet name as a string and then used in an Evaluate statement (I was using Evaluate on Sumproduct).
For example:
Function SumRange(RangeName as range)
Dim strCellRef, strSheetName, strRngName As String
strCellRef = RangeName.Address
strSheetName = RangeName.Worksheet.Name & "!"
strRngName = strSheetName & strCellRef
Then refer to strRngName in the rest of your code.
You may need to write code that handles a range with multiple areas, which this does:
Public Function GetAddressWithSheetname(Range As Range, Optional blnBuildAddressForNamedRangeValue As Boolean = False) As String
Const Seperator As String = ","
Dim WorksheetName As String
Dim TheAddress As String
Dim Areas As Areas
Dim Area As Range
WorksheetName = "'" & Range.Worksheet.Name & "'"
For Each Area In Range.Areas
' ='Sheet 1'!$H$8:$H$15,'Sheet 1'!$C$12:$J$12
TheAddress = TheAddress & WorksheetName & "!" & Area.Address(External:=False) & Seperator
Next Area
GetAddressWithSheetname = Left(TheAddress, Len(TheAddress) - Len(Seperator))
If blnBuildAddressForNamedRangeValue Then
GetAddressWithSheetname = "=" & GetAddressWithSheetname
End If
End Function
rngYourRange.Address(,,,TRUE)
Shows External Address, Full Address
The best way I found to do this is to use the following code:
Dim SelectedCell As String
'This message Box allows you to select any cell on any sheet and it will return it in the format of =worksheetname!$A$X" where X is any number.
SelectedCell = Application.InputBox("Select a Cell on ANY sheet in your workbook", "Bookmark", Type:=8).Address(External:=True)
SelectedCell = "=" & "'" & Right(SelectedCell, Len(SelectedCell) - Len("[" & ActiveWorkbook.Name & "]") - 1)
'Be sure to modify Sheet1.Cells(1,1) with the Sheet and cell you want to use as the destination. I'd recommend using the Sheets VBA name.
Sheet1.Cells(1, 1).Value = SelectedCell
How it works;
By Clicking on the desired cell when the message box appears. The string from "Address(External:=True)" (i.e ['[Code Sheet.xlsb]Settings'!$A$1) is then modified to remove the full name of the worksheet([Code Sheet.xlsb]).
Using the previous example it does this by taking the "Len" of the full length of;
[Code Sheet.xlsb]Settings'!$A$1 and subtracts it with the Len of ([Code Sheet.xlsb] -1). leaving you with Settings'!$A$1.
SelectedCell = "=" & "'" & Right(SelectedCell, Len(SelectedCell) - Len("[" & ActiveWorkbook.Name & "]") - 1)
The Code then its and "='" to insure that it will be seen as a Formula (='Settings'!$A$1).
Im not sure if it is only on Excel on IOS but for some reason you will get an Error Code if you add the "='" in any other way than "=" & "'" as seen bellow.
SelectedCell = "=" & "'" & Right....
From here all you need is to make the program in the Sheet and cell you want your new formula in.
Sheet1.Cells(1, 1).Value = SelectedCell
By Opening a new Workbook the full Code above will work as is.
This Code is Especially useful as changing the name of the workbook or the name of the sheet that you are selecting from in the message box will not result in bugs later on.
Thanks Everyone in the Forum before today I was not aware that External=True was a thing, it will make my coding a lot easier. Hope this can also help someone some day.
Why not just return the worksheet name with
address = cell.Worksheet.Name
then you can concatenate the address back on like this
address = cell.Worksheet.Name & "!" & cell.Address
Dim rg As Range
Set rg = Range("A1:E10")
Dim i As Integer
For i = 1 To rg.Rows.Count
For j = 1 To rg.Columns.Count
rg.Cells(i, j).Value = rg.Cells(i, j).Address(False, False)
Next
Next
For confused old me a range
.Address(False, False, , True)
seems to give in format TheSheet!B4:K9
If it does not why the criteria .. avoid Str functons
will probably only take less a millisecond and use 153 already used electrons
about 0.3 Microsec
RaAdd=mid(RaAdd,instr(raadd,"]") +1)
or
'about 1.7 microsec
RaAdd= split(radd,"]")(1)
[edit on 2009-04-21]
As Micah pointed out, this only works when you have named that
particular range (hence .Name anyone?) Yeah, oops!
[/edit]
A little late to the party, I know, but in case anyone else catches this in a google search (as I just did), you could also try the following:
Dim cell as Range
Dim address as String
Set cell = Sheet1.Range("A1")
address = cell.Name
This should return the full address, something like "=Sheet1!$A$1".
Assuming you don't want the equal sign, you can strip it off with a Replace function:
address = Replace(address, "=", "")