Run Time error 1004: Select Method of Worksheet class failed with (varCellContent.Parent.Name) - vba

The code edits, then copies data from a temporary sheet to the current workbook. I am using varCellContent to ask the user to choose the source sheet. I had no trouble when testing the code as I was building it by using F8 to step through (and the code still works perfectly like this).
But when I run the macro normally, I am getting
Run Time error 1004: Select Method of Worksheet class failed
on the following line:
Workbooks(varCellContent.Parent.Name).Worksheets("Sheet1").Select
The following may not be relevant to the cause of the problem but I have read a bit about it while searching for an answer.
It sounds like using .Select is not a good idea, but there are 2 reasons I thought it was useful in this situation.
I don't have to name the sheet for each of the following rows of code that delete and move the columns.
When building and debugging the code I wanted the sheet to be visible so that I could see what was happening as I stepped through each line of code.
So taking those 2 reasons into account is there still a better way to avoid using .Select?
Sub ImportNewData()
'
'
' Import data, save as new workbook
Dim LR As Long
LR = Range("A" & Rows.Count).End(xlUp).Row
' Clear data
Range("A3:I" & LR).ClearContents
' User choose source sheet
Dim varCellContent As Worksheet
Set varCellContent = Application.InputBox _
(prompt:=" " & vbNewLine & "Click any cell in the Aged AP Summary that has been exported from Systematic to Excel, then click OK", Type:=8).Parent
Workbooks(varCellContent.Parent.Name).Worksheets("Sheet1").Select
'Delete unrequired columns
Columns("E:I").Select
Selection.Delete Shift:=xlToLeft

Worksheets("Sheet1").Activate
Columns("E:I").Delete Shift:=xlToLeft

Related

VBA Lookup in Another Workbook

I am having an vba problem with Excel. So I have this workbook, "Book Tool - Updated Feb. 2017.xlsb", that I am currently updating and will distribute to about 10 team members to use to keep track of their work. What I am trying to do is lookup data from an outside document, "Team Data", put that in Column DE of the "Book Tool - Updated Feb. 2017.xlsb" file. So I wrote the below code, where when the team member pushes a button, it opens up the lookup file, looks for the data in Column A of the "SICcode" sheet of that external file, matches it with Column B of the "Book Sheet" of the "Book Tool" file, and returns the value in Column D of the lookup file. It runs for the length of the "Book Sheet", closes the external file, and you get a popup that the data add is done.
Now when I did this code myself, it works great. Automatically opened the external document, did the lookups, returned the correct value, closes the external document, the pop up. So I sent the file with the macro to my manager to play around with before giving it to the rest of my team, but the macro does not work. When the macro runs, the external document opens, it seems like it is running through the lookups, closes the external file, and the pop up appears, but there is no value in the DE column, nor is there the lookup formula there. My manager didn't change the name of the Tool document, he didn't mess with any code. He emailed it back to me and with that copy the formula isn't working, but I checked it with my master copy formula and even though it's the same, the macro will not populate the data.
We have to keep the external data in a separate file, because otherwise the tool with the lookup data is over 2MB and takes forever to run or crashes.
Is there something about emailing the tool back and forth that messes with the file, or is there some formatting issue I need to look into that causes it not to work? With my master copy on my computer, the code always works regardless if I work in a virtual desktop, have it in a different folder, whatever.
I am just okay with vba, I don't know all of the technicalities of this process, so maybe I am overlooking some flaw with how I've set it up or limitations Excel has. Any guidance or help would be appreciated.
Sub AddData()
On Error Resume Next
'Open External Data Source
Workbooks.Open Filename:= _
"W:\USB\Reporting\Book Tool\Attachments\Team Data.xls"
'View sheet where data will go into
Windows("Book Tool - Updated Feb. 2017.xlsb").Activate
'Gets last row of Tool sheet
Sheets("Book").Select
lastrow = Cells(Rows.Count, "B").End(xlUp).Row
'Lookup in External File
Sheets("Book").Select
Range("DE2:DE" & lastrow).FormulaR1C1 = "=VLOOKUP(RC[-108],'[Team Data.xls]SICcode'!C[-109]:C[-104],5,FALSE)"
'Close External Data File
Windows("Team Data.xls").Activate
ThisWorkbook.Saved = True
Application.DisplayAlerts = False
ActiveWindow.Close
MsgBox "Data Add Done"
End Sub
Be sure to properly qualify your statements, and also it would be wise to assign the appropriate workbook to a variable. See the modified code below:
Sub AddData()
On Error Resume Next ' I also suggest removing this since it wont warn you on an error.
Dim wb as Workbook
Dim wbExternal as Workbook
Dim ws as Worksheet
Dim wsExternal as Worksheet
'Open External Data Source
Set wbExternal = Workbooks.Open Filename:= _
"W:\USB\Reporting\Book Tool\Attachments\Team Data.xls"
' Depending on the location of your file, you may run into issues with workbook.Open
' If this does become an issue, I tend to use Workbook.FollowHyperlink()
'View sheet where data will go into
' Windows("Book Tool - Updated Feb. 2017.xlsb").Activate
' Set wb = ActiveWorkbook
' As noted by Shai Rado, do this instead:
Se wb = Workbooks("Book Tool - Updated Feb. 2017.xlsb")
' Or if the workbook running the code is book tool
' Set wb = ThisWorkbook
'Gets last row of Tool sheet
Set ws = wb.Sheets("Book")
lastrow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row
'Lookup in External File
Set wsExternal = wbExternal.Sheets("Book")
wsExternal.Range("DE2:DE" & lastrow).FormulaR1C1 = "=VLOOKUP(RC[-108],'[Team Data.xls]SICcode'!C[-109]:C[-104],5,FALSE)"
'Close External Data File
ThisWorkbook.Saved = True
Application.DisplayAlerts = False
Windows("Team Data.xls").Close
MsgBox "Data Add Done"
End Sub
I would also recommend browsing through SO for tips on avoiding .Select and .Activate as this can make your code unreliable and in some cases can slow down your code significantly.
Lastly, if performance is a concern you may want to look into loading your lookup values into arrays and finding the corresponding values this way. It will completely depend on what kind of data you are working with. I had a workbook using filldown vlookups that went from running in a matter of 5-10 minutes or more to consistently running in less than 20 seconds by replacing VLOOKUPS with for looping arrays.

