VBA Debugging: Step Into leads to Entire Program Running - vba

I'm having an issue where, when looking at my VBA code, I'll press F8 to "Step Into" the next line. After about 8 steps, when I "Step Into" the line: Set wb = Workbooks.Open(fileopen), it takes off and runs the entire program. What am I doing wrong?
Sub NSC_test()
'
' NSC_test Macro
'
' Keyboard Shortcut: Ctrl+u
'
Const filepath As String = "H:\DEPT\Supply Management\Shared\No Standard Cost Reports\No Standard Cost Reports FYE 15\"
Dim filename As String
Dim fileopen As String
Dim lastrow As Integer
Dim tempcell As Range
Dim ws As Worksheet
If ActiveWorkbook.Name = "NSC Template.xlsm" Then
'DATE OF PREVIOUS WEEK'S REPORT
filename = Format(DateAdd("d", -1, Now()), "mm-dd-yy") 'SET THIS BACK TO -7
filename = "NSC " & filename & ".xlsm"
fileopen = filepath & filename
'MsgBox fileopen 'TO CHECK IF THE FILEPATH IS CORRECT
Dim wb As Workbook
Set wb = Workbooks.Open(fileopen)
If wb Is Nothing Then MsgBox "File does not exist": Exit Sub
blah
blah
Thanks very much.

The code line,
filename = "NSC " & filename & ".xlsm"
... indicates to me that you are opening an macro-enabled workbook. This workbook will have event macros and/or sub procedures that are initiated on opening. This releases the debug session and the remaining code runs its course.

Related

Run-time error '9': Subscript out of range when saving running save file macro

When I run the macro I get the run time error and upon debugging it highlights the following code:
ThisWorkbook.Sheets("Template Summary Screen").Copy After:=wb.Sheets(2)
What do you think is going on?
Sub saveasxlsx()
Dim wb As Workbook
Dim staticFolder As String
Dim dateformat As String
Dim wbfirst As Workbook
Set wbfirst = ThisWorkbook
wbfirst.RefreshAll
'location of the parent folder
staticFolder = "\\C:\Location\"
'provides previous month YYYYMM
dateformat = Format(DateAdd("M", -1, Date), "yyyymm", 1)
Set wb = Workbooks.Add
ThisWorkbook.Sheets("Template Summary Screen").Copy After:=wb.Sheets(2)
ThisWorkbook.Sheets("IPV").Copy After:=wb.Sheets(3)
ThisWorkbook.Sheets("ADJ").Copy After:=wb.Sheets(4)
ThisWorkbook.Sheets("Lists").Copy After:=wb.Sheets(5)
'save the new workbook in the folder
ActiveWorkbook.SaveAs staticFolder & "\" & dateformat & "\" & "Working files" & "\" & "GM AFS PE - UPLOAD VERSION" & " - " & dateformat & ".xlsx"
'close the workbook
ActiveWorkbook.Close
End Sub
Set wb = Workbooks.Add
This creates a new Workbook with one sheet, so wb.Sheets(1) is the only valid sheet, any other integer is out of range.
To add the sheets you need use wb.Sheets.Add()
Got it to work! For some reason my excel had defaulted to a single sheet for new workbooks - just changed that to 3 and it works fine

Save multiple sheets in a new workbook in a particular file format

