VBA Open workbook and assign it to variable error - vba

I'm writing macro that goes through the file and marks lines that match some conditions as OK. Everything works fine when launched from the file. The problem is that when I try to launch it from another workbook I keep getting this error "Run time error 1004: Select method or Range class failed" at line
Range("C2").Select
I think that the problem lies in assigning opened file to the variable mainFile. (I can browse for the file, it opens and I can enter the year I want then it crashes)
Could you tell me what I'm doing wrong?
Sub sbVBA_To_Open_Workbook_FileDialog()
Dim strFileToOpen As Variant
Dim mainFile As Workbook
strFileToOpen = Application.GetOpenFilename("Excel Files (*.xls*), *.xls*", MultiSelect:=False)
If TypeName(strFileToOpen) = "String" Then
Set mainFile = Workbooks.Open(strFileToOpen)
Else
MsgBox "No file selected."
Exit Sub
End If
'sub data works fine
Call data
With mainFile
'Everything below works fine when launched in the mainfile
Dim myYear As Date
myYear = InputBox("Choose year", "Choose year", 2018)
Range("C2").Select
Do Until ActiveCell.Value = ""
If ActiveCell.Offset(0, 2) = "M" Then
If ActiveCell.Offset(1, 2) = "C" Then
If Day(ActiveCell.Value) = 1 Then
If Year(ActiveCell.Value) = myYear Then
If Month(ActiveCell.Value) & Year(ActiveCell.Value) = Month(ActiveCell.Offset(1, 0).Value) & Year(ActiveCell.Offset(1, 0).Value) Then
'^Comparing years and months
If DateSerial(Year(ActiveCell.Offset(1, 0).Value), Month(ActiveCell.Offset(1, 0).Value + 1), 0) = ActiveCell.Offset(1, 0).Value Then
' ^End of month?
ActiveCell.Offset(0, 10).Value = "OK"
Else
ActiveCell.Offset(0, 10).Value = "NOK"
End If
Else
ActiveCell.Offset(0, 10).Value = "NOK"
End If
Else
ActiveCell.Offset(0, 10).Value = "NOK"
End If
Else
ActiveCell.Offset(0, 10).Value = "NOK"
End If
Else
ActiveCell.Offset(0, 10).Value = "NOK"
End If
Else
ActiveCell.Offset(0, 10).Value = "NOK"
End If
ActiveCell.Offset(1, 0).Select
Loop
End With
End Sub

Just because you open a workbook, it won’t automatically assume it’s the active workbook.
Please try the following code after the “With mainFile” row:
mainFile.Sheets([your desired sheet]).Activate
Then, before the range.select part, add activesheet:
ActiveSheet.Range(“C2”).Select

Related

For loop VBA not populating cells correctly

