Filename is empty when trying to open file - vba

I try to merge workbooks from a folder in a new workbooks. The VBA code reads the excel file from folder, add every file name to a list box and then, after pressing the button "Start", add very file to the workbook. That is the idea.
The code is as folows:
When opening the file the userform is shown:
Private Sub Workbook_Open()
UserForm1.Show
End Sub
When activating userform, the list box is populated:
Private Sub UserForm_Activate()
Const strFolder As String = "C:\Users\user\Desktop\tmp\"
Const strPattern As String = "*.xls"
Dim strFile As String
Dim collection As New collection
Dim i As Integer
Dim isMerger As Integer
Dim lngth As Integer
strFile = Dir(strFolder & strPattern, vbNormal)
If (StrComp(strFile, "FileMerger.xls") <> 0) Then
If (Len(strFile) <> 0) Then
col.Add (strFolder & strFile)
Do While Len(strFile) > 0
strFile = Dir
If (StrComp(strFile, "FileMerger.xls") <> 0) Then
If (Len(strFile) <> 0) Then
col.Add (strFolder & strFile)
End If
End If
Loop
End If
End If
Vars.xlsFiles = ColToArray(collection)
For i = 1 To UBound(Vars.xlsFiles)
lstFiles.AddItem (Vars.xlsFiles(i))
Next i
End Sub
At this moment listbox and array Vars.xlsFiles are populated; they are OK.
Click on Start button in the userform:
Private Sub cmdStart_Click()
Dim fileName As String
Dim sheet As Worksheet
Dim i As Integer
Dim ub As Integer
ub = UBound(Vars.xlsFiles)
For i = 1 To ub
Workbooks.Open fileName:=Vars.xlsFiles(i), ReadOnly:=True
For Each sheet In ActiveWorkbook.Sheets
sheet.Copy After:=ThisWorkbook.Sheets(1)
Next sheet
Workbooks(fileName).Close
Next i
End Sub
In the folder are 3 files. Their name are in the listbox. But when the first is to be closed I received an error message and after debugging it says that fileName ="" (line Workbooks(fileName).Close).
whatever I try I got the same error, i.e. fileName = "".
What to do ?

Your never set the variable fileName, so it's still the default value "". Maybe you got confused by the fileName:=Vars.xlsFiles(i) of the Workbooks.Open method. That just sets the option FileName of that method. Use some unique name to avoid confusion and set it to Vars.xlsFiles(i) or use
Workbooks(Vars.xlsFiles(i)).close

FileName:= is a named parameter of the Workbooks.Open method. It does not set the value of the cmdStart_Click's fileName variable.
Private Sub cmdStart_Click()
Dim fileName As String
Dim sheet As Worksheet
Dim i As Integer
Dim ub As Integer
ub = UBound(Vars.xlsFiles)
For i = 1 To ub
fileName = Vars.xlsFiles(i)
Workbooks.Open FileName:=fileName, ReadOnly:=True
For Each sheet In ActiveWorkbook.Sheets
sheet.Copy After:=ThisWorkbook.Sheets(1)
Next sheet
Workbooks(fileName).Close
Next i
End Sub

Related

Combining macros in Excel

