I'm designing a PO that changes the cost per unit depending on the item selected in the Drop Down List.
I'm using...
Sub DropDown8_Change()
If (DropDown8.SelectedItem = "1") Then
Range("E21").Value = "54.90"
End If
End Sub
However I get the error,
Run-time error '424': Object required
If I remove the IF statement and have it simply change the contents of the Cell, It works.. So I'm assuming it is an issue with the Conditional Statement.
From my signifigant past with Visual Basic in Visual Studio, The name of the Control is included in the Method so I'm confused. I could be doing alot wrong here so bear with me :).
Thanks in advance
Working with Shapes on an Excel worksheet is kind of annoying. I usually stay away from them if I can.
Here's how you get the data you're looking for:
Sub DropDown8_Change()
Dim selectedItem As String
Dim ws As Excel.Worksheet
Set ws = Sheets(1)
Dim selectedIndex As Long
selectedIndex = ws.Shapes("Drop Down 8").ControlFormat.Value
selectedItem = ws.Shapes("Drop Down 8").ControlFormat.List(selectedIndex)
If (selectedItem = "1") Then
Range("E21").Value = "54.90"
End If
End Sub
The problem is that the method that's generated for you (in your case, DropDown8_Change()) doesn't really give you much to work with (like with Worksheet_Change(ByVal Target As Range)), and you have to deal with VBA Shapes (yuck).
You need to reference the Shape by it's actual name (unless you know the Shape's index, which isn't as easy to determine). The name can be found by right-clicking on the shape and then looking in the Range address textbox to the left of the formula bar. Then you have to go through this whole ControlFormat hoops to get what you're looking for.
Sorry for the rant. I hate VBA Shapes.
Related
I am a complete novice, this is my first VBA code (necessity is mother of . . . inept coding by novice).
Problem: Why is my code not updating in real-time? Or in any time at all? Can it be fixed? Do I need to somehow put all 16 sheets worth of VBA code into a "module" or do some other trick to fix it?
Background:
I have VBA code "behind" multiple "client" spreadsheets in a workbook. The code allows cell colors to transfer to a master "all clients" spreadsheet. The reason I needed the VBA code was that there was a function (and INDEX function) already in the color-filled cells.
The code was not working properly, so I figured out that the references were wrong and edited one of the sheets' VBA code to ensure I had the references right. They were correct. But even getting those edited references in that one sheet's code to work correctly took a bunch of clicking around and saving and reopening the document.
I then needed to fix the code in all the other sheets, starting with one of them. I can't for the life of me get anything to happen even though I made the correct edit. I should have seen colors change, but nothing happened.
Google search led me to the news that just putting code "behind" spreadsheets often doesn't work. One reference said I should place it in a module. But I have no idea how to do that across all of my 16 client sheets.
I'm also working over Remote Desktop which is probably not helping. I could probably send myself the workbook if needed.
Below is my code (one sheet's worth). The references are different across sheets so that the various client's data (in vertical columns) populates on the correct horizontal rows of the master sheet. Along with that data are the colors that this VBA code is supposed to help render onto the master sheet.
This is the "Glen" spreadsheet's VBA code, Glen's data that needs to be color coded identically on the "WeeklyRatingsAllClients" sheet (ending up in the BD6:CH6 range and BD7:CH7 range) is in the Q4:Q38 range and the U4:U38 range. The other sheets are the exact same except that in the next person's sheet the BD6:CH6 range and BD7:CH7 ranges will update to become BD8:CH8 range and BD9:CH9 and so on sequentially (next client is 10, 11; next is 12, 13 etc.).
If it matters to anyone, I got the original code here and modified it for my needs: https://www.extendoffice.com/documents/excel/4071-excel-link-cell-color-to-another-cell.html
Also, I make a long comment on above page under "Sara" dated 3 months ago that describes more about the code/purpose and shows how I modified the example code for my purpose and it worked--it's just not working now (probably not useful if you already know this stuff well, like I don't).
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim xRg As Range
Dim xCRg As Range
Dim xStrAddress As String
xStrAddress = "WeeklyRatingsAllClients!$BD$6:$CH$6"
Set xRg = Application.Range(xStrAddress)
Set xCRg = Me.Range("$Q$4:$Q$38")
On Error Resume Next
For xFNum = 1 To xRg.Count
xRg.Item(xFNum).Interior.Color = xCRg.Item(xFNum).Interior.Color
Next
xStrAddress = "WeeklyRatingsAllClients!$BD$7:$CH$7"
Set xRg = Application.Range(xStrAddress)
Set xCRg = Me.Range("$U$4:$U$38")
On Error Resume Next
For xFNum = 1 To xRg.Count
xRg.Item(xFNum).Interior.Color = xCRg.Item(xFNum).Interior.Color
Next
End Sub
Perhaps use the Workbook.SheetSelectionChange event, something like the following. Note that this can definitely be refactored.
Make sure to add this code in the ThisWorkbook module.
Change "Bob", "Fred", "Joe" to the sheet names in question (in order), and add more Cases as needed, always increasing the offsetNum by 2 from the previous Case.
There's a mismatch in the number of cells on the main sheet vs the client sheet. U4:U38 would be 35 cells, but BD6:CH6 is only 31... more an FYI.
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
Dim offsetNum As Long
Select Case Sh.Name
Case "Glen"
offsetNum = 0
Case "Bob"
offsetNum = 2
Case "Fred"
offsetNum = 4
Case "Joe"
offsetNum = 6
Case Else
Exit Sub
End Select
Dim allClientsSheet As Worksheet
Set allClientsSheet = Me.Worksheets("WeeklyRatingsAllClients")
Dim mainColorRange As Range
Set mainColorRange = allClientsSheet.Range("BD6:CH6").offset(offsetNum)
Dim sourceColorRange As Range
Set sourceColorRange = Sh.Range("Q4:Q38")
Dim i As Long
For i = 1 To mainColorRange.Rows(1).Cells.Count
mainColorRange.Rows(1).Cells(i).Interior.Color = sourceColorRange.Cells(i).Interior.Color
Next
Set sourceColorRange = Sh.Range("U4:U38")
For i = 1 To mainColorRange.Rows(2).Cells.Count
mainColorRange.Rows(2).Cells(i).Interior.Color = sourceColorRange.Cells(i).Interior.Color
Next
End Sub
tl;dr: Running a range.find function on a reference workbook doesn't seem to find text that's definitely there. Please critique my code.
My current goal is to have Textbox B of Userform automatically populated based on user input for Textbox A. I'm trying to make that work by automatically searching a reference workbook for the Textbox A (user input) string and returning a value from an offset cell.
I finally have the search running without vomiting an error at me, but it can't seem to find text that's clearly present. My code:
Function findSLINCalc(calc As String)
'Variables
Dim calcWkbk As Excel.Workbook
Dim slinCell As Excel.Range
Dim lCalc As Excel.Worksheet
Set calcWkbk = Excel.Workbooks("New COR Calculations.xlsx")
Set lCalc = calcWkbk.Sheets(1)
'Search the calculation spreadsheet for SLIN
If Not lCalc.Range("A1:A100").find(calc) Is Nothing Then
MsgBox "I found it!"
findSLINCalc = lCalc.Range("A1:A100").find(calc).Offset(1, 10).Value
Else
MsgBox "Nothing there!"
End If
End Function
Private Sub SLINTB_AfterUpdate()
findSLINCalc (Me.SLINTB.Value)
End Sub
I'm reasonably certain I'm calling the function incorrectly in my subroutine. Even so, running this code as is only gives me the "Nothing there!" message box. Surely it would give me the other one if it found something, right?
Other possibly pertinent info:
The reference workbook will vary in length but not format or file name/location.
The string I'm searching for will be part of a merged cell (columns A+B).
Thanks in advance!
I created a check box using the Developer Ribbon > Insert > ActiveX Controls > Check Box. I would like to code a sub which, when the box is checked, a range of values from the PCAPV10 worksheet is copied into a range on the BOM worksheet. I'm not sure if I am referencing my check box correctly in the code, and keep getting an object error. Any suggestions?
I've tried coding within the check box sub, and also referencing the check box from another sub. I can't seem to figure out either way to do this.
Private Sub CheckBox1_Click()
Dim PCAPV10 As Worksheet
Set PCAPV10 = Workbooks("CFC Calculation Program (Macro Enabled)").Sheets("Price Calculation APV10")
Dim BOM As Worksheet
Set BOM = Workbooks("CFC Calculation Program (Macro Enabled)").Sheets("BOM")
Dim chk1 As CheckBox
Set chk1 = Sheets("Price Calculation APV10").CheckBoxes("Check Box 1")
If Sheets("PCAPV10").OLEObjects("chk1").Object.Value = True Then
BOM.Range("A6:C120").Value = PCAPV10.Range("E11:I84").Value
End If
End Sub
I would like the code to recognize when the box is checked, and if true set the range within the BOM sheet equal to the range within the PCAPV10 sheet. If unchecked, do nothing. Instead, I am receiving the Run-time error '1004': Application-defined or Object-defined error.
No need to declare CheckBox1 As A Variable. You also put your variable PCAPV10 in Sheets(""). Try This:
If PCAPV10.OLEObjects("CheckBox1").Object.Value = True Then
BOM.Range("A6:C120").Value = PCAPV10.Range("E11:I84").Value
End If
If You Want To Define It, I'm Pretty Sure there isn't spaces:
Set chk1 = Sheets("Price Calculation APV10").CheckBoxes("CheckBox1")
You have already declared the check box and set the check box. Simply change the following:
If chk1.Value= 1 Then
This may not be the best practice, but I have always linked the check box to the cell it is in, so that cell toggles TRUE / FALSE.
Then I make the text match the fill color so it is not visible to the user.
Then in VBA I just use .range() or .cell() to match to that cell.
So I would use:
If Sheets("PCAPV10").range()
instead of what you have.
I'm stumped. I've read every thread regarding applying a RowSource to a ComboBox and just cannot get the solutions (which are mostly the same) to work.
The details are:
Excel 2010
UserForm = UFToTakeList
ComboBox = cbLvl2Selector
For which I want to have the RowSource as NRM1Lookup!NRM1GroupNoRange
I have typed: UFToTakeList.cbLvl2Selector.RowSource = NRM1Lookup!NRM1GroupNoRange to no success. I have added "" and '', I have tried other variations on the theme.
I can type the RowSource in the Properties box but I want to be able to concatenate another Range and know that I can apply this method to all my ComboBoxes.
I think my fundamental problem is knowing where to put the code. It automatically selects the _Change parameter for the ComboBox within the UserForm. If that is correct then I cannot workout why I can type the path above into the Properties box but it won't work as code.
Any guidance would be very much appreciated. My grey matter is frying.
From your explanation I could not understand what you want? You can try following codes, is it helpful to you or not?
Private Sub UserForm_Initialize()
Dim rng As Variant
rng = Sheets("Sheet1").Range("A1", Sheets("Sheet1").Range("A" & Rows.Count).End(xlUp))
If IsArray(rng) Then
ComboBox1.List = rng
Else
ComboBox1.AddItem rng
End If
End Sub
I have two spreadsheets... when one gets modified in a certain way I want to have a macro run that modifies the second in an appropriate manner. I've already isolated the event I need to act on (the modification of any cell in a particular column), I just can't seem to find any concrete information on accessing and modifying another spreadsheet (this spreadsheet is located on a different LAN share also... the user has access to both, though).
Any help would be great. References on how to do this or something similar are just as good as concrete code samples.
In Excel, you would likely just write code to open the other worksheet, modify it and then save the data.
See this tutorial for more info.
I'll have to edit my VBA later, so pretend this is pseudocode, but it should look something like:
Dim xl: Set xl = CreateObject("Excel.Application")
xl.Open "\\the\share\file.xls"
Dim ws: Set ws = xl.Worksheets(1)
ws.Cells(0,1).Value = "New Value"
ws.Save
xl.Quit constSilent
You can open a spreadsheet in a single line:
Workbooks.Open FileName:="\\the\share\file.xls"
and refer to it as the active workbook:
Range("A1").value = "New value"
After playing with this for a while, I found the Michael's pseudo-code was the closest, but here's how I did it:
Dim xl As Excel.Application
Set xl = CreateObject("Excel.Application")
xl.Workbooks.Open "\\owghome1\bennejm$\testing.xls"
xl.Sheets("Sheet1").Select
Then, manipulate the sheet... maybe like this:
xl.Cells(x, y).Value = "Some text"
When you're done, use these lines to finish up:
xl.Workbooks.Close
xl.Quit
If changes were made, the user will be prompted to save the file before it's closed. There might be a way to save automatically, but this way is actually better so I'm leaving it like it is.
Thanks for all the help!
Copy the following in your ThisWorkbook object to watch for specific changes. In this case when you increase a numeric value to another numeric value.
NB: you will have to replace Workbook-SheetChange and Workbook-SheetSelectionChange with an underscore. Ex: Workbook_SheetChange and Workbook_SheetSelectionChange the underscore gets escaped in Markdown code.
Option Explicit
Dim varPreviousValue As Variant ' required for IsThisMyChange() . This should be made more unique since it's in the global space.
Private Sub Workbook-SheetChange(ByVal Sh As Object, ByVal Target As Range)
' required for IsThisMyChange()
IsThisMyChange Sh, Target
End Sub
Private Sub Workbook-SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
' This implements and awful way of accessing the previous value via a global.
' not pretty but required for IsThisMyChange()
varPreviousValue = Target.Cells(1, 1).Value ' NB: This is used so that if a Merged set of cells if referenced only the first cell is used
End Sub
Private Sub IsThisMyChange(Sh As Object, Target As Range)
Dim isMyChange As Boolean
Dim dblValue As Double
Dim dblPreviousValue As Double
isMyChange = False
' Simple catch all. If either number cant be expressed as doubles, then exit.
On Error GoTo ErrorHandler
dblValue = CDbl(Target.Value)
dblPreviousValue = CDbl(varPreviousValue)
On Error GoTo 0 ' This turns off "On Error" statements in VBA.
If dblValue > dblPreviousValue Then
isMyChange = True
End If
If isMyChange Then
MsgBox ("You've increased the value of " & Target.Address)
End If
' end of normal execution
Exit Sub
ErrorHandler:
' Do nothing much.
Exit Sub
End Sub
If you are wishing to change another workbook based on this, i'd think about checking to see if the workbook is already open first... or even better design a solution that can batch up all your changes and do them at once. Continuously changing another spreadsheet based on you listening to this one could be painful.