Copying Cells from Workbook to Workbook Results in "Subscript Out of Range"

Good day.
I am trying to write a code that will essentially select cells (left to right) from "A - M" and (downwards) up until the last used row.
Then, once selected, I was to copy them to another workbook.
This is the code that I tried to use:
ActiveWorkbook.Worksheets("Sheet1").Range("A1:M" & LastRow).Copy _
Workbooks("Converter.xlsm").Worksheets("Sheet1").Range("A1").CurrentRegion
Everything else in the code works except for this line.
And the result is this:
Run-time error '9':
Subscript out of range
Thanks.
PS. The "LastRow" Variable I used, I just pulled that out of a tutorial. That's not a personal user-defined variable, so I am not sure if that's actually from VBA's Documentation.
You mentioned you do not have a calculation for LastRow.
Always put Option Explicit at the top of your module. It forces you to declare your variables and will help you recognize if something you got from another coder is "built-in" or not.
See this post about determining the last row in a range.
From that post, you should have a calculation such as the following before your line of code ...
LastRow = Sheets("Sheet1").Range("A" & Sheets("Sheet1").Rows.Count).End(xlUp).Row
Please close all the workbooks and reopen and then try with below code
Sub test()
Dim lastrow As Long
lastrow = Range("A" & Rows.Count).End(xlUp).Row
ActiveWorkbook.Worksheets("Sheet1").Range("A1:M" & lastrow).Copy Workbooks("Converter.xlsm").Worksheets("Sheet1").Range("A1")
End Sub

Inserting, searching, copying, pasting across 2 spreadsheets in Excel