I tried to read up a few related posts on the forum but wasnt able to make a code work or understand the syntax of a few functions.
I will try to describe what I want to be done in a crisp fashion:
I have a workbook with the multiple sheets (Sheet1, Sheet2 ... Sheet 5) and I want to create a macro assigned button to Save as a new work book containing only Sheet 1, Sheet 2 and Sheet3
The file format should be Microsoft Excel 97-2003 Worksheet (.xls)
On clicking the Macro assigned button the Save as dialogue box should pop up allowing the user to select destination and also optionally a new file name (pre assigned file name can be "textstring123"
After the workbook is saved the workbook should open for user to inspect while the old workbook is minimised
I am using Excel 2013, in case that is relevant.
The post may seem crude but I have no choice but to seek help from you as I have been breaking my head over this for the last day and a half and without this the rest of my macro project will become a waste. Thank you in advance for and suggestion/advice/ help.
If any other details or clarification is required please do ask.
I have added my lines of code that I have made but doesnt seem to work properly.
Sub Macro6()
'
' Macro6 Macro
' Save as
''
Dim varResult As Variant
Sheets(Array("sheet1", "sheet2", "sheet3")).Copy
varResult = Application.GetSaveAsFilename(FileFilter:= _
"Excel Files *.xls", FileFormat:=-57, Title:="Save File", _
InitialFileName:=ActiveWorkbook.Path \ Textstring123.xls)
If varResult <> False Then
ActiveWorkbook.SaveAs Filename:=varResult, _
FileFormat:=xlWorkbookNormal
Exit Sub
End If
End Sub
This will do the trick, I have an issue with the Filters so I added a bit of error handling!
Option Explicit
Sub Macro6()
'
' Macro6 Macro
' Save as
''
Dim tB As Excel.Workbook
Dim wB As Excel.Workbook
Dim ExportArray As Variant
Dim ShName As Variant
Dim ExportName As String
Dim varResult As Variant
Set tB = ThisWorkbook
ExportArray = Array("sheet1", "sheet2", "sheet3")
For Each ShName In ExportArray
Debug.Print ShName
tB.Sheets(ShName).Copy
Set wB = ActiveWorkbook
On Error Resume Next
ExportName = Application.GetSaveAsFilename(tB.Path & "\Textstring123", "Excel Files *.xls", , "Save " & ShName)
If Err.Number > 0 Then
ExportName = Application.GetSaveAsFilename(tB.Path & "\Textstring123", , , "Save " & ShName)
Else
'No error, everything went well with filters
End If
On Error GoTo 0
'String 8 and Boolean 11
If VarType(ExportName) <> 8 Then
Exit Sub
Else
wB.SaveAs Filename:=ExportName, FileFormat:=xlWorkbookNormal
End If
DoEvents
wB.Close
Next ShName
End Sub

GetActiveObject from The Excel Workbook

I have a Datepicker written in vb.net that looks like this.
I had to do it this way because of some Security Settings we have. Because of that, the Build in Datepicker from Excel generate sometimes an Error.
The Date Picker works fine if there Is Only One Excel Application Open. The Problem is when there are Multiple Excel Applications Open.
The code only takes the first Excel Application, but I want to get the Excel Workbook that's called "Test".
I Think the problem is this statement:
objExcel = System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application")
For a better understanding the Code from Excel and the DatePicker Application is below:
That's how I open the vb.net Application in Excel:
Set wsh = VBA.CreateObject("WScript.Shell")
arg = ActiveWorkbook.Path & ";" & ActiveWorkbook.Name & ";" & ActiveSheet.Name & ";" & Target.Address
' Wait for the shelled application to finish:
errorCode = wsh.Run(strPathDatePicker & " " & arg, windowStyle, waitOnReturn)
The code for the DatePciker is:
Public Sub frmDatePicker_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim Par() As String
Dim strTemp As String
Try
Dim arg = Environment.GetCommandLineArgs
strTemp = arg(1)
Par = Split(strTemp, ";")
'Split arg, to get the Information from the Excel Workbook
strWbPath = Par(0)
strWbName = Par(1)
strWsName = Par(2)
strAdresse = Par(3)
Catch ex As Exception
Me.Close()
End Try
End Sub
If you now click on a Date the vb.net Application will run this code for inserting the selected date into Excel:
Private Sub MonthCalendar1_DateSelected(sender As Object, e As DateRangeEventArgs) Handles MonthCalendar1.DateSelected
Dim objExcel As Excel.Application
Dim wb As Excel.Workbook
Dim ws As Excel.Worksheet
Try
'Get the Excel Object
objExcel = System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application")
For Each wb In objExcel.Workbooks
If wb.Name = strWbName Then
ws = wb.Sheets(strWsName)
ws.Range(strAdresse.ToString).Value = e.Start()
Me.Close()
End If
Next
Catch ex As Exception
MessageBox.Show(ex.Message)
Me.Close()
End Try
End Sub
The usual ways would probably be to pass the process Id, or Application.Hwnd, or even the risky ActiveWindow.Caption, but I think just the full external address is enough to find the Excel instance. For example in VB.Net (not tested):
Dim o As Object = GetObject("Book 1.xls")
Dim wb As Excel.Workbook = TryCast(o, Excel.Workbook)
Note that ; is valid character in file, workbook, worksheet, and named range names so I would recommend looking for a different separator. For example non-printable characters like Chr(0) might work, or just use the full external address Target.Address(,,,1).
Environment.GetCommandLineArgs(1) will cause problems if the argument contains spaces and is not surrounded by ": https://msdn.microsoft.com/en-us/library/system.environment.getcommandlineargs
Note: This is not the solution but I am posting it here to avoid long code in the comments (to improve readability). I will leave this answer here since the OP comment to this answer provides more information about his problem.
Maybe you should change:
arg = ActiveWorkbook.Path & ";" & ActiveWorkbook.Name & ";" & ActiveSheet.Name & ";" & Target.Address
to
arg = ThisWorkbook.Path & ";" & ThisWorkbook.Name & ";" & ActiveSheet.Name & ";" & Target.Address
At least you are referencing the workbook that's currently running the code and since you may have several workbooks open that could change the ActiveWorkbook as you are navigating between them.
HTH ;)