I'm trying to combine/nest 3 different functions in Excel VBE: open, loop, and click. I have them written out separately, but am unsure of how to combine them. I've tried the "call macro" function but got a compile error returned to me.
The goal is to open a bunch of files within a certain folder and click on the URL in all of them (the URL will not always be the same, so I need a click function that targets any unknown URL within a sheet).
Open macro:
Sub openMyfile()
Dim Source As String
Dim StrFile As String
Source = "/users/kmogilevsky/Desktop/IC_new/"
StrFile = Dir("/users/kmogilevsky/Desktop/IC_new/")
Do While Len(StrFile) > 0
Workbooks.Open Filename:=Source & StrFile
StrFile = Dir("/users/kmogilevsky/Desktop/IC_new/")
Loop
End Sub
Loop macro:
Sub LoopThroughFiles()
Dim MyObj As Object, MySource As Object, file As Variant
Set MySource = MyObj.GetFolder("/users/kmogilevsky/Desktop/IC_new/")
For Each file In MySource.Files
If InStr(file.Name, "test") > 0 Then
End If
Next file
End Sub
Click macro (this needs some work):
Private Sub CommandButton1_Click()
Call NewSub
End Sub
Sub ReadWorkbooksInCurrentFolder()
Dim wbDst As Workbook
Dim wbSrc As Workbook
Dim MyPath As String
Dim strFilename As String
'Stop annoying popups while macro is running
Application.DisplayAlerts = False
Application.EnableEvents = False
Application.ScreenUpdating = False
'When working with many open workbooks its good to explicitly reference all workbooks, makes sure your code works and easier to read, understand and remember which workbook is which.
Set wbDst = ThisWorkbook
srcSheetName = "Data"
dstSheetName = "Results"
'I want to loop through all .xlsx files in the folder
MyPath = ThisWorkbook.Path
strFilename = Dir(MyPath & "\*.xlsx", vbNormal)
If Len(strFilename) = 0 Then
MsgBox "No workbooks found ending in .xlsx in current folder"
Exit Sub
End If
Do Until strFilename = ""
Set wbSrc = Workbooks.Open(Filename:=MyPath & "\" & strFilename)
Call CollectData(wbDst, wbSrc, dstSheetName, srcSheetName)
wbSrc.Close
strFilename = Dir()
Loop
Application.DisplayAlerts = True
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
Sub CollectData(ByRef wbDst as Workbook, ByRef wbSrc as Workbook, dstSheetName as String, srcSheetName as String)
'Copy cell A1 contents in source workbook to destination workbook cell A1
wbDst.Sheets(dstSheetName).Range("A1") = wbSrc.Sheets(srcSheetName).Range("A1")
End Sub
Please edit the subroutine CollectData() so that it suits your needs, i.e. performs the click / url open. (I am not familiar with opening urls from excel, but I loop through workbooks often)
This code will open all Excel files in the IC_New folder on the desktop.
It will then look at each sheet and follow any hyperlinks that are on the sheet.
Sub Open_ClickHyperlinks()
Dim sPath As String
Dim vFiles As Variant
Dim vFile As Variant
Dim wrkBk As Workbook
Dim wrkSht As Worksheet
Dim HLink As Hyperlink
sPath = CreateObject("WScript.Shell").SpecialFolders("Desktop") & Application.PathSeparator & _
"IC_New" & Application.PathSeparator
'Return all files that have an extension starting with xls.
vFiles = EnumerateFiles(sPath, "xls*")
'Loop through each file.
For Each vFile In vFiles
'Open the file
Set wrkBk = Workbooks.Open(Filename:=vFile, UpdateLinks:=False)
With wrkBk
'Loop through each worksheet in the file.
For Each wrkSht In .Worksheets
'Loop through each hyperlink on the worksheet.
For Each HLink In wrkSht.Hyperlinks
HLink.Follow
Next HLink
Next wrkSht
.Close SaveChanges:=False
End With
Next vFile
End Sub
'Get all files in the specified folder, default to include all subfolders as well.
Public Function EnumerateFiles(sDirectory As String, _
Optional sFileSpec As String = "*", _
Optional InclSubFolders As Boolean = True) As Variant
EnumerateFiles = Filter(Split(CreateObject("WScript.Shell").Exec _
("CMD /C DIR """ & sDirectory & "*." & sFileSpec & """ " & _
IIf(InclSubFolders, "/S ", "") & "/B /A:-D").StdOut.ReadAll, vbCrLf), ".")
End Function

Open all dbf files in a folder and save them as excel in another folder

I have a folder "test" containing several dbf files. I would like vba to open them in excel file and save them (in excel format) in another folder keeping the same dbf file names.
I found this code on the net and am trying to use this code for my needs but it won't work. Error message:
"sub of function not defined"
...please look into it.
Sub test()
Dim YourDirectory As String
Dim YourFileType As String
Dim LoadDirFileList As Variant
Dim ActiveFile As String
Dim FileCounter As Integer
Dim NewWb As Workbook
YourDirectory = "c:\Users\navin\Desktop\test\"
YourFileType = "dbf"
LoadDirFileList = GetFileList(YourDirectory)
If IsArray(LoadDirFileList) = False Then
MsgBox "No files found"
Exit Sub
Else
' Loop around each file in your directory
For FileCounter = LBound(LoadDirFileList) To UBound(LoadDirFileList)
ActiveFile = LoadDirFileList(FileCounter)
Debug.Print ActiveFile
If Right(ActiveFile, 3) = YourFileType Then
Set NewWb = Application.Workbooks.Open(YourDirectory & ActiveFile)
Call YourMacro(NewWb)
NewWb.SaveAs YourDirectory & Left(ActiveFile, Len(ActiveFile) - 4) & ".xlsx"
NewWb.Saved = True
NewWb.Close
Set NewWb = Nothing
End If
Next FileCounter
End If
End Sub
You missing the functions GetFileList and YourMacro. A quick search brought me to this website (I think you copied it from there). http://www.ozgrid.com/forum/printthread.php?t=56393
There are the missing functions. Copy those two also in your modul to make it run (I tested it with pdf-Files):
Function GetFileList(FileSpec As String) As Variant
' Author : Carl Mackinder (From JWalk)
' Last Update : 25/05/06
' Returns an array of filenames that match FileSpec
' If no matching files are found, it returns False
Dim FileArray() As Variant
Dim FileCount As Integer
Dim FileName As String
On Error GoTo NoFilesFound
FileCount = 0
FileName = Dir(FileSpec)
If FileName = "" Then GoTo NoFilesFound
' Loop until no more matching files are found
Do While FileName <> ""
FileCount = FileCount + 1
ReDim Preserve FileArray(1 To FileCount)
FileArray(FileCount) = FileName
FileName = Dir()
Loop
GetFileList = FileArray
Exit Function
NoFilesFound:
GetFileList = False
End Function
Sub YourMacro(Wb As Workbook)
Dim ws As Worksheet
Set ws = Wb.Worksheets(1)
ws.Range("A6").Value = "=((+A2*$CN2)+(A3*$CN3)+(A4*$CN4)+(A5*$CN5))/SUM($CN2:$CN5)"
ws.Range("A6").Copy ws.Range("B6:CM6")
ws.Range("CO6").Value = "=CO2"
End Sub
To save files in a different directory:
Dim SaveDirectory As String
SaveDirectory = "c:\Users\navin\Desktop\test\converted to excel"
Replace this line
NewWb.SaveAs YourDirectory & Left(ActiveFile, Len(ActiveFile) - 4) & ".xlsx"
with this
NewWb.SaveAs SaveDirectory & Left(ActiveFile, Len(ActiveFile) - 4) & ".xlsx"

VBA: Open file from cell then move to next cell

I currently have a list of files with the file path (C:/something.xlxs) in column B of a sheet. I want to write a Macro to read the value from the cell, open the file, and then move on to the next cell and open that file, etc.
I currently have this:
Sub openFiles()
Dim sFullName As String
Dim i As Integer
For i = 1 To 5
If Not IsEmpty(Cells(i, 2)) Then
sFullName = Cells(i, 2).Value
Workbooks.Open fileName:=Cells(i, 2).Value, UpdateLinks:=0
End If
Next i
End Sub
It is only opening the first file from the list and then stopping. It is probably a small error but I am having trouble spotting it.
Thanks
I would do it this way:
Sub openFiles()
Dim sFullName As String
Dim i As Integer
Dim wsh As Worksheet
On Error GoTo Err_openFiles
Set wsh = ThisWorkbook.Worksheets("Sheet1")
i = 1
Do While wsh.Range("B" & i)<>""
sFullName = wsh.Range("B" & i)
Application.Workbooks.Open sFullName, UpdateLinks:=False
i = i+1
Loop
Exit_openFiles:
On Error Resume Next
Set wsh = Nothing
Exit Sub
Err_openFiles:
MsgBox Err.Description, vbExclamation, Err.Number
Resume Exit_openFiles
End Sub
Above code works in context and provides a way to handle errors.
Try
Dim wb As Excel.Workbook
Set wb = Workbooks.Open(Filename:=sFullName)

Visual Studio 2015 - Manipulating Excel?

I have 750 Excel files that I want to
clean by deleting columns of data that have a heading with an asterisk,
then take some of that data and put it in a new workbook worksheet, and other data into the same workbook worksheet, and some other data into a second new workbook.
I created a WPF project in Visual Studio 2015 with a little dialog box with 2 radio buttons for
clean data,
produce new files.
This is my VB code:
Class MainWindow
Dim wb As Microsoft.Office.Interop.Excel._Workbook
Dim ws As Microsoft.Office.Interop.Excel._Worksheet
Dim iCol As Integer
Dim strName As String
Dim iIndex As Integer
Dim strPath As String
Dim strFile As String
Private Sub button_Click(sender As Object, e As RoutedEventArgs) Handles button.Click
If cleanRadioButton.IsChecked = True Then
strPath = "c:\test\old\"
strFile = Dir(strPath & "*.csv")
Do While strFile <> ""
wb = wb.Open(Filename:=strPath & strFile)
'Loop through the sheets.
For iIndex = 1 To Application.Worksheets.Count
ws = Application.Worksheets(iIndex)
'Loop through the columns.
For iCol = 1 To ws.UsedRange.Columns.Count
'Check row 1 of this column for the char of *
If InStr(ws.Cells(10, iCol).Value, "*") > 0 Then
'We have found a column with the char of *
ws.Columns(iCol).EntireColumn.Delete
ws.Columns(iCol + 1).EntireColumn.Delete
ws.Columns(iCol + 2).EntireColumn.Delete
End If
Next iCol
Next iIndex
wb.SaveAs(Filename:="C:\test\new\" & wb.Name, FileFormat:=xlOpenXMLWorkbook)
wb.Close(SaveChanges:=False)
strFile = Dir()
Loop
MessageBox.Show("The csv files have now been cleaned. Congrats.")
Else inputRadioButton.IsChecked = True
MessageBox.Show("The data has now been split into Trajectory and ForcePlate input files. High 5.")
End If
End Sub
End Class
I get 3 errors but can't work out how to solve them.
a) Worksheets is not a member of Application [line 19]
b) Worksheets is not a member of Application [line 20]
c) 'xlOpenXMLWorkbook' is not declared. It may be inaccessible due to its protection level.
For a) and b), the pattern is :
Application.Workbooks.Worksheets
For c), easiest way out :
Go into VBE from Excel (Alt + F11)
Press F2 to display the Object Browser
Look for xlOpenXMLWorkbook
Result : Const xlOpenXMLWorkbook = 51 (&H33)
So, just replace it by the value 51!
Here is your amended code :
Class MainWindow
Dim wb As Microsoft.Office.Interop.Excel._Workbook
Dim ws As Microsoft.Office.Interop.Excel._Worksheet
Dim iCol As Integer
Dim strName As String
Dim iIndex As Integer
Dim wbIndex As Integer
Dim strPath As String
Dim strFile As String
Private Sub button_Click(sender As Object, e As RoutedEventArgs) Handles button.Click
If cleanRadioButton.IsChecked = True Then
strPath = "c:\test\old\"
strFile = Dir(strPath & "*.csv")
Do While strFile <> ""
wb = wb.Open(Filename:=strPath & strFile)
'Loop through the sheets.
For wbIndex = 1 To Application.Workbooks.Count
For iIndex = 1 To Application.Workbooks(wbIndex).Worksheets.Count
Ws = Application.Workbooks(wbIndex).Worksheets(iIndex)
'Loop through the columns.
For iCol = 1 To Ws.UsedRange.Columns.Count
'Check row 1 of this column for the char of *
If InStr(Ws.Cells(10, iCol).Value, "*") > 0 Then
'We have found a column with the char of *
Ws.Columns(iCol).EntireColumn.Delete
Ws.Columns(iCol + 1).EntireColumn.Delete
Ws.Columns(iCol + 2).EntireColumn.Delete
End If
Next iCol
Next iIndex
Next wbIndex
'Const xlOpenXMLWorkbook = 51 (&H33)
wb.SaveAs(Filename:="C:\test\new\" & wb.Name, FileFormat:=51)
wb.Close(SaveChanges:=False)
strFile = Dir()
Loop
MessageBox.Show ("The csv files have now been cleaned. Congrats.")
Else: inputRadioButton.IsChecked = True
MessageBox.Show ("The data has now been split into Trajectory and ForcePlate input files. High 5.")
End If
End Sub
End Class
To reference a worksheet yau can use either ws = wb.Worksheets(1) or ws = wb.Worksheets("Sheet1") or ws = excelApp.ActiveWorkbook.Worksheets(1) and to use xlOpenXMLWorkbook use the name of the corresponding Enum XlFileFormatas well: XlFileFormat.xlOpenXMLWorkbook.
This simplified example opens the workbook Test.xlsx, writes text in cell A1 and saves it to new folder.
Imports System.IO
Imports Microsoft.Office.Interop.Excel
Public Class MainWindow
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim excelApp As Application
Dim wb As _Workbook
Dim ws As _Worksheet
Dim rng As Range
Dim strPathOld = "c:\temp\old"
Dim strPathNew = "c:\temp\new"
' get excel application reference
excelApp = New Application
excelApp.Visible = True
excelApp.ScreenUpdating = True
' open the workbook
wb = excelApp.Workbooks.Open(Path.Combine(strPathOld, "Test.xlsx"))
' set reference to the sheet with index 1
ws = wb.Worksheets(1)
' or use sheet name
' ws = wb.Worksheets("Sheet1")
' or use ActiveWorkbook if it exists
' ws = excelApp.ActiveWorkbook.Worksheets(1)
' write text in cell A1
rng = ws.Range("A1")
rng.Formula = "Test123"
' save the workbook in new location
wb.SaveAs(Filename:=Path.Combine(strPathNew, wb.Name), _
FileFormat:=XlFileFormat.xlOpenXMLWorkbook)
excelApp.Quit()
End Sub
End Class
Note: add reference to MS Office Interop for your version of Excel(here example for Excel 2007).

Opening workbooks via hyperlink and then using Hyperlink name as workbook reference

I'm trying to take the hyperlink workbook name and put it into my code.
Sub Workbook()
Dim vbaname as string
Dim WBMaster As Workbook, WBSource As Workbook
Dim WSMaster As Worksheet, WSSource As Worksheet
Range("b7").Hyperlinks(1).Follow
'returns the hyperlink text "Vba Source test"
VbaName = """" & Range("B7").Text & """"
Set WBSource = Workbooks(VbaName)
I get a subscript out of range bug. Is there another way to do this. I just want to be able to put the hyperlink text into that bracket.
If you Debug.Print your VbaName it actually holds the value of B7 but the active window ( the followed one from hyperlink ). If you want to get the name of the workbook from the hyperlink, youre working in, then use this code
Sub GetWorkbookName()
MsgBox "the name of the workbook in the hyperlink is: " & vbCrLf & _
getWorkbookName(Range("B7").Text)
End Sub
Private Function getWorkbookName(hyperLink As String) As String
Dim i&
For i = 1 To Len(hyperLink)
If StrComp(Left(Right(hyperLink, i), 1), "\", vbTextCompare) = 0 Then
getWorkbookName = Right(hyperLink, i - 1)
Exit For
End If
Next i
End Function
On the other hand, I think you are trying to open the workbook from the hyperlink and assign a reference to it. The way you go about it it's not the right approach. I think you may want to consider doing it this way:
Sub Workbook()
Dim wbFromHyperLink As String
Dim WBSource As Workbook
MsgBox "the name of the workbook in the hyperlink is: " & vbCrLf & _
getWorkbookName(Range("B7").Text)
wbFromHyperLink = getWorkbookName(Range("B7").Text)
'Range("b7").Hyperlinks(1).Follow
Set WBSource = Workbooks.Open(Range("B7").Text)
' do not forget to close and free the object
' WBSource.Saved = True
' WBSource.Close
' Set WBSource = Nothing
End Sub
Private Function getWorkbookName(hyperLink As String) As String
Dim i&
For i = 1 To Len(hyperLink)
If StrComp(Left(Right(hyperLink, i), 1), "\", vbTextCompare) = 0 Then
getWorkbookName = Right(hyperLink, i - 1)
Exit For
End If
Next i
End Function