I thought I'd be able to figure this out based off an analysis of similar code we had written for something else, but code isn't my forte.
Diving into VBA without guidance has proved to be too daunting for me to proceed.
Forgive my terminology if I use the wrong language, I'm happy to learn and be corrected.
This shouldn't be difficult for someone that knows what they're doing, I just don't at all.
I'm trying to create a macro enabled workbook that does the following:
Open "Data.csv" from a folder called "Data" in the same directory as the macro. We'll call this workbook A - wbA.
Insert a column on wbA after Column C titled "Group Image Name." This Column D is where we want data to end up.
Open "Groups.csv" from a folder called "Groups" in the same directory as the macro. We'll call this workbook B - wkB.
(This next part needs to be a loop that starts at C1 on wbA and proceeds down the column until the end of the spreadsheet)
Copy value from selected cell in Column C on wbA
Search Column C on wbB for copied value. When found, move selection over to corresponding cell in Column A. (If C2, then A2)
Copy contents of the column A value from wbB to column D cell on wbA that corresponds to the original starting point on wbA.
Basically in plain language: Search for Column C contents from wbA on Column C of wbB. When found, move to Column A of same cell # on wbB, copy contents, and paste into cell # of Column D on wbA that corresponds to cell # of starting point from Column C.
I hope that's clear; please feel free to ask for more details if necessary. Thanks for anyone's help in advance!
Here is my terrible code I'm working with at the moment:
Sub OpenDataAddGroupImageTitleColumn()
ChDir "C:\[RealCodeHasCorrectFilepath..]\Desktop\TEST"
Workbooks.Open Filename:="C:\[RealCodeHasCorrectFilepath..]\Desktop\TEST\DATA.csv"
Columns("D:D").Select
Selection.Insert Shift:=xlToRight, CopyOrigin:=xlFormatFromLeftOrAbove
Cells.Select
Cells.EntireColumn.AutoFit
Range("D1").Select
ActiveCell.FormulaR1C1 = "Group Image Title"
Range("C2").Select
'Variables for storing Row, Column Location, and Value here
Dim GROUPNAME As String
Dim RowLocationX As Long
Dim ColumnLocationZ As Integer
GROUPNAME = ActiveCell.Value
RowLocationX = ActiveCell.Row
ColumnLocationZ = ActiveCell.Column
Workbooks.Open Filename:="C:\[RealCodeHasCorrectFilepath..]\Desktop\GROUPS.csv"
Columns("C:C").Select
Selection.Find(What:="GROUPNAME", After:=ActiveCell, LookIn:=xlFormulas, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
End Sub
The current snag I can't figure out after much googling is this: Is it possible to search for my variable GROUPNAME using the Find/Replace feature? Or should I be taking a different approach using something involving copying to clipboard?
The first problems that I see are:
1) You don't put functions in the middle of sub routines. If you want a function, you put it on its own as such:
Sub MySub()
'Do Stuff
x = myFunction()
debug.print x
End Sub
Function MyFunction() As String
'Do Stuff
MyFunction = "Test"
End Function
2) The code you have provided won't compile for reason 1 and also because you have ended the Sub with "End Function" instead of End Sub. Try running the code and you will get error messages. Then you can research the error message and try to fix it. Further, if you don't get error messages, you can step through the code to make sure it is working the way you intend it to.
3) The very first line isn't going to work. You need to use the ENTIRE path of the file, even if it is in the same folder as the file you currently have open. There are ways to get the directory of the file you currently have open (google will surely show you many of them), and you could just append the filename to the directory of the file you have open.
4) You want a loop, but you haven't put in any looping structions. Google "Excel VBA loop through cells" and you can find many examples to use.
5) I think the biggest issue that you are having is that you are overwhelmed because you are trying to do everything all at once. I would suggest solving one problem at a time and then putting the code together. For instance, you want to open two files. Start by writing code just to open one file. Then try to get a value out of the file into the open workbook. Then open another file. Then get data out of that file. Then test looping through cells in the current workbook and checking for desired criteria and pasting the results if they match. Then combine all of these things into coherent code.
Nobody writes efficient code the first time they try, so even if you end up with really long code that isn't efficient, you'll learn a lot and have something. Even experienced programmers can get stuck or write code that doesn't work the first or even tenth time. If you get stuck, ask a specific question about a specific error message or specific issue that you can't resolve.

VBA Import Data

