Excel Dir returns unexpected null - vba

I'm trying to write what I thought would be a simple routine to take all the Excel sheets in a directory and copy them to tabs in a master sheet. Here's what I'm trying:
Sub GetSheets()
myPath = "C:\Users\Brian.Scott\Documents\2017_INVENTORY\TestInv"
Filename = Dir(myPath)
MsgBox (Filename)
Do While Filename <> ""
Workbooks.Open Filename:=myPath & Filename, ReadOnly:=True
For Each Sheet In ActiveWorkbook.Sheets
Sheet.Copy After:=ThisWorkbook.Sheets(1)
Next Sheet
Workbooks(Filename).Close
Filename = Dir()
Loop
End Sub
I put in the MsgBox when nothing was happening. It returns a null. myPath returns the correct name - which I copied and pasted from explorer to avoid spelling errors. I only have excel files in the directory, so I'm not error checking. This is a one-off need, but there are over 200 files in the directory, so I figured I could spend a little time on the code.
Any ideas will be greatly appreciated as I'm pretty green with this.

Declare all your variables - specify Option Explicit at the top of every module, and then declare every single variable you use until the code compiles again. Not doing that is only asking for trouble; VBA will happily compile and run a typo, and debugging that isn't fun at all. Use Option Explicit. Always.
Option Explicit
Public Sub GetSheets()
Const myPath As String = "C:\Users\Brian.Scott\Documents\2017_INVENTORY\"
Const myFilter As String = "TestInv*.xls?"
Dim myFilename As String
myFilename = Dir(myPath & myFilter)
Do While myFilename <> vbNullString
MsgBox myFilename
With Workbooks.Open(Filename:=myPath & myFilename, ReadOnly:=True)
Dim sh As Worksheet
For Each sh In .Worksheets
sh.Copy After:=ThisWorkbook.Sheets(1)
Next
.Close
End With
Filename = Dir
Loop
End Sub
Notice that With block - it's holding a reference to the Workbook object that the Workbooks.Open function returns, so you can do .Worksheets and .Close against it, without needing to code against ActiveWorkbook, and without needing to re-fetch that exact same object reference from the Workbooks collection at every iteration.
Your myPath contains a path, yes, but also wildcards, and I doubt this would work as expected:
Workbooks.Open "C:\Users\Brian.Scott\Documents\2017_INVENTORY\TestInv*.xls?\TestInv42.xlsx"
That's why I split the myPath string into a path and a filter: you supply the filter to the Dir function, and supply the Workbooks.Open function with the path with the file name that Dir returned.

Related

VBA - Subscript out of Range when Workbooks().Close

I would like to loop through all excel workbooks in a folder and write the string "Test" in Cell A1 of every sheet of every workbook.
The following code results in 'Subscript out of Range(Error 9)'.
When I ran the code line by line it turned out the Error is caused by the
line:
Workbooks(FName).Close Savechanges:=True Dir("C\...") stored in FName returns just the file name so the error can't be because of giving the full path name to Workboooks(...).Close which seems often to be the reason for the error.On top of that this code really opens the workbook instead of just writing into it. I don't want it
to open visually.
Sub multWB()
Dim FName As String
Dim wb As Workbook
Dim sht As Worksheet
Dim directory As String
directory = "C:\Users\...\Desktop\multipleWorkbooks\"
FName = Dir("C:\Users\...\Desktop\multipleWorkbooks\*.xls*")
Do While FName <> ""
Set wb = Workbooks.Open(directory & FName)
For Each sht In wb.Worksheets
sht.Cells(1, 1) = "Test"
Next
FName = Dir
Workbooks(FName).Close Savechanges:=True 'causes error
Loop
Set wb = Nothing
End Sub
You already have a reference to the workbook with wb. Just use that reference!
wb.Close SaveChanges:=True
Anything else is dereferencing objects for no reason.
You are retrieving the name of the next workbook before closing the current open one. Switch the order those two lines of code:
Workbooks(FName).Close Savechanges:=True
FName = Dir()
This: FName = Dir is missing the folder name. Change it to this:
FName = directory & Dir()

VBA: How to delete Column "A" in a specific Folder with different files with Sheet name that varies

