VBA Excel 2016 - Run-time error '1004' - vba

I am trying to write code to copy and paste data from one sheet to the master sheet in the same workbook based on 5 drop down lists (using data validation) on the master sheet and have written this code for it as below, however every time I get the run time 1004 error and don't know how to solve it, is there a way to fix this?
Private Sub GO_Click()
Worksheets("Dashboard").Select
If Worksheets("Dashboard").Range(B3) = "National Gallery" And
Worksheets("Dashboard").Range(B4) = "unframed" And
Worksheets("Dashboard").Range(B7) = "Product Costings" And
Worksheets("Dashboard").Range(B5) = "N/A" And
Worksheets("Dashboard").Range(B6) = "N/A" Then
Worksheets("(7b)").Activate
Worksheets("(7b)").Range(A8, F23).Copy_
Destination = Worksheets("Dashboard").Range(D11)
Else: MsgBox ("No Data")
End If
End Sub

after copy the line put this :
Worksheets("Dashboard").activate
range("D11").pasteSpecial xlpastevalues 'or just paste depends on your need
don't forget to put " inside range("x")
hope it works

Jean-Pierre Oosthuizen is correct. adding commas to your ranges will fix the 1004 issue for you. The below code should now work for you.
Private Sub GO_Click()
Worksheets("Dashboard").Activate
If Worksheets("Dashboard").Range("B3") = "National Gallery" And _
Worksheets("Dashboard").Range("B4") = "unframed" And _
Worksheets("Dashboard").Range("B7") = "Product Costings" And _
Worksheets("Dashboard").Range("B5") = "N/A" And _
Worksheets("Dashboard").Range("B6") = "N/A" Then
Worksheets("(7b)").Activate
Worksheets("(7b)").Range("A8", "F232").Copy_
Destination = Worksheets("Dashboard").Range("D11")
Else: MsgBox ("No Data")
End If
End Sub

Unless B3, B4, etc are global variables, you're asking for .Range(null) which isn't valid. As #Jean-PierreOosthuizen said, you want .Range("B3").
Also unless you have a WorkSheet named "(7b)" (with the parens "()" included), your reference to Worksheets("(7b)") will fail next.
Bonus code review:
Please work on proper indentation - it makes your code much more readable! Future you (like you a week from now) will thank present you for doing so. Rubberduck VBA* will do that for you as well as pointing out lots of other things that will make your code better, like:
Eliminate Worksheets("Dashboard").Select - You're doing an excellent job of explicitly specifying all your worksheet references, so you don't need to .Select one.
Eliminate Worksheets("(7b)").Activate - Same as above
Eliminate the multiline Else: MsgBox ("No Data") and replace it with two lines of code - it's much more readable.
*I'm not yet a contributor to the Rubberduck project, but I'm a happy user and have learned quite a bit about better coding from them

Related

Validating Cell Input Based on Another Cell

