Application or Object defined error in range.formula - vba

I am trying to set a formula to certain cells. The code for setting the formula in a for loop is like this:
For i = 0 To MotorAmount
Set myCell = Range(Target.Address).Offset(i, 1)
myCell.Formula = "=IFERROR(VLOOKUP(Range(Target.Address);Database!$B$31:$G$131;2;False);0)"
Next i
However I get an application or object defined error on the line that starts with myCell.Formula. I hope someone can tell me why the error occurs and how to fix it.
PS: I use semicolons in the formula because my Excel works like that. the 'Database' is the name of another sheet I use.
PS2: The sub is placed in Sheet1 under Microsoft Excel Objects in the VBAProject.
The complete code is:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim myRange As Range
Dim myCell As Range
Dim i As Integer
Dim MotorAmount As Integer
Set myRange = Range("A68:A168")
If Not Application.Intersect(myRange, Range(Target.Address)) Is Nothing Then
If Not Range(Target.Address) = "" Then
MotorAmount = InputBox("How many motors are used in this transport?", "Amount of motors")
For i = 0 To MotorAmount
Set myCell = Range(Target.Address).Offset(i, 1)
myCell.Formula = "=IFERROR(VLOOKUP(Range(Target.Address);Database!$B$31:$G$131;2;False);0)"
Next i
End If
End If
End Sub

Your formula implementation should be:
myCell.Formula = "=IFERROR(VLOOKUP(" & Target.Address & ",Database!$B$31:$G$131,2,False),0)"
Note: In VBA use commas while writing formula, in native it will automatically show the correct argument separator you are using.

You can't put code inside a formula and you should be using commas not semicolons in the formula as VBA is US-centric. I'd suggest using R1C1 references:
myCell.FormulaR1C1 = "=IFERROR(VLOOKUP(R" & Target.Row & "C1,Database!R31C2:R131C7,2,False),0)"

Related

Is it possible in VBA to write an invalid formula to a range?

