Wha is setting a cell to a value not working? - vba

This must be a very stupid problem, but I just cannot set a value into a cell. I have a very complex VBA file where I try to do that without success, so I simplified my test to a basic empty sheet that contains just one function:
Function test()
Set Worksheets("Sheet1").Range("A1").Value = 3.1415
End Function
a code copy/pasted from an example here:
https://learn.microsoft.com/en-us/office/vba/api/excel.range.value
It doesn't work. Cell A1 stays blank.
Can anyone see the elephant I am missing?

The Set keyword assigns an object reference to a variable – for example, a reference to a worksheet:
Dim sheet As Worksheet
Set sheet = Worksheets("Sheet1")
3.1415 is a primitive value, not an object reference, so you'd do the assignment without Set:
Worksheets("Sheet1").Range("A1").Value = 3.1415

Related

Excel VBA Worksheets.Cells returning value instead of range

The following line is not working:
If Worksheets(Specialist).Cells(projectrow, WeekLoop + 4).Interior.Color = ReferenceCellColorPlanned.Interior.Color Then
where "ReferenceCellColorPlanned" is an user-input range in the formula
where "Specialist" is a string (and the worksheet does exist)
where "projectrow" and "WeekLoop" are integers
The problem is it always goes through the "If" criteria, no matter what the actual background is. So I tried to debug and set the following (simplified code, only taking out the bits that are needed)
Dim Cel1 as Range
Set Cel1 = Worksheets(Specialist).Cells(projectrow, WeekLoop + 4)
If Cel1.Interior.Color = ....
Then what I noticed is Cel1 actually returns a string value of what is the value of the cell, instead of the range value (which I find weird since as far as I understand, "Cells" is by default a range object and I declared Cel1 as a Range Variable).
Kindly help me understand why worksheets.cells is returning a string instead of a range, and how to make it return the range so I can check its background color. Thanks!
EDIT: I've always tried worksheets.Range(Cells()) as well, and it doesn't work either
Excel and VBA are in general user-friendly. Thus, the object Cell returns something, that would make sense to the user – its value, and not something a bit useless like the address of the object, which would someone working with Java expect (see: What's the simplest way to print a Java array?):
int[] intArray = new int[] {1, 2, 3, 4, 5};
System.out.println(intArray); // prints something like '[I#3343c8b3'
If you are familiar with Python, consider that the object Cells have a __repr__ method implemented, which returns their value - What is the difference between __str__ and __repr__?
In VBA, the __repr__ is achieved with the Default Member attribute:
Default Member (CPearson)
Is "Value" actually the default property of the Range object?
VBA Attributes - The High End VBA (MySite)
VB Attributes - What are they and why should we use them (ChristopherMcClellan)
Concerning the .Interior.Color property, you may access it easily like this and see the values you are comparing:
Public Sub TestMe()
Debug.Print Worksheets(1).Cells(1, 1).Interior.Color
Debug.Print Worksheets(2).Range("A10").Interior.Color
End Sub
Even though the Cell is returning its Value when getting printed via MsgBox, you should still be able to compare the Cell Colors since the variable itself remains an Range Object.
Following sample code works fine for me.
Sub test()
Dim Cel2 As Range
Dim Cel3 As Range
Set Cel2 = Worksheets(1).Cells(1, 1)
Set Cel3 = Worksheets(1).Cells(2, 2)
If Cel2.Interior.Color = Cel3.Interior.Color Then
MsgBox ("YES")
Else
MsgBox ("NO")
End If
End Sub

Excel VBA .Find Function changing values in selection

Heya this is probably simple but I cannot figure out what is wrong.
I am trying to do .find for a specific date and change that selection to a user input date.
I have a userform to select a date from a combobox (date1_cbo). The combobox source is linked to dates on a worksheet (Backend). There is a textbox below for writing the new date to change it to (date1_txt). I keep getting an error
object variable or with block variable not set.
I have tried a few options without any luck here is my code:
Dim selection As Range
Dim check As Boolean
'input box validation
check = IsDate(date1_txt.Value)
If check = True Then
'find cell matching combobox
With Worksheets("Backend").Range("A1:A500")
Set selection = .Find(date1_cbo.Value) 'this is the problem
selection.Value = date1_txt.Value
End With
Else
End If
Interestingly .Find returns the range or Nothing. however because the combobox is linked to the cells I am searching through this should never return nothing... I dont understand why the error is occurring.
a variable named as 'selection' is bad coding practice but totally legal. Don't use such names for the sake of clarity.
Error 91 is caused when you are trying to read a property( .value) from null object. your selection variable is null cause date formats on the sheet and combobox are different.
Just convert to date before attempting to find it in sheet.
Set selection = .Find(CDate(date1_cbo.Value)) '/ once again, selection is valid but bad name for variable.
You are using a variable named Selection. VBA uses it as well. Rename your variable to anything else, rewrite your code and it should work. Even Selection1 is quite ok:
Public Sub TestMe()
Dim selection1 As Range
With Worksheets(1).Range("A1:A500")
Set selection1 = .Find("vi")
End With
If Not selection Is Nothing Then
selection1.Value = "some other value"
End If
End Sub
To change multiple values with Find() as here - A1:A10, then some possibility is to do it like this:
Public Sub TestMe()
Dim myRng As Range
With Worksheets(1).Range("A1:A500")
.Range("A1:A10") = "vi"
Set myRng = .Find("vi")
If Not myRng Is Nothing Then
Do Until myRng Is Nothing
myRng.Value = "New value"
Set myRng = .Find("vi")
Loop
End If
End With
End Sub
It is a bit slow, as far as it loops every time and it can be improved, if the range is united and replaced at once.

To modify INDEX-MATCH which is not working

Basically this is supposed to be a modified INDEX/MATCH formula but will depend on variables and headers on another workbook, as well as hopefully make it easier on the user by only requiring them to provide two parameters.
Option Compare Text
Function DATAFILL(ID_number, source_headerRow) As Variant
ID_header_name = Cells.Item(1, ID_number.column).Value
Dim wb As String, ws As String
Dim ID_src As Range
'check if source_headerRow is an external workbook
If source_headerRow Like "'" Then
src = Split(source_headerRow.address(External:=True), "!")(0)
wb = Replace(Split(src, "]")(0),"[","")
ws = Split(src, "]")(1)
id_col = Application.WorksheetFunction.Match(ID_header_name, source, 0)
Set ID_src = Workbooks(wb).Worksheets(ws).Range(Cells(1, id_col))
Else
Set ID_src = Range(Cells(1, Application.WorksheetFunction.Match(ID_header_name, source_headerRow, 0)))
End If
headername = "Shift" 'placeholder
Set addr = Workbooks(wb).Range("A:Z")
DATAFILL = Application.WorksheetFunction.Index(addr, Application.WorksheetFunction.Match(ID_number, ID_src), Application.WorksheetFunction.Match(headername, source_headerRow, 0))
End Function
I'm very new to VBA so I can't pinpoint exactly where I'm going wrong...
No matter what I do, I get #VALUE! error.
Or is there a way to make INDEX/MATCH user friendly without needing VBA/Macros?
You don't say what line is give you the VALUE error. That would help.
Or is it in a specific cell?
You haven't defined "addr" variable type anywhere that I can see
and you don't have OPTION EXPLICIT at the top, so by default "addr" wil be a Variant data type.
It needs to be Object at minimum and preferably Range
You should add Option Explicit to the top of your module (above Option Compare Text) and recompile until you can fix all the errors (if there are more)

Value in cell as variable in select formula

I have programmed the following VBA code:
Sub test()
Dim Variable As Variant
Variable = "R2:R11"
Sheet1.Select
Range(Variable).Select
End Sub
This formula works perfectly. Now I want to replace the "R2:R11" part of the variable and instead referring to a cell (W12) in the spreadsheet. In this cell I have written "R2:R11" and I changed the formula to the following:
Variable = Sheet1.Range("W12")
which leads to the following code:
Sub test()
Dim Variable As Variant
Variable = Sheet1.Range("W12")
Sheet1.Select
Range(Variable).Select
End Sub
However, with this formula I now get the ERROR 1004.
Do you guys have any solution how I can make the variable referring to the cell in the spreadsheet and then use it in the select formula?
Thanks for any help :-)
You need to declare your variables properly and access the actual .Value property of the Range object.
Sub test()
Dim Variable As String
Variable = Sheet1.Range("W12").Value
Sheet1.Select
Range(Variable).Select
End Sub
Which can also be written as:
Sub test()
Sheet1.Activate
Range([W12]).Activate
End Sub
A note on the .Value property - if you omit this, the value will usually be assigned anyway because it's the default property of the range object. That being said there are scenarios where this won't be the case and therefore it's always best practice to explicitly state that you want the value.
you most probably typed "R2:R11" in W12 cell, i.e with double quotes too
in that cell you only have to type R1:R12
moreover you can simply code
Sub test()
Sheet1.Range(Sheet1.Range("W12")).Select
End Sub