I have some code that worked fine: it opens a file name from a list, finds if it contains a quote, and returns the status into the list, but I added a For loop and found it only works when set to about "1 to 10". Anything much bigger returns the wrong value in several instances. What step have I missed? (I had commented out extra parts which have been removed here.)
Sub BadCharactersFinder()
Application.ScreenUpdating = False
Dim foundDoubleQuote As Variant
Dim ClientID As String
Dim PDSfilename As String
Dim fname As String
ClientID = ActiveCell.Value
PDSfilename = ActiveCell.Offset(0, 1)
fname = "N:\DOWNLOAD\XYZfoldername\" & ClientID & "\original\" & XYZfilename
For i = 1 To 10
Set WBopener = Application.Workbooks.Open(fname)
Set foundDoubleQuote = ActiveSheet.Cells.Find("""", ActiveSheet.Cells(1, 1), xlValues, xlPart, xlByRows)
If (Not foundDoubleQuote Is Nothing) Then
ActiveWorkbook.Close savechanges:=False
ActiveCell.Offset(0, 15).Value = "Contains quotes"
Else
ActiveWorkbook.Close savechanges:=False
ActiveCell.Offset(0, 15).Value = "."
End If
Application.CutCopyMode = False
ActiveCell.Offset(1, 0).Select
Do Until ActiveCell.Height <> 0
ActiveCell.Offset(1, 0).Select
Loop
Next
End Sub

Statement to create excel vba hyperlink throws Run-time '1004' Error

So I have had a couple of questions I've asked regarding excel VBA, and I appreciate you all bearing with me as I stumble through learning about all this. Your answers have been a tremendous help and learning experience.
So far, I have a subroutine whose main responsibility is to write all of the values collected through a user form with various validations and dynamic comboboxes. My final task is to get this Subroutine to assign a hyperlink to the location selected by an earlier loop. But with my current syntax, I'm getting a "run-time error '1004' method '_default' of object 'range' failed". Some research proved that the cell coordinates require a .address property after them in order to avert this error, but it did not resolve the issue. The code is below:
Option Explicit
Dim cnt As Integer
Dim i As Long, rowOff As Long
Dim dateSel As String
Dim timeSel As String
Dim branch As String
Dim sht As Worksheet
Dim cel As Range
Dim matchingHeader As Range
Public Sub UserForm_Initialize()
'clear form
BranchBox.Value = ""
DateBox.Value = ""
TimeBox.Value = ""
'populate sheet names from each branch
For Each sht In ActiveWorkbook.Sheets
If sht.Name = "ApplicantInfo" Then
'Do Nothing
Else
Me.BranchBox.AddItem sht.Name
End If
Next sht
End Sub
Public Sub HoldButton_Click() 'revisit... throwing Time message box regardless what's selected
If TimeBox.Value <> "" Then
If DateBox.Value <> "" Then
If BranchBox.Value <> "" Then
sht.Cells(rowOff, i).Value = "-"
'Save workbook
Else
MsgBox "You must select a branch for your appointment"
End If
Else
MsgBox "You must select a date for your appointment"
End If
Else
MsgBox "You must select a time for your appointment"
End If
End Sub
Private Sub ResetButton_Click()
FirstName.Value = ""
LastName.Value = ""
EMail.Value = ""
Phone.Value = ""
Skills.Value = ""
'BranchBox.Value = "" throws error
DateBox.Value = ""
TimeBox.Value = ""
End Sub
Private Sub ScheduleButton_Click()
Dim row As Long, column As Long
Dim linkDisplay As String
'test for RowOff and i <> 0
If IsNull(BranchBox) = True Then
MsgBox "Select a branch for you interview before you click schedule"
Else
If IsNull(DateBox) = True Then
MsgBox "Select a date for you interview before you click schedule"
Else
If IsNull(TimeBox) = True Then
MsgBox "Select a time for you interview before you click schedule"
Else
'find first empty row in applicant profile tab.
'Insert applicant information in free row
'parse applicant name as a link to found free row above
'replace "-" placeholder for held appointment with applicant name as a link
Call GetFirstEmptyRow
'write selected values into row
Dim InfoRow As Integer
InfoRow = ActiveCell.row
ActiveCell.Value = ActiveCell.Offset(-5, 0).Value + 5
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = LastName.Value
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = FirstName.Value
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = EMail.Value
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = Phone.Value
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = Skills.Value
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = BranchBox.Value
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = DateBox.Value
ActiveCell.Offset(0, 1).Select
ActiveCell.Value = TimeBox.Value
branch = BranchBox.Value
Set sht = ActiveWorkbook.Worksheets(branch)
dateSel = DateBox.Value
timeSel = TimeBox.Value
'scan for selected date
For i = 2 To sht.Rows.Count
Set cel = sht.Cells(i, 1)
If cel.Value = dateSel Then
column = i
Exit For
End If
Next i
'Scan for selected time
For i = 2 To sht.Columns.Count
Set cel = sht.Cells(1, i)
If CStr(cel.Value) = timeSel Then
row = i
Exit For
End If
Next i
linkDisplay = LastName.Value & ", " & FirstName.Value
'This is the error
sht.Hyperlinks.Add Anchor:=sht.Cells(row, column).Address, Address:="", SubAddress:=ActiveWorkbook.Worksheets("ApplicantInfo").Cells(InfoRow, 1).Address, TextToDisplay:=linkDisplay
'end of validations
End If
End If
End If
End Sub
Public Sub GetFirstEmptyRow()
Set sht = ActiveWorkbook.Worksheets("ApplicantInfo")
sht.Activate
Range("A1").Select
Do
If IsEmpty(ActiveCell) = False Then
ActiveCell.Offset(1, 0).Select
End If
Loop Until IsEmpty(ActiveCell) = True
End Sub
Public Sub Save()
End Sub
Public Sub TimeBox_Change()
End Sub
Public Sub BranchBox_Change()
'clear Date Box Values
For i = DateBox.ListCount - 1 To 0 Step -1
DateBox.RemoveItem i
Next i
'clear Time Box Values
i = 0
For i = TimeBox.ListCount - 1 To 0 Step -1
TimeBox.RemoveItem i
Next i
'reset i to 0
i = 0
'populate dates
Me.DateBox.List = Worksheets(BranchBox.Value).Range("A2:A31").Value
End Sub
Public Sub DateBox_Change()
branch = BranchBox.Value
Set sht = ActiveWorkbook.Worksheets(branch)
dateSel = DateBox.Value
'Get Row to scan
For i = 2 To sht.Rows.Count
Set cel = sht.Cells(i, 1)
If cel.Value = dateSel Then
rowOff = i
Exit For
End If
Next i
'Scan selected row for blank cells
For i = 2 To sht.Columns.Count
Set cel = sht.Cells(rowOff, i)
If CStr(cel.Value) = "" Then
Set matchingHeader = sht.Cells(1, i)
TimeBox.AddItem matchingHeader.Text
End If
Next i
Me.TimeBox.AddItem ("No Appointments Available")
End Sub
This is the line which errors:
sht.Hyperlinks.Add Anchor:=sht.Cells(row, column).Address, _
Address:="", _
SubAddress:=ActiveWorkbook.Worksheets("ApplicantInfo") _
.Cells(InfoRow, 1).Address, _
TextToDisplay:=linkDisplay
Help is much appreciated! Thanks in advance!
sht.Hyperlinks.Add Anchor:=sht.Cells(row, column), _
Address:="", _
SubAddress:="'ApplicantInfo'!" & Cells(InfoRow, 1).Address(False, False), _
TextToDisplay:=linkDisplay
I'd typically use a utility method for this type of thing though.
E.g. something like:
Sub CreateHyperlink(FromCell As Range, ToCell As Range, Optional LinkText As String = "")
Dim subAddr, txt
subAddr = ToCell.Address(False, False)
If FromCell.Worksheet.Name <> ToCell.Worksheet.Name Then
subAddr = "'" & ToCell.Worksheet.Name & "'!" & subAddr
End If
txt = IIf(LinkText <> "", LinkText, FromCell.Value)
If Len(txt) = 0 Then txt = "Go"
With FromCell.Worksheet
.Hyperlinks.Add Anchor:=FromCell, Address:="", _
SubAddress:=subAddr, TextToDisplay:=txt
End With
End Sub

"My code is not working"

I am trying to run the below code. But it is showing the error of Subscript out of range. When I tried to debug it, it is showing error in the 5 line: Range(“A1”).Select
While debugging, when I made the Sheet1 of 4th line as Sheet2, then it is not going on Sheet2.
Please help me run the code properly.
Sub excelmacro()
Application.ScreenUpdating = False
Sheets(“Sheet1”).Select
Range(“A1”).Select
Sheets(“Sheet2”).Select
Range(“A2”).Select
For i = 1 To 3
Sheets(“Sheet1”).Select
If Len(ActiveCell.Value) > 1 Then
Sheets(“Sheet1”).Select
Xname = Right(ActiveCell.Value, Len(ActiveCell.Value) - 6)
Xdesig = Right(ActiveCell.Offset(1, 0).Value, Len(ActiveCell.Offset(1, 0).Value) - 13)
Xsalary = Right(ActiveCell.Offset(2, 0).Value, Len(ActiveCell.Offset(2, 0).Value) - 8)
Sheets(“Sheet2”).Select
ActiveCell.Value = Xname
ActiveCell.Offset(0, 1).Value = Xdesig
ActiveCell.Offset(0, 2).Value = Xsalary
ActiveCell.Offset(1, 0).Select
Sheets(“Sheet1”).Select
ActiveCell.Offset(3, 0).Select
Else
i = 10
End If
i = i - 1
Next
Application.ScreenUpdating = True
End Sub
The quotation marks are oddball and create an error, but even after changing to 'normal' quoates there is a Subscript out of range error:
Instead of using Sheets, try Worksheets:
Worksheets("Sheet1").Select
To summarize my comments:
The double-quotes in the original code are oddly formatted. Use Notepad or the VBA IDE to replace them with appropriate plain text double quotes.
Be sure to declare your variables before using them if Option Explicit is turned on. Also just a good practice to follow even if it were not on.
(To be updated when I have more time this evening) Avoid making selections and usingActiveCell/ActiveSheet references.
With minor changes to your code it should look like this:
Sub excelmacro()
Dim i As Double, _
Xname As String, _
Xdesig As String, _
Xsalary As String
Application.ScreenUpdating = False
Sheets("Sheet1").Select
Range("A1").Select
Sheets("Sheet2").Select
Range("A2").Select
For i = 1 To 3
Sheets("Sheet1").Select
If Len(ActiveCell.Value) > 1 Then
Sheets("Sheet1").Select
Xname = Right(ActiveCell.Value, Len(ActiveCell.Value) - 6)
Xdesig = Right(ActiveCell.Offset(1, 0).Value, Len(ActiveCell.Offset(1, 0).Value) - 13)
Xsalary = Right(ActiveCell.Offset(2, 0).Value, Len(ActiveCell.Offset(2, 0).Value) - 8)
Sheets("Sheet2").Select
ActiveCell.Value = Xname
ActiveCell.Offset(0, 1).Value = Xdesig
ActiveCell.Offset(0, 2).Value = Xsalary
ActiveCell.Offset(1, 0).Select
Sheets("Sheet1").Select
ActiveCell.Offset(3, 0).Select
Else
i = 10
End If
i = i - 1
Next
Application.ScreenUpdating = True
End Sub
I think this is what you're trying to do:
Sub excelmacro()
Dim lastrowinSheet1 As Long
Dim cellinSheet2 As Range
Dim rCell As Range
Dim x As Long
With ThisWorkbook
'Set a reference to cell A1 on Sheet2.
Set cellinSheet2 = .Worksheets("Sheet2").Range("A1")
With .Worksheets("Sheet1")
'This will return the last row number containing data in column A.
lastrowinSheet1 = .Cells(Rows.Count, 1).End(xlUp).Row
'Now loop through each cell in column A of sheet1.
For x = 1 To lastrowinSheet1
If Len(.Cells(x, 1)) > 1 Then
cellinSheet2.Value = Right(.Cells(x, 1).Value, Len(.Cells(x, 1).Value) - 6)
cellinSheet2.Offset(, 1) = Right(.Cells(x, 1).Offset(1).Value, Len(.Cells(x, 1).Offset(1).Value) - 13)
cellinSheet2.Offset(, 2) = Right(.Cells(x, 1).Offset(2).Value, Len(.Cells(x, 1).Offset(2).Value) - 8)
Set cellinSheet2 = cellinSheet2.Offset(1)
x = x + 2
End If
Next x
End With
End With
End Sub
I tried taking apart your code - I think this is what it's doing:
Sub excelmacro1()
'Stop the screen flicker.
Application.ScreenUpdating = False
'Select cell A1 on Sheet1.
Sheets(“Sheet1”).Select
Range(“A1”).Select
'Select cell A2 on sheet 2.
Sheets(“Sheet2”).Select
Range(“A2”).Select
For i = 1 To 3
'Select Sheet1 again.
Sheets(“Sheet1”).Select
'If the length of text in the ActiveCell is greater than 1 character then
'execute the lines up to ELSE.
If Len(ActiveCell.Value) > 1 Then
'Select Sheet1 yet again.
Sheets(“Sheet1”).Select
'Hope the value in the ActiveCell isn't longer than 6 digits, or it will error out.
'Take all characters from the ActiveCell except the last 6.
Xname = Right(ActiveCell.Value, Len(ActiveCell.Value) - 6)
'Take all characters from the ActiveCell except the last 13.
Xdesig = Right(ActiveCell.Offset(1, 0).Value, Len(ActiveCell.Offset(1, 0).Value) - 13)
'Take all characters from the ActiveCell except the last 8.
Xsalary = Right(ActiveCell.Offset(2, 0).Value, Len(ActiveCell.Offset(2, 0).Value) - 8)
'Select Sheet2.
Sheets(“Sheet2”).Select
'Place the values in ActiveCell and the two columns to the right.
ActiveCell.Value = Xname
ActiveCell.Offset(0, 1).Value = Xdesig
ActiveCell.Offset(0, 2).Value = Xsalary
'Select the next row down.
ActiveCell.Offset(1, 0).Select
'Active Sheet1 again.
Sheets(“Sheet1”).Select
'Select the cell 3 rows down from the previous row.
ActiveCell.Offset(3, 0).Select
Else
'If the lengh of text in the ActiveCell is 1 character or less then set the value of i to 10.
i = 10
End If
'Remove 1 from i.
i = i - 1
Next
Application.ScreenUpdating = True
End Sub

Msgbox() does not disappear on pressing O.K

I have this code where a msgbox pops up notifying a duplicate value.
Problem is the msgbox() does not go away on clicking ok and the code gets stuck.
Dim row As Integer
Dim counter As Integer
Range("c2").Activate
Application.ScreenUpdating = False
For counter = 0 To 688
If ActiveCell.Value = ActiveCell.Offset(1, 0).Value And ActiveCell.Offset(0, 2).Value = ActiveCell.Offset(1, 2).Value And ActiveCell.Offset(0, 3).Value = ActiveCell.Offset(1, 3).Value And ActiveCell.Offset(0, 9).Value = ActiveCell.Offset(1, 9).Value Then
MsgBox ("Found a duplicate")
Else ActiveCell.Offset(1, 0).Activate
End If
Next counter
The problem is that when the If is True the MsgBox is displayed and ActiveCell is never incremented. Therefore the MsgBox gets re-displayed 687 times!

GetData from multiple Workbooks in the same folder [correct function to add column with wbook name]

usually i never ask anything mostly because i always find some question similar to mine and the answers are, most of the cases, great, and i just need to adapt.
So, below this is the code i'm using, available on the internet and not created by me.
It is working nice but i would like/need to have, left or right column to the data extracted, the data origin workbook name, is that simple...my knowledge is very basic about vba, and even thinking this should have a easy answer i could not do it yet.
Public strFileName As String
Public currentWB As Workbook
Public dataWB As Workbook
Public strCopyRange As String
Sub GetDATA()
Dim strWhereToCopy As String, strStartCellColName As String
Dim strListSheet As String, strCopySheet As String
strListSheet = "List"
On Error GoTo ErrH
Sheets(strListSheet).Select
Range("B2").Select
'this is the main loop, we will open the files one by one and copy their data into the masterdata sheet
Set currentWB = ActiveWorkbook
Do While ActiveCell.Value <> ""
strFileName = ActiveCell.Offset(0, 1) & ActiveCell.Value
strCopyRange = ActiveCell.Offset(0, 2) & ":" & ActiveCell.Offset(0, 3)
strWhereToCopy = ActiveCell.Offset(0, 4).Value
strCopySheet = ActiveCell.Offset(0, 6).Value
strStartCellColName = Mid(ActiveCell.Offset(0, 5), 2, 1)
Application.Workbooks.Open strFileName, UpdateLinks:=False, ReadOnly:=True
Set dataWB = ActiveWorkbook
Sheets(strCopySheet).Select
Range(strCopyRange).Select
Selection.Copy
currentWB.Activate
Sheets(strWhereToCopy).Select
lastRow = LastRowInOneColumn(strStartCellColName)
Cells(lastRow + 1, 1).Select
Selection.PasteSpecial xlPasteValues, xlPasteSpecialOperationNone
Application.CutCopyMode = False
dataWB.Close False
Sheets(strListSheet).Select
ActiveCell.Offset(1, 0).Select
Loop
Exit Sub
ErrH:
MsgBox "It seems some file was missing. The data copy operation is not complete."
Exit Sub
End Sub
Public Function LastRowInOneColumn(col)
'Find the last used row in a Column: column A in this example
'http://www.rondebruin.nl/last.htm
Dim lastRow As Long
With ActiveSheet
lastRow = .Cells(.Rows.Count, col).End(xlUp).Row
End With
LastRowInOneColumn = lastRow
End Function
If I understand correctly, you want the source file name in Column A, while the data from that file starts in Column B? This should do that:
Sub GetDATA()
Dim strWhereToCopy As String, strStartCellColName As String
Dim strListSheet As String, strCopySheet As String
strListSheet = "List"
On Error GoTo ErrH
Sheets(strListSheet).Select
Range("B2").Select
'this is the main loop, we will open the files one by one and copy their
data into the masterdata sheet
Set currentWB = ActiveWorkbook
Do While ActiveCell.Value <> ""
strFileName = ActiveCell.Offset(0, 1) & ActiveCell.Value
strCopyRange = ActiveCell.Offset(0, 2) & ":" & ActiveCell.Offset(0,3)
strWhereToCopy = ActiveCell.Offset(0, 4).Value
strCopySheet = ActiveCell.Offset(0, 6).Value
strStartCellColName = Mid(ActiveCell.Offset(0, 5), 2, 1)
Application.Workbooks.Open strFileName, UpdateLinks:=False, ReadOnly:=True
Set dataWB = ActiveWorkbook
Sheets(strCopySheet).Select
Range(strCopyRange).Select
Selection.Copy
currentWB.Activate
Sheets(strWhereToCopy).Select
lastRow = LastRowInOneColumn(strStartCellColName)
'Paste data starting in column #2 (B)
Cells(lastRow + 1, 2).Select
Selection.PasteSpecial xlPasteValues, xlPasteSpecialOperationNone
Application.CutCopyMode = False
'Paste the filename in Column 1 (A) for all the rows just populated
Range(cells(LastRow + 1,1), cells(LastRowInOneColumn(strStartCellColName),1).value = strFileName
dataWB.Close False
Sheets(strListSheet).Select
ActiveCell.Offset(1, 0).Select
Loop
Exit Sub
ErrH:
MsgBox "It seems some file was missing. The data copy operation is not complete."
Exit Sub
End Sub
The key is the two lines I commented - Paste starting in column 2 instead of 1, then fill column 1 from the last known used row to the current last used row with the name of the file. I was a bit lazy in the example and pasted the full path, but there are plenty of examples on SE and all over Google on extracting just the file name from the path.
Also, I followed the pattern of using .Select, however if you modify the code to eliminate all the .Select and ActiveCell references, it will run much faster.
What I am thinking you want is for this procedure to append each copied row with the name of the source workbook. I modified your main procedure to do that:
Sub GetDATA()
Dim strWhereToCopy As String, strStartCellColName As String
Dim strListSheet As String, strCopySheet As String
strListSheet = "List"
On Error GoTo ErrH
Sheets(strListSheet).Select
Range("B2").Select
'this is the main loop, we will open the files one by one and copy their data into the masterdata sheet
Set currentWB = ActiveWorkbook
curLastCol = Cells.Find(what:="*", after:=Cells(1, 1), searchorder:=xlByColumns, searchdirection:=xlPrevious).Column 'gets right-most used column
Do While ActiveCell.Value <> ""
strFileName = ActiveCell.Offset(0, 1) & ActiveCell.Value
strCopyRange = ActiveCell.Offset(0, 2) & ":" & ActiveCell.Offset(0, 3)
strWhereToCopy = ActiveCell.Offset(0, 4).Value
strCopySheet = ActiveCell.Offset(0, 6).Value
strStartCellColName = Mid(ActiveCell.Offset(0, 5), 2, 1)
Application.Workbooks.Open strFileName, UpdateLinks:=False, ReadOnly:=True
Set dataWB = ActiveWorkbook
Sheets(strCopySheet).Select
Range(strCopyRange).Select
Selection.Copy
currentWB.Activate
Sheets(strWhereToCopy).Select
LastRow = LastRowInOneColumn(strStartCellColName)
Cells(LastRow + 1, 1).Select
Selection.PasteSpecial xlPasteValues, xlPasteSpecialOperationNone
Cells(LastRow + 1, curLastCol + 1).Value = dataWB.Caption 'puts source workbook name
Application.CutCopyMode = False
dataWB.Close False
Sheets(strListSheet).Select
ActiveCell.Offset(1, 0).Select
Loop
Exit Sub
Hope this helps!
Michael