I have the following code in a VBA macro:
Option Explicit
Sub WriteFormula()
Dim rng As Range
Set rng = Range("A1:B2")
' Works
rng.Formula = "=ROUNDUP(1, 1)"
' Doesn't work
rng.Formula = "=ROUNDUP(1)"
End Sub
The second write contains an invalid formula and causes a runtime exception:
Is there any way to disable error checking so that the second write succeeds?
No, you cannot bypass error control and write the bad formula but you could change the formula to text and write the text. This would give you the opportunity to view what was attempted to be written and correct it on the worksheet before applying the modifications to the VBA code.
Option Explicit
Sub WriteFormula()
Dim str As String
Dim rng As Range
Set rng = Range("A1:B2")
On Error GoTo forceWriteText
' Doesn't work
str = "=ROUNDUP(1)"
rng.Formula = str
Exit Sub
forceWriteText:
rng.Value = Chr(39) & str
End Sub
A bit tricky, but you could write your 'wrong' formula as a string in one cell, then, in another cell, use the hidden evaluate function (see https://stackoverflow.com/a/4472470/78522)
Well, cheeky answer.
Option Explicit
Sub WriteFormula()
Dim rng As Range
Set rng = Range("A1:B2")
' Works
rng.Formula = "=ROUNDUP(1, 1)"
' Doesn't work
rng = "'=ROUNDUP(1)"
End Sub
The Second formula is wrong syntax, = Round(number,num_digits) so its throws an error. Either remove it or correct it.
Thank You.
If you want to avoid the error for second line then you use "On Error Resume Next" statement. First statement will be succeed.

VBA set cell value after .ClearContents

Why does the cell value not set in another function when clearing the contents of the range in another function?
I'm trying to set a cell value to "All" after clearing the cells in the range. I've even tried to get a message box to pop up to see if i can somehow check if my check value is correct.
DelRange is the range i'm clearing.
Building is the cell that i'm checking the value for and if it's blank, it needs to change to "All".
clearPreviw is used to clear another sheet, which it's doing.
Sub ClearSheet()
Dim Dash As Worksheet
Dim DelRange As Range
Dim Building As Range
Set Dash = ActiveWorkbook.Worksheets("DASH")
Set DelRange = Dash.Range("FilterData")
Set Building = Dash.Range("SelBuild")
DelRange.ClearContents
Call clearPreview
'This part below doesn't work when the Range.ClearContents has been done, but doing it on it's own without clearing the range works fine
If Building.Value = "" Then
MsgBox "Building is empty", vbOKOnly
Building.Value = "All"
End If
End Sub
I've run this test as a separate process which works, but once again when running it as a call function right after .ClearContents seems to stop this.
Sub test()
Dim Dash As Worksheet
Dim DelRange As Range
Dim Building As Range
Set Dash = ActiveWorkbook.Worksheets("DASH")
Set DelRange = Dash.Range("FilterData")
Set Building = Dash.Range("SelBuild")
If Building.Value = "" Then
MsgBox "Building is empty", vbOKOnly
Building.Value = "All"
End If
End Sub
I've been poking at it and searching but i can't wrap my head around this.
I think you are missing:
Building.ClearContents;
Also I would prefer:
If IsEmpty(Building.Value) Then
over:
If Building.Value = "" Then
This link gives you a good start on how to set range variables (although I would advice you against the use of .Select and .Activate).
After that, use .ClearContents or .Clear, depending on your needs.
If you properly cleared the ranges, there is no need to check if they are empty, so this might be a redundant step within your current planning.

Excel VBA - How to alter the value of multiple cells inputted by the user?

I have a worksheet on Excel in which the user must input some registration numbers in column C. These numbers are usually inserted by the user by copying a pasting several of them at a time. The format of the copy source is often in the format "000.000.000-00", but I want it to be just "00000000000" in the worksheet, without the dots and dash.
I am trying to develop a code in Excel VBA to automatically remove these dots and dash after the user types or paste the registration number. I need it to be in the same cell. The code is:
Private Sub Worksheet_Change(ByVal Target As Range)
Dim SkipEvents As Boolean
If SkipEvents Then Exit Sub
With ActiveWorkbook.Sheets("Staff")
If Not Application.Intersect(Target, Me.Range("C:C")) Is Nothing Then
SkipEvents = True
li = Intersect(Target, Range("C:C")).Row
nl = Intersect(Target, Range("C:C")).Rows.Count
lf = li + nl - 1
For i = li To lf
RegNumb = Range("C" & i).Value
If Len(RegNumb) = 14 Then
Range("C" & i).Value = Left(RegNumb, 3) & Mid(RegNumb, 5, 3) & Mid(RegNumb, 9, 3) & Right(RegNumb, 2)
End If
Next i
SkipEvents = False
End If
End With
End Sub
So far, the code is able to remove the dots and dash if the user types or copy+paste one registration number at a time. However, when the user copy+paste 2 or more registraton numbers at a time, only the first cell from the range have its dots and dash removed, and the others stay as they are. Can someone help me with this problem?
Only the first cell in the range is being changed by your code because you are not iterating over the range. You could instead do this:
For each c in Target
if c.column = 3 then
c.value = Replace(Replace(c.value, ".", ""), "-", "")
end if
Next c
inside your Worksheet_Change.
You can replace directly on the entire desired range. You'll also need to Disable Events from firing since the changes you make will again fire the code. Also, since it's sheet level code, no need to refer to the sheet.
Private Sub Worksheet_Change(ByVal Target As Range)
Dim rCheck as Range
Set rCheck = Application.Intersect(Target, Me.Range("C:C"))
If Not rCheck is Nothing
Application.EnableEvents = False
rCheck.Replace(".","",lookat:=xlPart)
rCheck.Replace("-","",lookat:=xlPart)
Application.EnableEvents = True
End If
End Sub
I will also warn that if the data set being checked is very large, this replace method can have poor performance. However, if copy / paste is relatively small in terms of cell counts, it should be fine.

Excel VBA. For each row in range, for each cell in row, for each character in cell

I have created a VBA macro simple to absurdity.
For each row in range, then for each cell in row and then for each character in cell.
But it returns property or method not supported.
Now, to refer to each character in a cell in Excel VBA, it has to be defined as a range. So how is not a cell in a row in a range not a range object?
In all Excel examples the cells with Characters property have been referred to in absolute values. Like Worksheets("Sheet1").Range("A1")
Do I have to write a code of
Worksheets("MySheet").Range("B1")
...
Worksheets("MySheet").Range("B2")
...
...
Worksheets("MySheet").Range("B250")
To access characters or is there a way to access each character in a cell without Mid function?
By the way, Mid function looses formatting but I am looking for underlined characters.
My program is like this
Sub Celltest()
For Each rw In Sheets("Joblist").Range("B1:D250").Rows
For Each cel In rw.Cells
For Each char In cel.Characters
If char.Font.Underline = True Then MsgBox char
Next
Next
Next
End Sub
As a result I get message that a property or method is not supported.
Thank you!
David
"Why is suddenly a part of a range object suddenly not a range?" That's not the issue. The error is Object doesn't support this property or method. That means that (basically) anything after the . is an object, so the error is telling you that something is up with how you're using .Character.
I did some quick searching around, and this works:
Sub Celltest2()
Dim rw As Range, cel As Range
Dim i As Integer
Dim char
For Each rw In Sheets("Joblist").Range("B1:D250").Rows
For Each cel In rw.Cells
For i = 1 To Len(cel)
'Debug.Print cel.Characters(i, 1).Text
If cel.Characters(i, 1).Font.Underline = 2 Then
MsgBox (cel.Characters(i, 1).Text)
End If
Next i
Next
Next
End Sub
I just looked up the Characters Object documentation, and there is the answer of how to use .Characters. The issue is how .Characters is used with the range - no sophisticated skills or knowledge necessary. Just use the VB Error messages.
Two things I noticed. 1. Characters is not a collection, so For Each won't work. 2. Font.Underline is not Boolean. Try something like:
Sub Celltest()
Dim rw As Excel.Range
Dim cel As Excel.Range
Dim char As Excel.Characters
Dim I As Long
For Each rw In Sheets("Joblist").Range("B1:D250").Rows
For Each cel In rw.Cells
For I = 1 To cel.Characters.Count
Set char = cel.Characters(I, 1)
If char.Font.Underline <> xlUnderlineStyleNone Then MsgBox char.Text
Next I
Next
Next
Set rw = Nothing
Set cel = Nothing
Set char = Nothing
End Sub
Hope that helps

Does there exist a VBA command which does not change the formula of a cell, but its value?

Suppose in a worksheet the formula of R4 cell is =B1+B2, and its current value is 10.
A VBA command Range("R4").Value = 5 will change both its formula and its value to 5.
Does anyone know if there exists a VBA command which changes the value of R4 to 5, but does not change its formula, such that its formula is still =B1+B2?
PS: we can also achieve the same state in another way: 1) do a Range("R4").Value = 5 2) change the formula of R4 to =B1+B2 but without evaluating it. In this case, does there exist a VBA command which change the formula of a cell without evaluating it?
Edit: What I want to do is...
I would like to write a function, which takes a worksheet where some cells may be out of date (the formula does not match its value), and generates automatically a VBA Sub, this VBA Sub can reproduce this worksheet. The VBA Sub may look like:
Sub Initiate()
Cells(2,3).Value = 5
Cells(4,5).Value = 10
...
Cells(2,3).Formula = "=2+3"
Cells(4,5).Formula = "=C2+C2"
...
End Sub
Such that running Initiate() builds one worksheet with same values and formulas.
Without the VBA command I am asking, this Initiate() will be hard to generated.
You cannot change the value of a cell to something different than what the cell formula computes to.
Regarding your p.s.: You can probably change the formula of a cell without re-evaluation by changing the calculation mode to manual. But that would of course apply to the entire workbook, not just this one cell
EDIT: maybe a solution would be to temporarily save the formula of the cell in either a tag of that cell, or a hidden worksheet?
It is quite simple to change the result of a formula without changing the formula itself:
Change the value of of its argument(s). This is a Solver-type approach:
Sub ForceDesiredResult()
Dim r As Range
Set r = Range("B2")
With r
If r.HasFormula Then
.Formula = .Formula & "-5"
Else
.Value = .Value - 5
End If
End With
End Sub
Here is some very dirty code that will save all values of all formulas on the active sheet as custom properties of the sheet, and a 2nd sub that will mark red all cells where the value has changed from it's original value, while preserving all formulas. It will need some error-checking routines (property already exists, property doesn't exist,...) but should give you something to work with. Since I don't really understand your problem it's a bit hard to say ;)
Sub AddCustomProperty()
Dim mysheet As Worksheet
Dim mycell2 As Range
Dim myProperty As CustomProperty
Set mysheet = ActiveWorkbook.ActiveSheet
For Each objcell In mysheet.UsedRange.Cells
Debug.Print objcell.Address
If objcell.HasFormula Then Set myProperty = mysheet.CustomProperties.Add(objcell.Address, objcell.Value)
Next objcell
End Sub
Sub CompareTags()
Dim mysheet As Worksheet
Dim mycell2 As Range
Dim myProperty As CustomProperty
Set mysheet = ActiveWorkbook.ActiveSheet
For Each objcell In mysheet.UsedRange.Cells
Debug.Print objcell.Address
If objcell.HasFormula Then
On Error Resume Next
If mysheet.CustomProperties(objcell.Address).Value <> objcell.Value Then
objcell.Font.ColorIndex = 3
On Error GoTo 0
End If
End If
Next objcell
End Sub