When I input some text in a cell, for example in cell B2-test, I want in cell A6 the input to begin with this string and to end with _VAR1-for example test_VAR1.
I have found a simple solution as formula - =IF(A2="test","test_VAR1") but I want to make it as a VBA code.
So any idea how this can be done?
This is the most minimal example that I can come up with.
The LCase(Range("B2")) would also take "Test" and "TeSt" into account:
Option Explicit
Public Sub TestMe()
With ActiveSheet
If LCase(.Range("B2")) = "test" Then
.Range("A6") = .Range("B2") & "_VAR1"
End If
End With
End Sub
And if you want to check every event of the worksheet, put your code in the corresponding worksheet (Sheet1, Sheet2 and Sheet3 on the picture below):
Option Explicit
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
If Target.Cells.Count > 1 Then Exit Sub
If Intersect(Target, Me.Range("B2")) Is Nothing Then Exit Sub
Application.EnableEvents = False
If LCase(Target) = "test" Then
Me.Range("A6") = Target & "_VAR1"
End If
Application.EnableEvents = True
End Sub
I know you said in your question you wanted macro, but I'm not going to post my own (because I feel like #Vityata's answer should be sufficient)
However, I got impression from your post, that you could adjust / improve your formula instead and avoid macro altogether. It's usually better to avoid macro, when possible, for compatibility reasons (a lot of users have macros disabled by default)
If you simply want to add the keyword "_VAR1" to the input, use the following formula instead
=LTRIM(B2) & "_VAR1"
If the input can be anything, that contains the word "test"
=IF(ISNUMBER(SEARCH("test", TRIM(LOWER(B2)))), LTRIM(B2) & "_VAR1", "Incorrect Input")
The text contains only the word "test" and nothing else
=IF(TRIM(LOWER(B2))="test", LTRIM(B2) & "_VAR1", "Incorrect input"
There are some other variations / tricks you could do with this, but these are some of the most basic examples you can use as your "building blocks"

VBA code crashes after saving - says the situation lies with the XML "Run-time error '429'

I made a worksheet for the company I work for to help with pricing out custom designs. A few months ago I made a macro that can save the parts to a text file that can be pulled from at a later date if we wanted to quote out the same design. Everything was working perfectly, until one day I go to open it up and got the error message
We found a problem with some content in 'File.xlsm'. Do you want us to try
to recover as much as we can?
When I click yes, it then comes up with the worksheet the macro was on completely un-formatted and says it could only open the file by repairing or removing the following part
Repaired Part: /xl/worksheets/sheet3.xml part.
This is weird because the only xml code I use is just to create a drop-down menu when the saved design names are loaded. Nothing has changed since the final revision of the code other than the amount of designs that have been saved. The boxes I had as buttons tied to macros have been deleted and none of the code for this sheet works. What it shows when I view the code now is Sheet_Thumbnails
All other macros work, the other sheets are fully functional. When I try and run the code on this sheet I get
Run-time error '429':
ActiveX component can't create object
This has to be when compiling because I can't even debug where this is happening. The best answer I get when I look this error up is that I am not using the "New" keyword when calling a file or object from somewhere else. But I have looked through my code and don't see anywhere that applies. Luckily a co-worker saved a copy off our server to her computer so I have a backup, but when I open this and run the macros then save and re-open, the same crash happens.
Here is the code with xml:
Sub MakeList(ByRef r As Range, ByRef Config As String)
r.Clear
If Not Config = "" Then
r.Select
With Selection.Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Formula1:=Config
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With
End If
End Sub
Can anyone help me? I am at a total loss for why this has happened and why it keeps happening. Is it the validation part? Why would it happen after working for months?
Thank you in advance.
EDIT 1
Exporting all of the code and creating a new workbook did not solve the problem.
Thanks to Profex, the problem has been found and is in the validation. Essentially one of my lists was too long. The formula used in validation is not supposed to be beyond 255 characters. Even though Excel doesn't give any warning on this, when I would create the drop down menus, although it would populate each item from the list, after saving closing and re-opening, apparently this would corrupt the coded sheet. So now the question lies with how to add values into a drop-down menu without clearing and re-initializing with a longer list. Should I post a new question for that?
In Excel, Cell Validation Lists have a 8191 character limit (which is way too long for a user to pick from anyway).
Anything over 254 characters will corrupt the file upon save/re-open.
Here is something similar to what I have done in the past to create Dynamic Validations lists:
It uses your MakeList() subroutine, and requires another GetList() function to get the validation list for the specified cell.
Since this code is in the Workbook module, I also added another function called IsSheetTheOneICareAboutWithValidations(). If you use the WorksSheet_SelectionChange Event from in a specific sheet module, this isn't required; but you would have to change the scope of m_ValidationCell and m_ValidationList to be Public.
This code is untested and goes in the ThisWorkbook module:
Option Explicit
Private m_ValidationCell As Excel.Range
Private m_ValidationList As String
Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
If Not m_ValidationCell Is Nothing Then
m_ValidationList = m_ValidationCell.Validation.Value
m_ValidationCell.Validation.Delete
End If
End Sub
Private Sub Workbook_AfterSave(ByVal Success As Boolean)
If m_ValidationList <> vbNullString Then
With m_ValidationCell.Validation
.Add Type:=xlValidateList, Formula1:=ValidationList
End With
m_ValidationList = vbNullString
End If
End Sub
Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
If Not m_ValidationCell Is Nothing Then
m_ValidationCell.Validation.Delete
Set m_ValidationCell = Nothing
End If
If IsSheetTheOneICareAboutWithValidations(Sh) Then
' Since we're changing the Validation each time there is a new Selection;
' It's the Active Cell that matters, not the Target range
' Add a validation list to any cell in column 4, after the header (in row 1).
If ActiveCell.Column = 4 And ActiveCell.Row > 1 Then
List = GetList(ActiveCell)
MakeList ActiveCell, List
' Should probably add this next line to you MakeList() function
Set m_ValidationCell = ActiveCell
End If
End If
End Sub
Private Function GetList(Target As Range) As String
GetList = vbNullString ' or whatever you want
End Function
Private Function IsSheetTheOneICareAboutWithValidations(Sh As Object) As Boolean
IsSheetTheOneICareAboutWithValidations = (Sh.Name = "Pricing")
End Function
Recovery
It looks like you just had a bad save. Sometimes it just corrupts the file and there isn't much you can do, other then hope you have a backup.
Right Click in the Folder > Properties > Previous Versions
If you don't have a backup, it might just help to move everything to a new file.
Create a New Workbook
Select All cells from your first sheet (click above the 1, left of the A)
Press Ctrl+C to Copy
Select All cells in your New Workbook/Sheet
Press Ctrl+V to Paste
Repeat for all Worksheets
On the VB side of things, you can just Drag the Forms/Modules/Classes from the Old file to the New One.
Issue
Did you know that all New Office documents are really just ZIP files...
Go ahead, rename the file to File.xlsm.zip
Inside the file you'll see a folder structure which should have .../xl/worksheets/sheet3.xml
This is what excel is complaining about! That file is either missing or wrong.
Code
I don't know how you're calling Makelist, so I can't verify that the range R that you are passing is valid.
Please remove the Select/Selection from your code. You don't need to select anything in the front end GUI of Excel to access/change the cells. Also you didn't check if R was Nothing.
Sub MakeList(ByRef r As Range, ByRef Config As String)
If Not r Is Nothing then
r.Clear
If Not Config = "" Then
With r.Validation
...
End With
End If
End If
End Sub

Excel File Open Macro

So I'm trying to create a Macro That will update a cell when the file is opened. I'm getting the 424 Error and so I tried to do a better job defining my code/object but It still wasn't succesfull. I think I'm missing/overlooking something really easy but I can't figure it out and this is my first project so I'm trying to learn and gain a better understanding then just googling a segment of code that will work.
Private Sub Auto_Open()
Dim Try1 As String
Try1 = ActivateSheet.Cells(3, 2).Select
Tryl = "-"
' My first attempt is shown below
'
'Sheets("Current Calc").Activate
'ActivateSheet.Cells(3, 2).Value = "-"
End Sub
You've got a typo in your commented code
What you have...
Sheets("Current Calc").Activate
ActivateSheet.Cells(3, 2).Value = "-"
What it should be...
Sheets("Current Calc").Activate
ActiveSheet.Cells(3, 2).Value = "-"
Also, I should mention you should avoid using .Activate and .Select unless necessary. With that being said, I'd suggest the below code instead...
Sheets("Current Calc").Cells(3, 2).Value = "-"
EDIT:
When using Auto_Open, Excel must be opened MANUALLY in order for the code to execute; thus if it is opened via VBA this event will NOT trigger. If you want an event to trigger via VBA as well as manually, I'd suggest using Workbook_Open
Try with the following sub:
Private Sub Workbook_Open()
Dim Try1 As String
Try1 = ActiveSheet.Cells(3, 2).Select
Tryl = "-"
End Sub
Some advices:
write your code in lowercase. When you change a line, your code will change to upper and lower case automatically, this way you will detect if you have some typo error.
write a function or object ant type . This will open a dropdown list, this way you will also avoid typo error.

VBA-get values with known cell address

I am trying to achive the values of a row holding specific text. Say Liquidity Coverage Ratio is the text that is available in B57. I need the value of C57 and D57. I have achieved until retreiving the address of the cell holding text.
Kindly help me progressing further.
If fCheckSheet(forecastWorkbook, "Calculator (FX net)") Then
wsForecast.Activate
Else
ErrorStatus = "Source Sheet:Calculator (FX net) not found"
msgBoxReturn = MsgBox(ErrorStatus & forecastWorkbook.FullName, vbExclamation + vbOKCancel)
End If
Set rngRatio = FindRangeOfText(wsForecast, "Liquidity Coverage Ratio")
'Gets the address of cell having
RatioAddress = rngRatio.Address
'The address is $B$57
'???? how to retreive values for $c$57 and $D$57
I really appreciate the response from stackoverflow users who made me grow from novice until this level. Thanks for your patience.
Regards,
Mani
Assuming that the functions you refer to (but did not provide the code to support) will return Range type object (or Nothing), then you can simply use the Offset method:
If Not rngRatio Is Nothing Then
With rngRatio
Debug.Print .Offset(0,1).Address, .Offset(0,1).Value '$C$57
Debug.Print .Offset(0,2).Address, .Offset(0,2).Value '$D$57
End With
End If
There is also a lesser-known way to do the same thing:
If Not rngRatio Is Nothing Then
With rngRatio
Debug.Print .Cells(1, 2).Value
Debug.Print .Cells(1, 3).Value
End With
End With
My preference is for the first method, because it is explicit rather than implicit. This method is less clear, because not everyone knows intuitively that you can reference a cell outside of a range object, using the Cells property, such as:
MsgBox Range("A1").Cells(1, 4).Address ' --> $E$1
MsgBox Range("A1").Cells(4, 2).Address ' --> $B$4

VBA compiler not breaking / trapping on errors and no error message, when using UDF in conditional formatting

See new development.
I have a strange problem in Excel. I've got a Worksheet_Change event that I'm using and I'm trying to debug it. I save the program and open it back up and all of a sudden the compiler is not breaking on an error. In fact, it's not breaking at all!! I'll put a break at the head of the sub (and the next three lines for good measure) and it just does not happen. I thought maybe the events weren't enabled... So, I've put a message box as one of the first lines of code. The message box pops up.... even with the break on it's line.
This happened once before on a particular line of another macro and I tried copying everything into a .txt file and pasting it back into an earlier version of my program. This worked for months, but the problem now came back.
The coding isn't really important but I'll paste it below for kicks and giggles. It's aborting without an error wether I remove all the "on error"'s or not. I've cut and pasted the code into a new sub and it works fine. I've also checked the options and checked "break on all errors." nothing, even an undefined call won't throw an error, will stop the program from aborting.
Private Sub Worksheet_Change(ByVal target As Range)
Application.EnableEvents = False
Dim aVar() As String
Dim iVar As Integer
On Error GoTo 0
MsgBox "you changed something" 'this is a msgbox that does pop up during execution, verifying that the sub did in fact, run.
Call iRandomNonsense 'this is a sub that does not exist which the compiler does not tell me about any more.
If target.Columns.Count = 1 Then
Select Case target.Column
Case 2
If target.Count = 1 And Cells(target.Row, 1) = "" Then _
Cells(target.Row, 1) = Now
Case 8
On Error GoTo ExitSub
aVar = Split(target.Value)
For Each sVar In aVar
If IsNumeric(sVar) And Len(sVar) = 5 Then
If sVar > 30000 Then
aVar(iVar) = "ALN-" & sVar
Else
aVar(iVar) = "DEV-" & sVar
End If
End If
iVar = iVar + 1
Next
target.Value = Join(aVar, " ")
End Select
Else
On Error GoTo ExitSub
target.Resize(target.Rows.Count, Cells(target.Row, target.Columns.Count).End(xlToLeft).Column + 1 - target.Column).Select
Select Case Selection.Columns.Count
Case 18, 21 'Paste from Scrap report
Debug.Print "Paste from Scrap report" & Now
Call purgeCheckboxes
With Selection
.Copy
.PasteSpecial (xlValues)
End With
OnSelRow(4, 8).Select
Selection.Copy Destination:=OnSelRow(1)
'desc
OnSelRow(6) = OnSelRow(10)
OnSelRow(4) = OnSelRow(15)
With Range(Cells(Selection.Row, 10), Cells(Selection.Row + Selection.Rows.Count - 1, 10))
.FormulaR1C1 = _
"=RC[2]&"" ""&RC[3]&"" ""&RC[-3]&"" ""&RC[4]&"" ""&RC[7]&"" ""&RC[11]"
.Copy
.PasteSpecial (xlValues)
End With
Application.CutCopyMode = False
Range(Cells(Selection.Row, 7), Cells(Selection.Row + Selection.Rows.Count - 1, 7)).FormulaR1C1 = "TRUE"
Range(Cells(Selection.Row, 8), Cells(Selection.Row + Selection.Rows.Count - 1, 8)).FormulaR1C1 = "T D Q 9 A Wav DMR"
Range(Cells(Selection.Row, 9), Cells(Selection.Row + Selection.Rows.Count - 1, 9)).FormulaR1C1 = "2"
Range(Cells(Selection.Row, 11), Cells(Selection.Row + Selection.Rows.Count - 1, 11)).Select
Range(Selection, Cells(Selection.Row, UsedRange.Columns.Count)).Select
Selection.ClearContents
ActiveWindow.ScrollColumn = 1
End Select
Call RefreshCondFormats
End If
ExitSub:
On Error GoTo 0
Application.EnableEvents = True
End Sub
A new development:
I followed the advice in one of the comments. "Long shot: do you have any conditional formatting that uses UDFs? – Rory yesterday" It resolved the breaking error when I deleted the User Formula in my conditional formatting. Now the compiler stops like its supposed to and when I comment out "iRandomNonsense" it breaks on my command. When I put the formatting back it screws up again.
Rory, put your comment down as an answer (with a little more description as to how you figured this out) and I'll check it off to you.
If anyone's willing, I'd really like to know a way around this glitch in excel. It seems like a utility I might use in the future, and it really bothers me I can't use a user function in a conditional format. Also, this code has been very useful to me and I don't see any other way to do what I've done without either a user formula in conditional formatting, or a hairy autocorrect code.
If you are using UDFs in conditional formatting, this kind of problem can occur. It is most likely if you don't have error handling, or if you try and access any properties other than .Value or .Formula. It is often possible to work around the issue - e.g. using an alternative calculation, or putting the UDF in a cell - but occasionally you may just be out of luck.
I suggest using Rob Bovey's Code Cleaner to get rid of the accumulated p-code that can cause errors like this. When Excel VBA starts behaving strangely cleaning the code often fixes the problem.
http://www.appspro.com/Utilities/CodeCleaner.htm