Method Back Reference to calling Worksheet/Cell

I have a method to execute a Distinct Result from a Table Column on a Worksheet.
The result of the Method will go into a Data-Validation listbox in a cell. I have two needs right now that require me to "dummy mitigate" the method's use, by limiting the number of columns passed to the method by one. This part i can get done, what i would like to do is have it so that if there are multiple columns in the Range, then it "pukes" on the user, stating that an illegal function call was made from "Worksheet"."Cell" and to alert the IT Support to resolve the problem.
Getting the Worksheet is great and the easy part. Its more of getting the reference to the Calling Cell without explicitely forcing the IT Support to pass the Cell as a value to the method.
Any ideas on how to extract the Calling Cell?
Ultimately this method will be used across several worksheets to perform the same logic with different ranges being passed to it.
Edited 2012-09-24 10:30am CST
Here is my implementation so far, havent utilized the Application.Caller method into it.
Function UniqueValues(ws As Worksheet, col As String) As Variant
Dim rng As Range: Set rng = ws.Range(col)
Dim dict As New Scripting.Dictionary
If Not (rng Is Nothing) Then
Dim cell As Range, val As String
For Each cell In rng.Cells
val = CStr(cell.Value)
If Not dict.Exists(val) Then
dict.Add val, val
End If
Next cell
End If
'Return value
UniqueValues = dict.Items
End Function
This method is already being used in code-behind logic. I will be copying this logic and making it apart of the Application.Volatile segment for the Excel Workbook i am working on. Will be similar but not the same.
Here is the current design, not much but what i am workgin with atm.
Function DistinctValues(rng As Range)
Application.Volatile True
If rng.Columns.Count > 1 Then
Err.Raise -1542376, rng.Worksheet.name, "An invalid function call was made!"
End If
End Function
Application.Caller returns the cell that called a function. See this MSDN definition.