Issue with cancelling the selection of txt file - excel

I want to import a txt file to excel using a button.
I have a dialog box to pick a folder name and display the name of the folder that the user selects.
If the user selects cancel an error occure because of type mismatch. I have declared variables as VARIANT
Have a look in the code:
Sub ImportTXTFiles()
Dim fso As Object
Dim xlsheet As Worksheet
Dim qt As QueryTable
Dim txtfilesToOpen As Variant, txtfile As Variant
Application.ScreenUpdating = False
Set fso = CreateObject("Scripting.FileSystemObject")
txtfilesToOpen = Application.GetOpenFilename(FileFilter:="Text Files (*.txt), *.txt", _
MultiSelect:=True, Title:="Text Files to Open")
If txtfilesToOpen = "False" Then
Exit Sub
End If
For Each txtfile In txtfilesToOpen
' FINDS EXISTING WORKSHEET
For Each xlsheet In ThisWorkbook.Worksheets
If xlsheet.Name = Replace(fso.GetFileName(txtfile), ".txt", "") Then
xlsheet.Activate
GoTo ImportData
End If
Next xlsheet
' CREATES NEW WORKSHEET IF NOT FOUND
Set xlsheet = ThisWorkbook.Worksheets.Add( _
After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
xlsheet.Name = Replace(fso.GetFileName(txtfile), ".txt", "")
xlsheet.Activate
GoTo ImportData
My question is how can I handle this exception here
If txtfilesToOpen = "False" Then
Exit Sub
End If
if the user cancels the selection, while variables are declared as variant.
Thanks in advance.

Maybe using this auxiliar function will help you out:
Option Explicit
Sub Test()
Dim txtfilesToOpen As String
txtfilesToOpen = GetFile
End Sub
Private Function GetFile() As String
Dim fldr As FileDialog
Set fldr = Application.FileDialog(msoFileDialogFilePicker)
With fldr
.Title = "Text Files to Open"
.AllowMultiSelect = False
If .Show <> -1 Then
MsgBox "No file was picked. Please run the macro again."
End
End If
GetFile = .SelectedItems(1)
End With
End Function
If the user doesn't pick a file, a MsgBox will pop up warning the user and then finishing the whole procedure. Note that this procedure works for only one selected item at a time. If you need to pick more than one, consider using the folder picker.

Related

How to set default directory for Excel's GetOpenFilename using Outlook VBA?

I'm trying to set the default directory for the VBA function GetOpenfilename. I managed to get it working before but lost the code before saving it.
Sub Sample2()
Dim myFile As Variant
Dim i As Integer
Dim myApp As Excel.Application
Dim strCurDir As String
Set myApp = New Excel.Application
ChDrive ("H:\")
ChDir ("H:\99 - Temp")
'Open File to search
myFile = myApp.GetOpenFileName(MultiSelect:=True)
If myFile <> False Then
If IsArray(myFile) Then '<~~ If user selects multiple file
For i = LBound(myFile) To UBound(myFile)
Debug.Print myFile(i)
Next i
Else '<~~ If user selects single file
Debug.Print myFile
End If
Else
Exit Sub
End If
End Sub
I tried several variations of this code and the posts I found are very old. It is going to be part of a bigger code in Outlook 2016.
Try the FileDialog property of the Excel object instead...
Dim xlApp As Object
Set xlApp = CreateObject("Excel.Application")
Dim myFile As Variant
With xlApp.FileDialog(msoFileDialogFilePicker)
.AllowMultiSelect = True
.ButtonName = "Select"
.Title = "Select File"
.InitialFileName = "H:\99 - Temp\"
If .Show = 0 Then Exit Sub 'user cancelled
For Each myFile In .SelectedItems
Debug.Print myFile
Next myFile
End With
Set xlApp = Nothing

How can I open multiple files to copy data into a master workbook in new tab?

I have a master Excel file that needs to inherit data from .csv files.
When I run the VBA, it will pop up the file explorer, let me select multiple files and loop over them and create new sheets.
When I try to copy the data into the sheet that it created, it gives me a type mismatch error.
Sub OpenLMSFiles()
Dim fd As FileDialog
Dim FileChosen As Integer
Dim FileName As String
Dim tempWB As Workbook
Dim i As Integer
Set fd = Application.FileDialog(msoFileDialogFilePicker)
fd.InitialFileName = "Libraries\Documents"
fd.InitialView = msoFileDialogViewList
fd.AllowMultiSelect = True
FileChosen = fd.Show
If FileChosen = -1 Then
For i = 1 To fd.SelectedItems.Count
Set tempWB = Workbooks.Open(fd.SelectedItems(i))
Call ReadDataFromSourceFile(tempWB)
Next i
End If
End Sub
Private Sub ReadDataFromSourceFile(src As Workbook)
Application.ScreenUpdating = False
ThisWorkbook.Sheets.Add
Workbooks(src).Worksheets(src.ActiveSheet).Range("A1:Z500").Copy _
Workbooks(ThisWorkbook).Worksheets(ThisWorkbook.ActiveSheet).Range("A1:Z500")
End Sub
The cause of the error is the way you are referencing workbooks and worksheets, which are collections that take index arguments (integer or string). For example you can reference a workbook as Workbooks(1) (bad idea) or Workbooks("FileName.xlsx") (better). Similarly use Sheets(1) or Sheets("SheetName").
src is a Workbook -> simply use src.Sheets(). Because csv files have only 1 worksheet it is safe to use src.Worksheets(1) (Sheets and Worksheets are equivalent).
Anyway, here is a working code. I rearranged the code as I think ReadDataFromSourceFile should encapsulate opening and closing the csv file as well as reading data from it (only an opinion)
Sub ImportLMSFiles()
Dim fd As FileDialog
Dim FileChosen As Long
Dim FileName As String
Dim i As Long
Set fd = Application.FileDialog(msoFileDialogFilePicker)
fd.InitialFileName = "Libraries\Documents"
fd.InitialView = msoFileDialogViewList
fd.AllowMultiSelect = True
FileChosen = fd.Show
If FileChosen = -1 Then
For i = 1 To fd.SelectedItems.Count
Call ReadDataFromSourceFile(fd.SelectedItems(i))
Next i
End If
End Sub
Private Sub ReadDataFromSourceFile(sSrcFilename As String)
' Validate the name
If Right(sSrcFilename, 4) <> ".csv" Then Exit Sub
Application.ScreenUpdating = False
Dim shtDest As Worksheet: Set shtDest = ThisWorkbook.Sheets.Add
Dim wbSrc As Workbook: Set wbSrc = Workbooks.Open(sSrcFilename)
' csv files have only 1 sheet
' UsedRange is exactly what it sounds like
With wbSrc.Sheets(1)
.UsedRange.Copy shtDest.Range(.UsedRange.Address)
' if you want to rename the new sheet
' Bug: another sheet might have the same name -> u need check for that
' Here I'm just ducking it: name not changed
On Error Resume Next
shtDest.Name = .Name
On Error GoTo 0
End With
wbSrc.Close SaveChanges:=False
Application.ScreenUpdating = True
End Sub

/I want to show a messagebox when the right excel file is not selected

Private Sub CommandButton1_Click()
Application.ScreenUpdating = False
Dim currentWorkbook As Excel.Workbook
Dim otherWorkbook As Excel.Workbook
Dim workbookName As Variant
Set currentWorkbook = ActiveWorkbook
workbookName = Application.GetOpenFilename(workbookNamePath)
If Not workbookName = False Then
Set otherWorkbook = Workbooks.Open(workbookName)
Workbooks("name.csv").Sheets("sheet 2").Copy Before:=ThisWorkbook.Sheets(2)
otherWorkbook.Close False
Set otherWorkbook = Nothing
End If
MsgBox "done?", Title:="Name", Buttons:=vbInformation
Application.ScreenUpdating = False
End Sub
**so when I select a different file other than name.csv i want to give a message " Select the right file" rather than giving me an error code. I am new to vba please help
#Luuklag is absolutely right. Formally I'd check the filename before opening it like this:
If Not workbookName = False Then
if mid(workbookname, instrrev(workbookname,"\")+1) <> "name.csv" Then
MsgBox "Select the right file...."
End If
GetOpenFileName returns the full path so you can even check the path.

convert all xlsx files in directory to text

I am trying to create a button in a .xlsm that will convert each of the ~100 .xlsx files in the myFolder directory to .txt. The below VBA code returns an Expected End Suberror. The data is always in `Sheet 1" even though there may be other sheets present.
The Dos command executes and converts the files but they are unreadable (something to do with excels formatting?). I am not sure what to do? Thank you :)
Dos
cd C:\Users\Desktop\folder
Copy *.xlsx *.txt
VBA
Option Explicit
Private Sub CommandButton1_Click()
Dim oFSO, myFolder
Dim xlText
myFolder = "C:\Users\Desktop\folder"
Set oFSO = CreateObject("Scripting.FileSystemObject")
xlText = -4158 'Excel txt format enum
Call ConvertAllExcelFiles(myFolder)
Set oFSO = Nothing
Call MsgBox("Done!")
Sub ConvertAllExcelFiles(ByVal oFolder)
Dim targetF, oFileList, oFile
Dim oExcel, oWB, oWSH
Set oExcel = CreateObject("Excel.Application")
oExcel.DisplayAlerts = False
Set targetF = oFSO.GetFolder(oFolder)
Set oFileList = targetF.Files
For Each oFile In oFileList
If (Right(oFile.Name, 4) = "xlsx") Then
Set oWB = oExcel.Workbooks.Open(oFile.Path)
For Each oWSH In oWB.Sheets
Call oWSH.SaveAs(oFile.Path & ".txt", FileFormat:=xlTextWindows)
Next
Set oWSH = Nothing
Call oWB.Close
Set oWB = Nothing
End If
Next
Call oExcel.Quit
Set oExcel = Nothing
End Sub
The first lines of your code belong in Private Sub CommandButton1_Click()
(it has to be closed by End Sub)
Option Explicit and proper code indentation can help in this situation
Try this version:
Option Explicit
Private Sub CommandButton1_Click()
Dim myFolder As String
myFolder = "C:\Users\Desktop\folder"
ConvertAllExcelFiles myFolder
MsgBox "Done!"
End Sub
Public Sub ConvertAllExcelFiles(ByVal folderPath As String)
Dim xlApp As Object, wb As Workbook, ws As Variant, fso As Object
Dim fileList As Object, itm As Object, fileName As String
Set fso = CreateObject("Scripting.FileSystemObject")
Set fileList = fso.GetFolder(folderPath).Files
Set xlApp = CreateObject("Excel.Application")
xlApp.DisplayAlerts = False
For Each itm In fileList
If Right(itm.Name, 4) = "xlsx" Then
Set wb = xlApp.Workbooks.Open(itm.Path)
fileName = fso.GetParentFolderName(itm.Path) & "\" & fso.GetBaseName(itm.Path)
If True Then 'if converting all sheets use For loop (Change True to False)
wb.Sheets(1).SaveAs fileName & ".txt", FileFormat:=xlTextWindows
Else
For Each ws In wb.Sheets
ws.SaveAs fileName & " - " & ws.Name & ".txt", FileFormat:=xlTextWindows
Next
Set ws = Nothing
End If
wb.Close: Set wb = Nothing
End If
Next
xlApp.Quit
End Sub

Modify VBS – Excel Macro Loop Apply to all files in folder

I have a script that applies a macro to multiple excel spreadsheets. The code below opens specific file names and runs the script. I would love to modify this to run on all xls files within a specified folder. Any help would be great!
Dim objExcel, objWorkbook, xlModule, strCode
If ReportFileStatus("C:\Billing\Import\IL\3.xls") = "True" Then
OpenFile "C:\Billing\Import\IL\3.xls, ""
If ReportFileStatus("C:\Billing\Import\IL\3.xls") = "True" Then
OpenFile "C:\Billing\Import\IL\3.xls", ""
If ReportFileStatus("C:\Billing\Import\IL\3.xls") = "True" Then
OpenFile "C:\Billing\Import\IL\3.xls", ""
End If
On Error Resume Next
Set xlModule = Nothing
Set objWorkbook = Nothing
objExcel.Quit
Set objExcel = Nothing
On Error GoTo 0
'~~> Sub to open the file
Sub OpenFile(sFile, DestFile)
Set objExcel = CreateObject("Excel.Application")
objExcel.Visible = false
objExcel.DisplayAlerts = False
Set objWorkbook = objExcel.Workbooks.Open(sFile)
Set xlModule = objWorkbook.VBProject.VBComponents.Add(1)
strCode = _
"Sub MACRO()" & vbCr & _
'~~> My Macro Here
"End Sub"
xlModule.CodeModule.AddFromString strCode
objExcel.Run "MACRO"
objWorkbook.Close (False) '<~~ Change false to true in case you want to save changes
objExcel.Application.Quit
End Sub
'~~> Function to check if file exists
Function ReportFileStatus(filespec)
Dim fso, msg
Set fso = CreateObject("Scripting.FileSystemObject")
If (fso.FileExists(filespec)) Then
msg = "True"
Else
msg = "False"
End If
ReportFileStatus = msg
End Function
Thanks
The concept is pretty simple, given a folder path, process all files in it (or only certain files based on extension), and all files within it's subfolder. The simplest method is recursive subs and functions with some global variables in a single thread.
The next thing to consider is to Import .bas file instead of trying to add text to a new module. You need to export a working code from a Module first.
Below assumed the root folder to be "C:\Billing\Import", the exported module .bas file is "C:\Test\Module1.bas", and the Sub name you want to execute is "MACRO".
Const sRootFolder = "C:\Billing\Import"
Const sExportedModule = "C:\Test\Module1.bas"
Const sMacroName = "MACRO"
Dim oFSO, oFDR, oFile ' File and Folder variables
Dim oExcel, oWB ' Excel variables (Application and Workbook)
Start
'------------------------------
Sub Start()
Initialize
ProcessFilesInFolder sRootFolder
Finish
End Sub
'------------------------------
Sub ProcessFilesInFolder(sFolder)
' Process the files in this folder
For Each oFile In oFSO.GetFolder(sFolder).Files
If IsExcelFile(oFile) Then ProcessExcelFile oFile.Path
Next
' Recurse all sub-folders from this folder
For Each oFDR In oFSO.GetFolder(sFolder).SubFolders
ProcessFilesInFolder oFDR.Path
Next
End Sub
'------------------------------
Sub Initialize()
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oExcel = CreateObject("Excel.Application")
End Sub
'------------------------------
Sub Finish()
oExcel.Quit
Set oExcel = Nothing
Set oFSO = Nothing
End Sub
'------------------------------
Function IsExcelFile(oFile)
IsExcelFile = (InStr(1, oFSO.GetExtensionName(oFile), "xls", vbTextCompare) > 0) And (Left(oFile.Name, 1) <> "~")
End Function
'------------------------------
Sub ProcessExcelFile(sFileName)
On Error Resume Next
wscript.echo "Processing file: " & sFileName ' Comment this unless using cscript in command prompt
Set oWB = oExcel.Workbooks.Open(sFileName)
oWB.VBProject.VBComponents.Import sExportedModule
oExcel.Run sMacroName
oWB.Close
Set oWB = Nothing
End Sub
'------------------------------
Feel free to ask if you get stuck understanding the program flow.

Resources