I have written a VBScript to group the files based on the file type for a particular folder path (given as input). I'm trying to handle a scenario that when a folder path is empty, the script should ask us to mention the file path. However, I'm not able to handle it.
v_Path = InputBox("Enter the FileName Along With Path")
If IsEmpty(v_Path) Then
MsgBox("What's the File Path?")
Else
Set objFso = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder(v_Path)
Set colFiles = objFolder.Files
For Each objFile in colFiles
v_FileName = v_Path&"\" & objFile.Name
v_FileExtensionName = v_Path & "\" & objFso.GetExtensionName(v_FileName)
If Not(objFso.FolderExists(v_FileExtensionName)) Then
objFso.CreateFolder(v_FileExtensionName)
objFso.MoveFile v_FileName, v_FileExtensionName & "\"
Else
objFso.MoveFile v_FileName, v_FileExtensionName & "\"
End If
Next
MsgBox("Files Grouped Based on File Type!!")
End If
Set objFso = Nothing
Set objFolder = Nothing
Set colFiles = Nothing
IsEmpty is looking at the string here and saying v_Path is initiliazed or not. If the variable was an object reference, or not declared, then isEmpty will return true. In this case, the message box returns an empty string or ""
Try this change,
If Isempty(v_Path) or v_Path = "" Then
or just
If v_Path = "" Then
Related
I have some XML files in a folder \\demo.US\Modified\. The files in the folder are:
USA.xml
Canada.xml
Mexico.xml
The code below is changing the encoding from UTF-8 to windows-1252 and is creating a modified file mod.xml.
This mod.xml file have data from all three XML files concatenated.
I need help so I can save files separately.
If value of objFile.Name is USA.xml then it should save modified file name as USA_mod.xml. the output for \\demo.US\Modified\ folder after execution is complete should have mod files in it as below.
USA.xml
Canada.xml
Mexico.xml
USA_mod.xml
Canada_mod.xml
Mexico_mod.xml
The code I used is as follows.
Set objFSO = CreateObject("Scripting.FileSystemObject")
objStartFolder = "\\demo.US\Modified\"
Set objFolder = objFSO.GetFolder(objStartFolder)
Set colFiles = objFolder.Files
For Each objFile In colFiles
WScript.Echo objFile.Name
Set objFile = objFSO.OpenTextFile(objStartFolder & objFile.Name, 1)
Set outFile = objFSO.OpenTextFile(objStartFolder & "mod.xml", 2, True)
Do Until objFile.AtEndOfStream
strContent = strContent & objFile.ReadLine
Loop
MsgBox strContent
strContent = Replace(strContent, "encoding=""UTF-8""", "encoding=""windows-1252""")
outFile.WriteLine strContent
outFile.Close
objFile.Close
Next
As others have already pointed out, you shouldn't do what you're attempting to do here, because it is very likely to create more problems down the road. Find the cause of the issue and fix that instead of trying to handle symptoms. You have been warned.
With that said, the reason why the content of all input files is written to the same output file is because you always specify the same output file. That file should contain only the content of the last input file, though, because you open the file for writing (thus erasing previous content) rather than for appending.
Replace these lines:
Set objFile = objFSO.OpenTextFile(objStartFolder & objFile.Name, 1)
Set outFile = objFSO.OpenTextFile(objStartFolder & "mod.xml", 2, True)
with this:
Set inFile = objFile.OpenAsTextStream
outFilename = objFSO.BuildPath(objStartFolder, objFSO.GetBaseName(objFile) & "_mod.xml")
Set outFile = objFSO.OpenTextFile(outFilename, 2, True)
and also replace the other occurrences of objFile after that with inFile (always avoid changing the value of a loop variable), and the code should do what you expect it to do. But again, be warned that the output may not be valid XML.
I managed to made it working, below is the code I used
Dim objFSO, filePath, objFile, colFiles, s , FName
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set filePath = objFSO.GetFolder("\\demo.US\Modified\")
Set colFiles = filePath.Files
For Each FName in colFiles
set objFile = objFSO.OpenTextFile(FName.Path,1)
set outFile = objFSO.OpenTextFile(LEFT(FName.Path,instr(FName.Path,".xml")-1) &"_mod.xml",2,True)
do until objFile.AtEndOfStream
strContent=objFile.ReadLine
Loop
strContent = Replace(strContent, "encoding=""UTF-8""", "encoding=""windows-1252""")
outFile.WriteLine strContent
outFile.Close
objFile.Close
Next
I was trying to build a VBS to test creating files because a larger script I wrote isn't creating an output file. The point of the following script is to test functionality; which I'm not currently seeing.
Option Explicit
Dim objFSO, objFSOText, objFolder, objFile
Dim strDirectory, strFile
strDirectory = "C:\Test\next"
strFile = "\Try.txt"
' Create the File System Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
' Create the Folder specified by strDirectory on line 10
Set objFolder = objFSO.CreateFolder(strDirectory)
' -- The heart of the create file script
'-----------------------
'Creates the file using the value of strFile on Line 11
' -----------------------------------------------
Set objFile = objFSO.CreateTextFile(strDirectory & strFile)
Wscript.Echo "Just created " & strDirectory & strFile
Wscript.Quit
While running this code, everything works the first time but there isn't an output file in the destination directory. When I run it again it throws an error that the file already exists.
I think the problem is that you are trying to create the path "C:\Test\next", which is a structure of two nested folders) in one go and also do not test if that path already exists.
To create a nested folder structure, I have added a small helper function CreateNestedFolder to your code and tidied it up a bit:
Option Explicit
Dim strDirectory, strFile, overwrite
strDirectory = "C:\Test\next"
strFile = "Try.txt"
overwrite = True 'set this to False if you do not wish to overwrite an existing file
'Create the (nested) Folder Structure specified by strDirectory if it does not exist yet
If Not CreateNestedFolder(strDirectory) Then
Wscript.Echo "Could not create folder " & strDirectory
Else
Dim objFSO, objFile
' Create the File System Object
Set objFSO = CreateObject("Scripting.FileSystemObject")
' -- The heart of the create file script
'-----------------------
'Creates the file using the value of strFile
' -----------------------------------------------
'combine the directory and filename
strFile = strDirectory & "\" & strFile
'Create the new file and write something in it
Set objFile = objFSO.CreateTextFile(strFile, overwrite)
objFile.WriteLine("This is a test.")
objFile.Close
Wscript.Echo "Just created " & strFile
'Clean up the used objects
Set objFile = Nothing
Set objFSO = Nothing
End If
Function CreateNestedFolder(ByVal sPath)
'Helper function to create a nested folder structure.
'Returns True on success, False otherwise
Dim aFolders, oFso, i, firstIndex
On Error Resume Next
Set oFso = CreateObject("Scripting.FileSystemObject")
'Check if the path already exists
If Not oFso.FolderExists(sPath) Then
'Find the root drive and split the path in subfolder parts
aFolders = Split(sPath, "\")
'Get the root path from the complete path
If Left(sPath, 2) = "\\" Then
'If this is a UNC path then the root will be "\\server\share"
sPath = "\\" & aFolders(2) & "\" & aFolders(3)
firstIndex = 4
Else
'For a local path, the root is "X:"
aFolders = Split(sPath, "\")
sPath = aFolders(0)
firstIndex = 1
End If
'Loop through the aFolders array and create new folders if needed
For i = firstIndex to UBound(aFolders)
If Len(aFolders(i)) > 0 Then
sPath = sPath & "\" & aFolders(i)
If Not oFso.FolderExists(sPath) Then oFso.CreateFolder sPath
End If
Next
End If
CreateNestedFolder = (Err.Number = 0)
On Error GoTo 0
Set oFso = Nothing
End Function
How to replace a specific string with the filename? Example: I have several files with different names (like: Test.asp, Constant.asp, Letter.asp, etc.) within a subfolder that contain the text "ABC123". I would like to replace the "ABC123" in each file with the filename.
Below is the code I have that finds string and replaces it with a specific string but it doesn't do the job that I listed above.
Option Explicit
Dim objFilesystem, objFolder, objFiles, objFile, tFile, objShell, objLogFile,objFSO, objStartFolder, colFiles
Dim SubFolder, FileText, bolWriteLog, strLogName, strLogPath, strCount, strCount2, strOldText, strNewText, strEXT
bolWriteLog = True
Const ForReading = 1
Const ForWriting = 2
Const TriStateUseDefault = -2
Set objFilesystem = WScript.CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("WScript.Shell")
strLogName = "log.txt"
strLogPath = "C:\" & strLogName
strCount = 0
strCount2 = 0
strOldText = "ABC123"
strNewText = ""
strEXT = "asp"
'Initialize log file
If bolWriteLog Then
On Error Resume Next
Set objLogFile = objFileSystem.OpenTextFile(strLogPath, 2, True)
WriteLog "############### Start Log ##################"
If Not Err.Number = 0 Then
MsgBox "There was a problem opening the log file for writing." & Chr(10) & _
"Please check whether """ & strLogPath & """ is a valid file and can be openend for writing." & _
Chr(10) & Chr(10) & "If you're not sure what to do, please contact your support person.", vbCritical, "Script Error"
WScript.Quit
End If
On Error Goto 0
End If
Set objFSO = CreateObject("Scripting.FileSystemObject")
objStartFolder = "D:\MyFolder"
Set objFolder = objFSO.GetFolder(objStartFolder)
WScript.Echo objFolder.Path
Set colFiles = objFolder.Files
For Each objFile In colFiles
'WScript.Echo objFile.Name
' Now we have an exception for all files that can not be opened in text modus: all extensions such as "exe" should be listed upfront.
ReplaceText(objFile)
Next
ShowSubfolders objFSO.GetFolder(objStartFolder)
Sub ReplaceText(objFile)
If InStr(1, strEXT, Right(LCase(objFile.Name), 3)) = 0 Or objFile.Size = 0 Then
Else
strCount = strCount + 1
WriteLog("Opening " & objFile.Name)
Set tFile = objFile.OpenAsTextStream(ForReading, TriStateUseDefault)
FileText = tFile.ReadAll
tFile.Close
If InStr(FileText, strOldText) Then
WriteLog("Replacing " & strOldText & " with " & strNewText & ".")
FileText = Replace(FileText, strOldText, strNewText)
WriteLog("Text replaced")
Else
WriteLog(strOldText & " was not found in the file.")
strCount2 = strCount2 + 1
End If
Set tFile = objFile.OpenAsTextStream(ForWriting, TriStateUseDefault)
tFile.Write FileText
tFile.Close
FileText = ""
strCount = 0
strCount2 = 0
End If
End Sub
Sub ShowSubFolders(Folder)
For Each Subfolder in Folder.SubFolders
'WScript.Echo Subfolder.Path
Set objFolder = objFSO.GetFolder(Subfolder.Path)
Set colFiles = objFolder.Files
For Each objFile in colFiles
'WScript.Echo objFile.Name
ReplaceText(objFile)
Next
ShowSubFolders Subfolder
Next
End Sub
WriteLog "############### EndLog ##################"
WScript.Echo "Script Complete"
objShell.Run "C:\" & strLogName
'Clear environment and exit
On Error Resume Next
Set tFile = Nothing
Set objFile = Nothing
Set objFiles = Nothing
Set objFolder = Nothing
Set objLogFile = Nothing
Set objFilesystem = Nothing
Set objShell = Nothing
WScript.Quit
'Subs and functions ********** DO NOT EDIT ***************
Sub WriteLog(sEntry)
If bolWriteLog Then objLogFile.WriteLine(Now() & ": Log: " & sEntry)
End Sub
I can give you a one line Ruby solution, should be not too difficult to translate that in Python but somewhat more extensive in VbScript I am afraid. First a generic search and replace version.
ARGV[0..-3].each{|f| File.write(f, File.read(f).gsub(ARGV[-2],ARGV[-1]))}
Save it in a script, eg replace.rb
You start in on the command line (here cmd.exe) with
replace.rb *.txt <string_to_replace> <replacement>
broken down so that I can explain what's happening but still executable
# ARGV is an array of the arguments passed to the script.
ARGV[0..-3].each do |f| # enumerate the arguments of this script from the first to the last (-1) minus 2
File.write(f, # open the argument (= filename) for writing
File.read(f) # open the argument (= filename) for reading
.gsub(ARGV[-2],ARGV[-1])) # and replace all occurances of the beforelast with the last argument (string)
end
And finally your request to replace ABC123 with the filename.
Of course tested and working
ARGV[0..-1].each{|f| File.write(f, File.read(f).gsub('ABC123', f))}
Contents of one of my testfiles (1.txt) after executing
test phrase
1.txt
EDIT
I see you want subfolder recursion on a fixed folder, no problem
Dir['**/*'].each{|f| File.write(f, File.read(f).gsub('ABC123', f)) unless File.directory?(f) }
I have a directory of files that I want to Loop through and use part of their filename to replace text in a template doc.
For example one filename may be 'NV_AD32_city.dxf'. All files in the directory follow the same filename pattern of XX_XXXX_string.dxf, using two underscores.
I need to capture the string to the right of the first "_" and to the left of the "."so for this example that would be 'AD32_city'
How do I script to use capture that text of the active file to replace text in the template? I guess I need to create an object? But what is the object to use for the current file from a directory?
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Thx for the replies, guys. After several days of trying your code I am just not "getting it". I understand it is set up to take the part of the filename's string that I want but how do I tell the script to use the current file I am looping through? Here is my script so far. I have your code on line 20 under the Sub 'GetNewInputs'
Set fso = CreateObject("Scripting.FileSystemObject")
Option Explicit
Dim WritePath : WritePath = "S:\TempFolder\"
Dim OutFile : OutFile = "VEG_DXF-2-SHP_script-"
Dim WorkingFile : WorkingFile = GetFileContent(SelectFile())
Dim NewState, NewSection, NewArea
Dim OldState, OldSection, OldArea
Call GetNewInputs()
Call GetOldInputs()
Sub GetNewInputs()
NewState = UCase(InputBox("INPUT STATE:", _
"INPUT STATE", "SOCAL"))
NewSection = ("Section_" & InputBox("INPUT SECTION NUMBER:", _
"INPUT SECTION", "14"))
NewArea = "^[^_]+_(.*)\.dxf$"
End Sub
Private Sub GetOldInputs()
OldState = "XX"
OldSection = "_X"
OldArea = "ZZZZ"
End Sub
Function SelectFile()
SelectFile = vbNullString
Dim objShell : Set objShell = WScript.CreateObject("WScript.Shell")
Dim strMSHTA : strMSHTA = "mshta.exe ""about:" & "<" & "input type=file id=FILE>" _
&"<" & "script>FILE.click();new ActiveXObject('Scripting.FileSystemObject')" _
&".GetStandardStream(1).WriteLine(FILE.value);close();resizeTo(0,0);" & "<" & "/script>"""
SelectFile = objShell.Exec(strMSHTA).StdOut.ReadLine()
If SelectFile = vbNullString Then
WScript.Echo "No file selected or not a text file."
WScript.Quit
End If
End Function
Private Function GetFileContent(filePath)
Dim objFS, objFile, objTS
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objFile = objFS.GetFile(filePath)
Set objTS = objFile.OpenAsTextStream(1, 0)
GetFileContent = objTS.Read(objFile.Size)
Set objTS = Nothing
End Function
For Each FileRefIn fso.GetFolder("S:\SOCAL\Section_14\Veg DXFs\").Files
NewFile = WorkingFile
NewFile = Replace(NewFile, OldState, NewState)
NewFile = Replace(NewFile, OldSection, NewSection)
NewFile = Replace(NewFile, OldArea, NewArea)
WriteFile NewFile, WritePath & OutFile & ".gms"
WScript.Echo NewArea
Next
Private Sub WriteFile(strLine,fileName)
On Error Resume Next
Dim objFSO, objFile
Set objFSO = CreateObject("Scripting.FileSystemObject")
Do Until IsObject(objFile)
Set objFile = objFSO.OpenTextFile(fileName, 8, True)
Loop
objFile.WriteLine strLine
objFile.Close
End Sub
Well, that’s actually two questions.
To enumerate files in a directory, you can use FileSystemObject, like this (untested)
const strFolderPath = "C:\Temp\Whatever"
set objFSO = CreateObject( "Scripting.FileSystemObject" )
set objFolder = objFSO.GetFolder( strFolderPath )
set colFiles = objFolder.Files
for each objFile in colFiles
' Do whatever you want with objFile
next
Here's the reference of those objects properties/methods.
And to extract portion of file names, you could use a regular expression.
Here’s some guide how to use'em in VBScript.
The following expression should work for you, it will capture the portion of that file names you asked for:
"^[^_]+_(.*)\.dxf$"
If you need to edit the content of the .dxf files, you will need to work within the AutoCAD VBA (Visual Basic for Applications) environment.
If that is the case, you will need to start with something like below:
GetObject("AutoCAD.Application.20")
CreateObject("AutoCAD.Application.20")
https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2015/ENU/AutoCAD-ActiveX/files/GUID-0225808C-8C91-407B-990C-15AB966FFFA8-htm.html
** Please take note that "VBA is no longer distributed with the AutoCAD installation; it must be downloaded and installed separately. The VBA Enabler for Autodesk AutoCAD can be downloaded here."
I am working on a project that requires me to search and list all files in a folder that could have multiple sub folders and write it to text documents.
Primarily the file extension i will be searching for is a .Doc, but I will need to list the other files found in said directory as well.
To make things slightly more difficult I want the text documents to be sorted by File type and another by Directory.
I do not know how possible this is, but I have search for methods online, but have as of yet found correct syntax.
Any help will be greatly appreciated.
I write this in the past, should server as a base for your version. I know it's not .NET, still I hope it helps something. It prompts the user for a path to scan, recurses into folders, and writes the file name, path, and owner into a CSV file. Probably really inefficient and slow, but does the job.
Main() ' trickster yo
Dim rootFolder 'As String
Dim FSO 'As Object
Dim ObjOutFile
Dim objWMIService 'As Object
Sub Main()
StartTime = Timer()
If Wscript.Arguments.Count = 1 Then ' if path provided with the argument, use it.
rootFolder = Wscript.Arguments.Item(0)
Else
rootFolder = InputBox("Give me the search path : ") ' if not, ask for it
End If
Set FSO = CreateObject("Scripting.FileSystemObject")
Set ObjOutFile = FSO.CreateTextFile("OutputFiles.csv")
Set objWMIService = GetObject("winmgmts:")
ObjOutFile.WriteLine ("Path, Owner") ' set headers
Gather (rootFolder)
ObjOutFile.Close ' close the stream
EndTime = Timer()
MsgBox ("Done. (ran for " & FormatNumber(EndTime - StartTime, 2) & "s.)")
End Sub
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function Gather(FolderName)
On Error Resume Next
Dim ObjFolder
Dim ObjSubFolders
Dim ObjSubFolder
Dim ObjFiles
Dim ObjFile
Set ObjFolder = FSO.GetFolder(FolderName)
Set ObjFiles = ObjFolder.Files
For Each ObjFile In ObjFiles 'Write all files to output files
Set objFileSecuritySettings = _
objWMIService.Get("Win32_LogicalFileSecuritySetting='" & ObjFile.Path & "'")
intRetVal = objFileSecuritySettings.GetSecurityDescriptor(objSD)
If intRetVal = 0 Then
owner = objSD.owner.Domain & "\" & objSD.owner.Name
ObjOutFile.WriteLine (ObjFile.Path & ";" & owner) ' write in CSV format
End If
Next
Set ObjSubFolders = ObjFolder.SubFolders 'Getting all subfolders
For Each ObjFolder In ObjSubFolders
Set objFolderSecuritySettings = _
objWMIService.Get("Win32_LogicalFileSecuritySetting='" & ObjFile.Path & "'")
intRetVal = objFolderSecuritySettings.GetSecurityDescriptor(objSD)
If intRetVal = 0 Then
owner = objSD.owner.Domain & "\" & objSD.owner.Name
ObjOutFile.WriteLine (ObjFolder.Path & ";" & owner) ' write in CSV format
End If
Gather (ObjFolder.Path)
Next
End Function