How to check whether a input string is a File name or Folder name using Vbscript - string

My objective is to find whether the given input is s file name or folder name using Vb script.
For example if user gives "D:\Temp\testfile.docx" then it should navigate to File Related Function,
Similarly if user gives "D:\Temp\" then it should navigate to Folder Related Function.
If there is no straightforward solution, Is there any work around to do this ?

Check whether the user input refers to an existing file (.FileExists) or folder (.FolderExists):
If FolderExists(userinp) Then
folderaction
Else
If FileExists(userinp) Then
fileaction
Else
handle bad user input
End If
End If
If that doesn't fit your needs, ask the user to identify folders by always appending "\" and check Right(userinp, 1).

I created this simple function that should suit your needs:
'Return 1 if the provided path is a folder, 2 if it's a file, and -1 if it's neither.
Function GetTypeOfPath(strToTest)
Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")
If(objFSO.FolderExists(strToTest)) Then
GetTypeOfPath = 1
ElseIf(objFSO.FileExists(strToTest)) Then
GetTypeOfPath = 2
Else 'neither
GetTypeOfPath = -1
End If
End Function
You can test it by creating a file "c:\test" and running `MsgBox(GetTypeOfPath("c:\test"))"; it will return 2. Then delete that file, create a folder "c:\test" and run the same thing; it will return 1. Then delete that and run it a third time; it will return -1.

Related

Error in saving minitab graphs and plots: "...collection is empty and contains no valid output object"

I want to automate GageR&R study in minitab.
I found code but the line mtbProject.Commands.Item(1).Outputs.Item(1).Graph.SaveAs.
Gives
Run time error:"IOutput: IOutput collection is empty and contains no valid output object"
Sub msa_macro()
'
' msa_macro Macro
'
'
Dim MtbApp As Mtb.Application
Dim mtbProject As Mtb.Project
Dim mtbWorksheet As Mtb.Worksheet
Set MtbApp = New Mtb.Application
Set mtbProject = MtbApp.ActiveProject
Set mtbWorksheet = mtbProject.ActiveWorksheet
MtbApp.UserInterface.Visible = True
MtbApp.UserInterface.DisplayAlerts = True
mtbProject.ExecuteCommand "Execute 'C:\Amir\DataAnalysis2\MSA_FixtureMill_STC049\MSA_STC049_BSM\Results_Files\readfileMinitab_test.mtb' 1."
mtbProject.Commands.Item(1).Outputs.Item(1).Graph.SaveAs "C:\Result_Files\grph1.png", True, GFJPEG
End Sub
The problem is, that you want to save the Outputs.Item(1) from Commands.Item(1). So you address the first command that you called, which is "Excecute … ", and this has no Output-Item. Therefore the IOutputs Collection for this Command-Item is empty.
The Output-Collection is defined as the Items of Outputs for each command. What you would want to do, is to save the first Output-Item of the command with which you created the graph.
It would be very helpful, if you could provide some information about your readfileMinitab_test.mtb. What are you doing in this .mtb file, is it also a macro-enabled file? I would guess, that you create the graph in this file?
If you want to save your graph as a .png, I guess you might need the MtbGraphFiletype GFPNGColor instead of GFJPEG. You also don´t need to save the file as grph1.png (just grph1 will suffice), as this is done automatically, because you tell Minitab to save it in a specific filetype.
You could also use the digit-code for the Filetypes (which is a little bit shorter). This would mean GFPNGColor = 3 and GFJPEG = 1. For some further information about this I recommend you the Minitab-Automation-Guide.
An example code could look as following:
'This is the first Command Minitab is executing
mtbProject.ExectueCommand "Execute <something>"
'This is the second Command Minitab is executing
mtbProject.ExecuteCommand "Boxplot C" & CStr(i as Integer)
'We want to Save the Graph, which we created with Command 2. We created one graph with
'this Command, to we only have 1 Output.
mtbProject.Commands.Item(2).Outputs.Item(1).Graph.SaveAs <path as String>, True, 3
Thanks Florian. Yes you are right, I figured it out that I am trying to read the output of the wrong command.
I wanted to execute a sequence of 'Gage R&R' commands and to save an output graph. It is completed now.
Thanks again for the helping answer.

Excel 2010 Macro - Creating txt files with names from ColA and content ColB. Stacko. solutions not work

I have found some answers/examples here on stackoverflow for an issue where in Microsoft Excell 2010, I want to create a txt files for each cell from for e.g. ColumnA which would contain file names, and ColumnB which would contain what is inside certain text file, however one example doesn't work at all, and second bugs after few files created.
You can use the CreateTextFile method which will create your file and provide a TextStream object which you can use to write to the text files. Microsoft Docs
Here's a code example that will do what you asked.
Sub CreateTxt()
Dim my_range As Range
Dim pth As String
Set my_range = Selection
For Each x In my_range.Rows:
pth = "C:\excel_test\" + x.Cells(1) + ".txt" 'file name in column A
Set file_sys = CreateObject("Scripting.FileSystemObject")
Set txt_file = file_sys.CreateTextFile(pth, True)
txt_file.WriteLine (x.Cells(2)) 'content in Column B
txt_file.Close
Next x
End Sub
Just remember, in order to create a file you need adequate permissions on the path you're writing to - I had to run excel as administrator to get the functionality.
Also, the True value in the CreateTextFile method is necessary to overwrite any files with the existing file name, if set to false it will throw an error when trying to write to the file.

How to know numerically the last saved file name

I am creating and saving .ini files in Excel. The files need to follow a specific naming convention that increments by 1 each time a file is created. Not all the files will be created in Excel, some will be done in a separate program. Is there a way to read the saved files in their folder to know which number is next?
For example there are files named exampleFile1.ini through exampleFile63.ini. From Excel using VBA or other means can I see that exampleFile63.ini was the last file and name the next exampleFile64.ini?
Thank you. I'm very new if thats not obvious.
This function will return the next available .INI file name:
Private Function GetNextFile() As String
Dim i As Long
Dim fileName As String
For i = 1 To 1000
' Update Path and File Name prefix below to where your .INI files will be stored.
fileName = "d:\path\exampleFile" & i & ".ini"
If Dir(fileName) = "" Then
GetNextFile = fileName
Exit Function
End If
Next
End Function
Call it like this:
Dim NextIniFile As String
NextIniFile = GetNextFile()

VBA Create folder and move file based on folder names in table

I have around 10,000 files all in one folder called "Z:\ContactLog\". The files are named "Contact_1.pdf", "Contact_2.pdf" etc. I also have an Access table with the file names listed in the first column and an associated group name in the second column. The group names are "Group1", Group2" etc.
I need help to write the VBA code to create a sub-folder for each group using the group name as the folder name, (e.g. "Z:\ContactLog\Group1\") and then move the files into the folders according to the group names listed against the file names in the table.
My research so far has found code for moving files based on the file name, but not based on a table field entry. Any help to get started with writing the VBA would be greatly appreciated. I am using Access 2010, but will do this in Excel if needed. Thank you.
I hope it isn't considered bad form to answer your own question, but I have just thought of and tested an answer using a completely different approach.
To achieve the goal I did the following:
Export the access table to Excel, so column A has the file name and column B has the name of the desired destination folder.
In column C use the formula...
=CONCATENATE("xcopy Z:\ContactLog\",A1,".pdf Z:\ContactLog\",B1,"\ /C")
Copy the formula downwards for all 10,000 entries
Copy and paste column C into a batch file
Run the batch file
Manually delete the source files
I have tried this on a small sample of the entries and it works perfectly. Xcopy will create the folders that don't exist. The switch "/C" will allow the batch to continue if there is an error (e.g. if the file does not exist).
Looks like your set, but I thought I would add an Access answer for the heck of it.
First back up the entire folder in question so you can revert incase something goes wrong. Next add a column in the file information table called FILE_MOVED so you can use it as a flag.
I've done this sort of thing a lot and have run into many issues like files moved, renamed, locked, etc. (If there's an error in the run, you'll end up with more errors on subsequent runs trying to move file's that have already been moved.) Be sure to update the FILE_MOVED col to 0 or null if you have to revert to original folder. So here's some code that should accomplish what you wanted:
Declare this in a Module:
Declare Function MoveFile Lib "kernel32" Alias "MoveFileA" (ByVal lpExistingFileName As String, ByVal lpNewFileName As String) As Long
Paste this into a Module:
Function OrganizeFiles() As Long
On Error GoTo ErrHandler
Dim rst As New ADODB.Recordset
Dim strFolderFrom As String, strFolderTo As String
Dim strPathFrom As String, strPathTo As String
rst.CursorLocation = adUseClient
rst.CursorType = adOpenForwardOnly
rst.LockType = adLockOptimistic
rst.Open "SELECT * FROM [YourTableName] WHERE nz(FILE_MOVED,0) = 0 ", CurrentProject.Connection
strFolderFrom = "Z:\ContactLog\" 'the main folder will always be the same
Do Until rst.EOF
'destination folder
strFolderTo = strFolderFrom & rst.Fields("[YourGroupCol]") & "\" 'destination folder can change
'make sure the destination folder is there; if not, then create it
If Dir(strFolderTo, vbDirectory) = "" Then MkDir strFolderTo
'get the source file path
strPathFrom = strBaseFolder & rst.Fields("[YourFileNameCol]")
'get the destination file path
strPathTo = strFolderTo & rst.Fields("[YourFileNameCol]")
Call MoveFile(strPathFrom, strPathTo)
'at this point the file should have been moved, so update the flag
rst.Fields("FILE_MOVED") = 1
rst.MoveNext
Loop
rst.Close
ErrHandler:
Set rst = Nothing
If err.Number <> 0 Then
MsgBox err.Description, vbExclamation, "Error " & err.Number
End If
End Function
This task and the my code is pretty basic but this kind of thing can become complicated when working with multiple source and destination folders or changing file names in addition to moving them.

Excel VBA global variables "lifetime"?

Sorry about the non descriptive Title, I just didn't know how to describe my goal.
I'm new at VBA and didn't yet understand how things really work.
I've written a function which gets a directory from the user, and displays data from the first file in the directory. Now, I want to add a "next" button.
When the "next" button is pressed, my code should display data from the next file in the directory.
I tried to use global variables but they seem to get initialized each time the button is pressed.
What is the best way to achieve my goal? Do I have to use the spreadsheet as memory and write and read everything from there? Or does Excel VBA have some other "live memory" mechanism?
Thanks,
Li
Globals will not normally be reinitialized when you click a button. They will be reinitialized if you recompile your VBA project. Therefore, while debugging, you may see a global being reinitialized.
You can use the spreadsheet as memory. One way to do this is to have a worksheet whose Visibility property you set to xlSheetVeryHidden (you can do this from the VBA project). This worksheet won't be visible to users, so your VBA application can use it to store data.
This could be approached many ways, as with any problem I guess!
You could break the problem up into two subroutines:
1) Retrieve all the file names in the selected directory and display the first file's data
2) If it's not the last file, get the next file's data and display it
You could use a global variable to store the filenames and an index to remember where you are up to in the collection of filenames.
Global filenames As Collection
Global fileIndex As Integer
Public Sub GetFilenames()
Dim selectedDirectory As String
Dim currentFile As String
selectedDirectory = "selected\directory\"
currentFile = Dir$(selectedDirectory)
Set filenames = New Collection
While currentFile <> ""
filenames.Add selectedDirectory & currentFile
currentFile = Dir$()
Wend
' Make sure there were files
If filenames.Count >= 1 Then
fileIndex = 1
' Call a method to display data
DisplayData(filenames(fileIndex))
Else
' No files
End If
End Sub
Public Sub GetNextFile()
' Make sure we have a filenames object
If Not filenames Is Nothing Then
If fileIndex < filenames.Count Then
fileIndex = fileIndex + 1
' Call the display method again
DisplayData(filenames(fileIndex))
Else
' Decide what to do after reaching the final file
End If
Else
' No filenames
End If
End Sub
I didn't include the DisplayData procedure as I'm not sure what type of files you're grabbing or what you are doing with them but if it were say excel files it could be something like:
Public Function DisplayData(filename As String)
Dim displayWb As Workbook
Set displayWb = Workbooks.Open(filename)
' Do things with displayWb
End Function
You could then set the macro of the button to "GetNextFile" and it will cycle through the files after each click. As for the lifetime of global variables, they only reinitialize when the VBA project is reset or when they are specifically initialized through a procedure or the immediate window.
Perhaps these two functions can also help you:
SaveSetting
GetSetting
as showed here: http://www.j-walk.com/ss/excel/tips/tip60.htm

Resources