I have a problem and I think it's complicated. It's regarding importing data/information from a another Excel file and the data/information needed is on 2 sheets.
The code is working but not the way It should be it doesn't seem to import the data and down below it will explain what we cannot do in it, ("me and my friend that are working in this project that was demand by our company don't know almost nothing about this category VBA and we are just researching info about this but get always stuck").
We need to extract from the file (the link is in the description), and the file is created every week(semana) so somehow it needs to extract the newest every week.
Down below there's the Excel file that is responsible for the extraction of the data for security reason we deleted most of the information on it and changed names.
Workbook with the Macro - Used for importing The sheet is the number 2 and also It's called Dev.Pag the macro is associated to the button "IMPORT DATA" in the same file.
Source Workbook - Contains the data This is where it gets the values(exports) from once again the name and some data was erased because It might compromise the company.
If there's anything I can edited or change please tell me. Thanks in advance for any reply.
Also will post the code down below:
Option Explicit
Sub ImportData()
Application.ScreenUpdating = False
Dim Path As String, Lstrw As Long
Dim SourceWb As Workbook
Dim TargetWb As Workbook
'Change this to your company workbook path
Path = "C:\Users\DZPH8SH\Desktop\Status 496 800 semana 12 2015.xls"
Workbooks.Open (Path)
'Change "Source" to the name of your company workbook
Set SourceWb = Workbooks("Status 496 800 semana 12 2015.xls")
'Part that needs some adjustments in down below
'This part is working good but probably some error in the data
'transferance may be intrefering with the integridty
'change the file address
Set TargetWb = Workbooks("Master_Atual_2015.xlsm")
Lstrw = SourceWb.Sheets(1).Cells.Find(What:="*", SearchOrder:=xlRows, _
SearchDirection:=xlPrevious, LookIn:=xlValues).Row
With SourceWb.Sheets(1)
.Application.Union(.Range("D2:D" & Lstrw), .Range("F2:F" & _
Lstrw), .Range("I2:I" & Lstrw), .Range("M2:M" & Lstrw)).Copy _
Destination:=TargetWb.Sheets(1).Range("A3")
End With
SourceWb.Close savechanges:=False
Application.ScreenUpdating = True
End Sub
It was pretty hard to understand your code for several reasons:
You just reference the sheets by index. Thus they are hard to find. Better reference them by name
you reference ranges only by addresses, it would be better to define named ranges
Another point to make it more readable/ debuggable, set the union to an own range object to be able to watch the content and be sure that this is what you want to have.
With SourceWb.Sheets(1)
Set objTargetRange = .Application.Union(.Range("D2:D" & Lstrw), .Range("F2:F" & Lstrw), .Range("I2:I" & Lstrw), .Range("M2:M" & Lstrw))
objTargetRange.Copy Destination:=TargetWb.Sheets(1).Range("A3")
End With
When printing out the objTargetRange's addresses it looks like this (You can do that by simply pressing ctrl+g and writing ?objTargetRange.Address)
$D$2:$D$9;$F$2:$F$9;$I$2:$I$9;$M$2:$M$9
So you selected four columns, each of them has 8 cells. When adding this to A3, it will be added side by side, it doesn't have any offset.
So cells A3-D10 will be overwritten by your data, the code works. It was not visible that it does that, because comparing state before and state after was pretty complicated. You can make visible, that the changes actually happen by just
temporary removing your actual data from the sheet
temporary adding some empty rows

Macro Produces Different Results If Clicking Screen While Running