How do I name a spreadsheet automatically, by referencing two cells?

I've just finished writing a spiffy macro for automatically generating reports. It works well, but I need it to automatically name the spreadsheet according to the data in two cells.
Essentially, this macro creates a new spreadsheet, copies the information over to it, and creates the relevant pivot-tables which are required monthly.
As part of this I've created a dashboard for generating the report with instructions and a date range the report is to relate to. It currently creates the spreadsheet "NEW REPORT". Is there a way of creating the new spreadsheet and naming it something along the lines of "Report 01.01.15 to 01.02.15" automatically?
I've got the date range as two separate cells, and I'm aware I'll have to make sure the date range is one that will use allowed characters (I.E. 01.01.15 rather than 01/01/15) - am I right in saying there's a way of telling the user they've put the dates in with the incorrect separators?
Example
Option Explicit
Public Sub SaveAs()
Dim FilePath As String
FilePath = "D:\Temp"
Dim FileName As String
FileName = Sheets("Report").Range("A1").Text
ThisWorkbook.SaveAs FileName:=FilePath & "\" & FileName, _
FileFormat:=xlOpenXMLWorkbook, CreateBackup:=False
End Sub
To save it on today's date
Dim sSave As String
sSave = "Reports " & Format(Date, "dd-mm-yyyy")
Or tomorrow Date
"Reports" & Format(Date + 1, "dd-mm-yyyy")
For File Format See Examples
ThisWorkbook.SaveAs Filename:=FilePath, fileformat:=52
These are the main file formats in Excel 2007-2013
51 = xlOpenXMLWorkbook (without macro's in 2007-2013, xlsx)
52 = xlOpenXMLWorkbookMacroEnabled (with or without macro's in 2007-2013, xlsm)
50 = xlExcel12 (Excel Binary Workbook in 2007-2013 with or without macro's, xlsb)
56 = xlExcel8 (97-2003 format in Excel 2007-2013, xls)
*Or maybe you want to save the one worksheet workbook to csv, txt or prn.*
".csv": FileFormatNum = 6
".txt": FileFormatNum = -4158
".prn": FileFormatNum = 36
To Save only one Sheet as new Workbook then you need to copy the sheet before saving it
Option Explicit
Sub SaveAs()
Dim Sht As Worksheet
Dim FileName As String
Dim FilePath As String
FilePath = "C:\Temp"
FileName = Sheets("Sheet1").Range("A1").Text
Set Sht = ActiveWorkbook.Sheets("Sheet1")
Sht.Copy
ActiveWorkbook.SaveAs FileName:=FilePath & "\" & FileName
End Sub
To Save Multiple sheets as new Workbook then use Sheets(Array("Sheet1", "Sheet2")).Copy
Option Explicit
Sub SaveAs()
Dim Sht As Worksheet
Dim Book As Workbook
Dim FileName As String
Dim FilePath As String
FilePath = "C:\Temp"
FileName = Sheets("Sheet1").Range("A1").Text
Set Book = ActiveWorkbook
With Book
.Sheets(Array("Sheet1", "Sheet2")).Copy
End With
ActiveWorkbook.SaveAs FileName:=FilePath & "\" & FileName
End Sub

Copy data from another Workbook through VBA

I want to collect data from different files and insert it into a workbook doing something like this.
Do While THAT_DIFFERENT_FILE_SOMEWHERE_ON_MY_HDD.Cells(Rand, 1).Value <> "" And Rand < 65536
then 'I will search if the last row in my main worksheet is in this file...
End Loop
If the last row from my main worksheet is in the file, I'll quit the While Loop. If not, I'll copy everything. I'm having trouble finding the right algorithm for this.
My problem is that I don't know how to access different workbooks.
The best (and easiest) way to copy data from a workbook to another is to use the object model of Excel.
Option Explicit
Sub test()
Dim wb As Workbook, wb2 As Workbook
Dim ws As Worksheet
Dim vFile As Variant
'Set source workbook
Set wb = ActiveWorkbook
'Open the target workbook
vFile = Application.GetOpenFilename("Excel-files,*.xls", _
1, "Select One File To Open", , False)
'if the user didn't select a file, exit sub
If TypeName(vFile) = "Boolean" Then Exit Sub
Workbooks.Open vFile
'Set targetworkbook
Set wb2 = ActiveWorkbook
'For instance, copy data from a range in the first workbook to another range in the other workbook
wb2.Worksheets("Sheet2").Range("C3:D4").Value = wb.Worksheets("Sheet1").Range("A1:B2").Value
End Sub
You might like the function GetInfoFromClosedFile()
Edit: Since the above link does not seem to work anymore, I am adding alternate link 1 and alternate link 2 + code:
Private Function GetInfoFromClosedFile(ByVal wbPath As String, _
wbName As String, wsName As String, cellRef As String) As Variant
Dim arg As String
GetInfoFromClosedFile = ""
If Right(wbPath, 1) <> "" Then wbPath = wbPath & ""
If Dir(wbPath & "" & wbName) = "" Then Exit Function
arg = "'" & wbPath & "[" & wbName & "]" & _
wsName & "'!" & Range(cellRef).Address(True, True, xlR1C1)
On Error Resume Next
GetInfoFromClosedFile = ExecuteExcel4Macro(arg)
End Function
Are you looking for the syntax to open them:
Dim wkbk As Workbook
Set wkbk = Workbooks.Open("C:\MyDirectory\mysheet.xlsx")
Then, you can use wkbk.Sheets(1).Range("3:3") (or whatever you need)
There's very little reason not to open multiple workbooks in Excel. Key lines of code are:
Application.EnableEvents = False
Application.ScreenUpdating = False
...then you won't see anything whilst the code runs, and no code will run that is associated with the opening of the second workbook. Then there are...
Application.DisplayAlerts = False
Application.Calculation = xlManual
...so as to stop you getting pop-up messages associated with the content of the second file, and to avoid any slow re-calculations. Ensure you set back to True/xlAutomatic at end of your programming
If opening the second workbook is not going to cause performance issues, you may as well do it. In fact, having the second workbook open will make it very beneficial when attempting to debug your code if some of the secondary files do not conform to the expected format
Here is some expert guidance on using multiple Excel files that gives an overview of the different methods available for referencing data
An extension question would be how to cycle through multiple files contained in the same folder. You can use the Windows folder picker using:
With Application.FileDialog(msoFileDialogFolderPicker)
.Show
If .Selected.Items.Count = 1 the InputFolder = .SelectedItems(1)
End With
FName = VBA.Dir(InputFolder)
Do While FName <> ""
'''Do function here
FName = VBA.Dir()
Loop
Hopefully some of the above will be of use
I had the same question but applying the provided solutions changed the file to write in. Once I selected the new excel file, I was also writing in that file and not in my original file. My solution for this issue is below:
Sub GetData()
Dim excelapp As Application
Dim source As Workbook
Dim srcSH1 As Worksheet
Dim sh As Worksheet
Dim path As String
Dim nmr As Long
Dim i As Long
nmr = 20
Set excelapp = New Application
With Application.FileDialog(msoFileDialogOpen)
.AllowMultiSelect = False
.Filters.Add "Excel Files", "*.xlsx; *.xlsm; *.xls; *.xlsb", 1
.Show
path = .SelectedItems.Item(1)
End With
Set source = excelapp.Workbooks.Open(path)
Set srcSH1 = source.Worksheets("Sheet1")
Set sh = Sheets("Sheet1")
For i = 1 To nmr
sh.Cells(i, "A").Value = srcSH1.Cells(i, "A").Value
Next i
End Sub
With excelapp a new application will be called. The with block sets the path for the external file. Finally, I set the external Workbook with source and srcSH1 as a Worksheet within the external sheet.