I have a folder in my Desktop with more or less 2000 csv files. Those files have only 1 "Sheet" but the sheet name varies. The only similar thing is that it starts with the word "Tankard".
In that one sheet, I just need to remove Column A and Save it, for all 2000 files. Its only my 2nd month to explore vba automation at work. I'd appreciate if someone can help me. Thanks in advance.
Script:
Sub Tank()
Dim wb As Workbook
Dim myPath As String
Dim myfile As String
Dim myExtension As String
Dim SheetName As String
'Optimize Macro Speed
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.Calculation = xlCalculationManual
SheetName = "Tankard*"
myPath = "\\ph00winfdfs01p\shares\JoeyC\documents\Roaming\Windows\Desktop\Tank\"
If myPath = "" Then GoTo ResetSettings
'Target File Extension (must include wildcard "*")
myExtension = "Tankard*.csv"
'Target Path with Ending Extention
myfile = Dir(myPath & myExtension)
'Loop through each Excel file in folder
For i = 1 To 201
Set wb = Workbooks.Open(Filename:=myPath & myfile)
';;;;;;;;;;;;;;WRITE YOUR CODE HERE
Sheets("SheetName").Select
Columns("A").Select
Selection.Delete
wb.Close SaveChanges:=True
Next i
'Get next file name
myfile = Dir
'Message Box when tasks are completed
MsgBox "Task Complete!"
ResetSettings:
'Reset Macro Optimization Settings
Application.EnableEvents = True
Application.Calculation = xlCalculationAutomatic
Application.ScreenUpdating = True
End Sub
Try to understand what's happening. What this sub does at the moment is opening the first workbook that Dir can find, opening it 201 times and deleting the first column of sheet "Sheetname" every time.
Sheets("SheetName").Select
This selects the sheet with the name "Sheetname", not the name with the value that you set the string Sheetname to. If anything, it should be Sheets(Sheetname) but wildcards don't work here anyways.
Now let's look at the process you're trying to achieve.
myfile = Dir(myPath & myExtension)
sets myfile to the first file that matches your pattern ...\Tankard*.csv
Set wb = Workbooks.Open(Filename:=myPath & myfile)
opens the file and now you can access the workbook via wb
To delete the first column on the sheet I would recommend selecting all that stuff but deleting the range directly:
wb.Sheets(1).Columns(1).Delete 'If you want to actually delete the column
wb.Sheets(1).Columns(1).Clear 'If you want to just remove the values
As you can see you don't need the name of the sheet at all. Now save the workbook:
wb.Close SaveChanges:=True
Now you can set myfile to the next filename using Dir:
myfile = Dir
Then repeat that until there are no more files (at that point Dir will return "". The best way to achieve that is to use a While loop, e.g. like this
While myfile <> ""
'Do stuff here
Wend '(While End)
The advantage over a For loop is that you don't need to know the exact number of files in your folder.
I'll leave it up to you to patch that all together.

Combine Workbooks and Rename imported worksheet using VBA in Excel

I am trying to import all the XLS files in a particular directory into one workbook. I've tried several sources for the code and the closest I've come is the one below (all the rest complained when closing the imported workbook no matter what i tried).
All I want to do now is take the text from a merged cell (C7 and D7) and rename the new worksheet to that. (there is a carriage return above the name in the cell in case this has any impact. I have no control over the source files as they're produced by an external team).
I'm afraid I have almost no ability with coding of any kind but I can normally futz things reading code from other sources but I stumped here. I've managed to get it to rename it to the source filename but I would prefer to get it from the cell text.
Cheers!
Sub Merge2MultiSheets()
Dim wbDst As Workbook
Dim wbSrc As Workbook
Dim wsSrc As Worksheet
Dim MyPath As String
Dim strFilename As String
Application.DisplayAlerts = False
Application.EnableEvents = False
Application.ScreenUpdating = False
MyPath = "C:\Temp\" ' change to suit
Set wbDst = Workbooks.Add(xlWBATWorksheet)
strFilename = Dir(MyPath & "\*.xls", vbNormal)
If Len(strFilename) = 0 Then Exit Sub
Do Until strFilename = ""
Set wbSrc = Workbooks.Open(Filename:=MyPath & "\" & strFilename)
Set wsSrc = wbSrc.Worksheets(1)
wsSrc.Copy After:=wbDst.Worksheets(wbDst.Worksheets.Count)
ActiveSheet.Name = wsSrc.Range("C7").Value
wbSrc.Close False
strFilename = Dir()
Loop
wbDst.Worksheets(1).Delete
Application.DisplayAlerts = True
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
I would change this line:
ActiveSheet.Name = wsSrc.Range("C7").Value
to:
wbDst.Worksheets(wbDst.Worksheets.Count).Name = wsSrc.Range("C7")
This will ensure you're naming the sheet in your destination workbook, not in your source workbook, which you might end up with by using ActiveSheet
From your question in the comment about the order of your files:
(BTW - you should edit your post and put the question in there, comments can get deleted)
The order is determined by the "natural" sort order that the files are held in by the OS. I have not found any flags that can be added to the Dir() command to sort them on input.
If you need to process them in name order, I would suggest:
Create a scratch sheet in wbDst
Loop through all the files using Dir(), putting them in Range(A1:An)
i.e put the first file name in Range("A1"), the second file name in Range("A2"), etc
Sort Range(A1:An) so they are in the desired order
Loop through your now sorted Range() to do the actual processing
Delete the scratch sheet from wbDst when you're done processing
For now, comment out:
Application.DisplayAlerts = False
Application.EnableEvents = False
Application.ScreenUpdating = False
These are great things to have in your code, but not until everything is working properly
I would suggest changing:
If Len(strFilename) = 0 Then Exit Sub
to
If Len(strFilename) > 0 Then
Do Until...
Loop
Because, if your initial read of the directory gives you no files, you never get to your clean up code after your loop. At the moment, there's nothing really critical there, but you may modify code in the future, or use this as model for other code that will require critical clean up, and it's a good habit to be in.

Copy & Transpose Values from 1 Workbook to Another

Sub LoopThroughDecTab()
Dim MyFile As String
Dim erow
Dim FilePath As String
FilePath = "C:"
MyFile = Dir(FilePath)
Do While Len(MyFile) > 0
If MyFile = "Dec Tab Macro.xlsm" Then
Exit Sub
End If
Workbooks.Open (FilePath & MyFile)
ActiveWorkbook.Worksheets("Declaration Analysis (Source)").Activate
Range("H9:H21").Copy
ActiveWorkbook.Close False
'Getting Runtime error PasteSpecialMethod of Range Failed on following line'
ActiveSheet.Range(Cells(erow, 1), Cells(erow, 7)).PasteSpecial.Range Transpose:=True
MyFile = Dir
Loop
End Sub
I have files in a folder, the code loops through the files copies values and then I want those values Transposed into the Active MasterSheet. There are 7 values that need to be pasted, and then it should open the next workbook in folder and repeat the process.
Assuming that you posted your complete code, and simply interjected the 'non-code' message to tell us where your error was, give this a try:
Option Explicit
Sub LoopThroughDecTab()
Dim MyFile As String
Dim erow
Dim FilePath As String
Dim DestWB as Workbook
Dim SourceWB as Workbook
'this way we know the one where the code is running and the destination for our copies
set DestWB = ThisWorkbook
FilePath = "C:"
MyFile = Dir(FilePath)
Do While Len(MyFile) > 0
If MyFile = "Dec Tab Macro.xlsm" Then
Exit Sub
End If
Set SourceWB = Workbooks.Open (FilePath & MyFile)
SourceWB.Worksheets("Declaration Analysis (Source)").Range("H9:H21").Copy
'Move the close to AFTER you do the paste
'NOTE: You may have to make a change here:
DestWB.Range(Cells(erow, 1), Cells(erow, 7)).PasteSpecial.Range Transpose:=True
SourceWB.Close False
MyFile = Dir
Loop
End Sub
If you open two workbooks (A & B) in Excel, copy some cells from A, close A, then try to paste into B, you'll have nothing left to paste - closing A clears the clipboard buffer. I believe the same thing is happening here.
Important Notes:
I've removed all references to ActiveWorkbook - I believe that I've gotten it correct, but I always get a bit lost when using Active*, so I avoid it at all cost. (There are a very few situations where it's the only way to get things done, this isn't one of them.) If I've messed up your source & destinations for the copy, simply reverse the Set statements so you're using them the other way.
I'm not sure where erow and FilePath are getting set, so I'm assuming this wasn't the complete code. The assumption is that they'll still get set somehow.
I've not used the copy/transpose function, so you may well need to include Excel Developers's adjustments, as well.
It's difficult to understand what's the problem without seeing what are you copying, but you can try:
ActiveSheet.Cells(erow, 1).PasteSpecial Transpose:=True
set CopyFromRange = Range("H9:H21")
set CopyToRange = ActiveSheet.Cells(erow,1).Resize(1,13)
CopyToRange.Value = Application.Transpose(CopyFromRange.Value)

Combine Multiple Excel Workbooks into one Workbook with multiple sheets

I have about 70 different excel files that I need to combine into one master workbook. I would like each excel file to get its own worksheet in the master workbook. The name of the worksheet generated in the master workbook doesn't matter.
I retrieved this code off of another website, but cannot make it work for my needs. This code stipulates that all files to be combined are located in the same directory. I have them located here "C:\Users\josiahh\Desktop\cf"
Below is the code as it is now
Sub GetSheets()
Path = "C:\Users\dt\Desktop\dt kte\"
Filename = Dir(Path & "*.xls")
Do While Filename <> ""
Workbooks.Open Filename:=Path & Filename, ReadOnly:=True
For Each Sheet In ActiveWorkbook.Sheets
Sheet.Copy After:=ThisWorkbook.Sheets(1)
Next Sheet
Workbooks(Filename).Close
Filename = Dir()
Loop
End Sub
This is tested and works as expected. You would be wise to use Option Explicit and declare your variables appropriately in the future, although that did not cause any problems with your code.
As indicated in comments above, the likely failure is that the argument you're passing to the Dir function is unnecessarily restrictive:
=Dir(path & "*.xls") will look ONLY for files ending exactly in ".xls", and will not account for newer file formats. To resolve that, do =Dir(path & "*.xls*")
Code below:
Option Explicit
Const path As String = "C:\Users\dt\Desktop\dt kte\"
Sub GetSheets()
Dim FileName As String
Dim wb As Workbook
Dim sheet As Worksheet
FileName = Dir(path & "*.xls*")
Do While FileName <> ""
Set wb = Workbooks.Open(FileName:=path & FileName, ReadOnly:=True)
For Each sheet In wb.Sheets
sheet.Copy After:=ThisWorkbook.Sheets(1)
Next sheet
wb.Close
FileName = Dir()
Loop
End Sub