I have two files (Microsoft Excel 97-2003 Worksheets) that contain multiple fields of data. A macro I have will open both files, copy the data (without headers) from one of them, and paste that data underneath the data in the other file. Once the data has been combined, I save the combined file as a new workbook. A somewhat stripped down version of the code I have is below (sorry it's inefficient; I had only just begun VBA when I wrote it):
Sub Combine()
' Combine Macro
' Turn some things off to speed things up
Application.ScreenUpdating = False
Application.StatusBar = False
Application.EnableEvents = False
' Set to directory where files to combine exist
ChDir "C:\Users\Me\Desktop\Macro Work"
' Variable Declarations
Dim EmptyRow As Long
Dim FileA, FileB As String
Dim Day as Integer
Day = 1
' Loop and combine the two files for each day of the month (if they exist)
Do Until (Day > 31)
' Get FileA and FileB names
FileA = "FileA" & Day & ".xls"
FileB = "FileB" & Day & ".xls"
' Open files A and B; handle error if file doesn't exist
On Error Resume Next
Workbooks.Open FileName:=FileA
If Err.Number = 1004 Then
GoTo NoFile
End If
Workbooks.Open FileName:=FileB
If Err.Number = 1004 Then
GoTo NoFile
End If
On Error GoTo 0
'Copy data from FileB and paste into FileA
EmptyRow = Workbooks(FileA).Worksheets(1).Cells(Rows.Count, 1).End(xlUp).Row + 1
Range(Range("A2"), Range("A2").End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy Workbooks(FileA).Worksheets(1).Range("A" & EmptyRow)
' Save combined workbook as FileName in Excel format
Workbooks(FileA).SaveAs FileName:="CombinedFile" & Day, FileFormat:=51
' Close the workbooks
Workbooks("CombinedFile" & Day).Close SaveChanges:=False
Workbooks(FileB).Close SaveChanges:=False
NoFile:
Day = Day + 1
Loop ' End of Loop
MsgBox "PAUSE - End of Macro"
End Sub
My problem isn't that that Macro won't run or throws an error. Rather if I run it and don't do anything else, I get one set of results. But if I run it and click on the VBA Editor Window while it's running, I get a different set of results.
Is it a known fact that you shouldn't do other things on your machine while your macro is running? Or have I neglected to add a piece of code that will keep the results of the macro consistent whether or not I sit and watch or am clicking the VBA Editor Window?
Thanks in advance, and let me know if I can provide further clarification.
Zachary
EDIT:
It's difficult to track down exactly what goes wrong with combining the files, but I can see that the number of lines differ. The combined file generated when I am clicking on the Editor Window has several thousand lines less than when I just watch it run. And I'll need to retract my earlier claim that I can consistently produce the same error. I can consistently reproduce an error, but the results may differ (i.e. maybe I'm missing only 4995 lines instead of 5000).
Liam, your response makes sense to me. However, I have a near identical Macro that skips this section:
'Copy data from FileB and paste into FileA
EmptyRow = Workbooks(FileA).Worksheets(1).Cells(Rows.Count, 1).End(xlUp).Row + 1
Range(Range("A2"), Range("A2").End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Selection.Copy Workbooks(FileA).Worksheets(1).Range("A" & EmptyRow)
Since sometimes the files I work with only have "FileA" I don't combine anything and instead use a Macro to open the file and SaveAs FileFormat=51 and with a new name. Obviously that removes sections in the code where I select data in the file. Yet I still receive different results when clicking. What might be causing this?
Lastly, in addition to removing sections of code where Selection is used, is there a way to help prevent the user from messing up the results of the macro in this way?
Thanks again.
its because you use:
Range(Range("A2"), Range("A2").End(xlDown)).Select
Range(Selection, Selection.End(xlToRight)).Select
Just because screenupdate is false, doesn't mean excel isn't executing your clicks. You can't reference a selection and expect it not to change if you select something else
Answers To Updated Question
You can easily remove the need to "select" cells by defining them in a range and referencing your new range. This will remove the possibility of users clicking and messing up the flow of your script
'Copy data from FileB and paste into FileA
Dim R1 as Range
Dim R2 as Range
EmptyRow = Workbooks(FileA).Worksheets(1).Cells(Rows.Count, 1).End(xlUp).Row + 1
Set R1 = Range(Range("A2"), Range("A2").End(xlDown))
Set R2 = Range(R1, R1.End(xlToRight))
R2.Copy Workbooks(FileA).Worksheets(1).Range("A" & EmptyRow)
This will do the same as your original code, without using select
One way to eliminate these problems is to reference the sheet in your calls (Sheets(1).Range(...)), and minimize selection (instead of .Select and then Selection., just put your Range.Copy or whatever you're doing). A little more code, but more robust.