Reading data from a file with a variable name - VBScript - vbscript

I'm trying to count the number of lines in a text file using VBScript. I have managed to do this without a problem for a text file with a fixed name. EG: "C:\Orig\sample.txt"
However, our filenames change daily, EG: "C:\Orig\sample*todaysdate*.txt"
I have looked high and low for a way to 'read' a file with a variable name and have had no luck.
What I have so far for a fixed file name is:
Dim oFso, oReg, sData, lCount, linesum
Const ForReading = 1, sPath = "C:\Orig\sample.txt"
Set oReg = New RegExp
Set oFso = CreateObject("Scripting.FileSystemObject")
sData = oFso.OpenTextFile(sPath, ForReading).ReadAll
With oReg
.Global = True
.Pattern = "\r\n" 'vbCrLf
lCount = .Execute(sData).Count + 1
End With
WScript.Echo("The total number of lines including the header is " & lCount)
Set oFso = Nothing
Set oReg = Nothing
This works perfectly well, but I just cannot find the correct syntax for a variable file name.
If it is of any help, the file I'm looking to interrogate will be the ONLY file in the containing folder.
Is anybody able to offer any assistance? Many thanks.
I have now tried the following:
Dim objFso, objReg, sData, lCount
Const ForReading = 1
sPath = "C:\Orig"
Set objFso = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFso.GetFolder(sPath)
For Each objFile in objFolder.Files
Set objReg = New RegExp
sData = objFso.OpenTextFile(sPath, ForReading).ReadAll
With objReg
.Global = True
.Pattern = "\r\n" 'vbCrLf
lCount = .Execute(sData).Count + 1
End With
WScript.Echo("The total number of lines including the header is " & lCount)
Set objFso = Nothing
Set objReg = Nothing
Set objFolder = Nothing
set sData = Nothing
Next
But on line 9 I am getting a 'Permission denied' error. I have checked folder permissions and file permissions and I have full rights.
Does anybody have any ideas?
Thanks in advance.

Loop through the files in the folder instead. There's no need to name the file directly.
Dim oFso, oReg, sData, lCount, linesum
Const ForReading = 1
sPath = "C:\Orig\sample\"
Set oFso = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFso.GetFolder(sPath)
For Each objFile in objFolder.Files
Set oReg = New RegExp
sData = oFso.OpenTextFile(sPath, ForReading).ReadAll
With oReg
.Global = True
.Pattern = "\r\n" 'vbCrLf
lCount = .Execute(sData).Count + 1
End With
WScript.Echo("The total number of lines including the header is " & lCount)
Set oFso = Nothing
Set oReg = Nothing
Next

Related

variable isnt updating as the code loops through

Ive written some code that loops through text files in a folder and updates them with an addiotnal header "TREATMENT_CODE" and then appends a code to the end of each line within each text file. The code is taken from the txt file name. Ive set this as a variable called TCode. The problem Im having is that the TCode variable isn't changing after the first loop through. Can anybody help? Thanks
Please excuse all of the msgbox lines, just me using them to figure out whats going on.
Code:
Option Explicit
Dim FSO, FLD, FIL, TS
Dim strFolder, strContent, strPath, FileName, PosA, TCode, rfile, Temp, dataToAppend, fulldata, wfile, TempArr, i
Const ForReading = 1, ForWriting = 2, ForAppending = 8
'Change as needed - this names a folder at the same location as this script
strFolder = "C:\Users\User1\OneDrive - Company/Documents\Temporary_delete_every_month\CRM_combiner_macro\Looping_test\files to amend"
'Create the filesystem object
Set FSO = CreateObject("Scripting.FileSystemObject")
'Get a reference to the folder you want to search
set FLD = FSO.GetFolder(strFolder)
'loop through the folder and get the file names
For Each Fil In FLD.Files
'MsgBox Fil.Path
'If UCase(FSO.GetExtensionName(Fil.Name)) = ".txt" Then
strPath = Fil.Path
'msgbox strPath
'strPath = Replace(strPath,"""","")
'msgbox strPath
posA = InStrRev(strPath, "\") +1
TCode = "|" & Mid(strPath, posA, 11)
msgbox "this is TCode " & TCode
Set fso = CreateObject("scripting.filesystemobject")
'msgbox "next file to amend" & strPath
Set rfile = fso.OpenTextFile(strPath, ForReading) 'File opened in Read-only mode
While Not rfile.AtEndOfStream
temp=rfile.ReadLine()
If rfile.Line=2 Then
dataToAppend = "|TREATMENTCODE"
ElseIf rfile.Line=3 Then
dataToAppend = TCode
End If
fulldata = fulldata & temp & dataToAppend & "|||"
Wend
rfile.Close
fulldata = Left(fulldata,Len(fulldata)-2)
Set wfile = fso.OpenTextFile(strPath, ForWriting) 'File opened in write mode
tempArr = Split(fulldata,"|||")
For i=0 To UBound(tempArr)
wfile.WriteLine tempArr(i)
Next
wfile.Close
Set fso= Nothing
'End If
'Clean up
Set TS = Nothing
Set FLD = Nothing
Set FSO = Nothing
set rfile = Nothing
set wfile = Nothing
set tempArr = Nothing
set Temp = Nothing
set TCode = Nothing
Next
MsgBox "Done!"

How to save all Excel files in a folder as pipe delimited files

I'm writing a process that needs to loop through all Excel files in a folder and save each one as a pipe delimited value.
I've done a lot of hunting on how to do this and most of them say to change the delimiter value in Region settings. This isn't an option for me as this will be implemented on a customer's system and I cannot change these settings.
I've got some code to work as a vba macro in each file, and I have a vbs script that loops through the files in a folder and converts them to tab delimited files, both of these were found from this site and adapted to do what I need.
This is the code i have so far:
WorkingDir = "C:\Test\Temp"
savedir="C:\Test\Temp\"
Dim fso, myFolder, fileColl, aFile, FileName, SaveName
Dim objExcel, objWorkbook
Dim lastColumn
Dim lastRow
Dim strString
Dim i
Dim j
Dim outputFile
Dim objectSheet
Dim objectCells
Set fso = CreateObject("Scripting.FilesystemObject")
Set myFolder = fso.GetFolder(WorkingDir)
Set fileColl = myFolder.Files
Set objExcel = CreateObject("Excel.Application")
objExcel.Visible = False
objExcel.DisplayAlerts = False
For Each aFile In fileColl
name= Left(aFile.Name,Len(aFile.Name)-Len(Extension))
Set objWorkbook = objExcel.Workbooks.Open(aFile)
Set objectSheet = objExcel.ActiveWorkbook.Worksheets(1)
Set objectCells = objectSheet.Cells
lastColumn = objectSheet.UsedRange.Column - 1 + objectSheet.UsedRange.Columns.Count
lastRow = objectSheet.UsedRange.Rows(objectSheet.UsedRange.Rows.Count).Row
SaveName = savedir & name & ".txt"
Set outputFile = CreateObject("Scripting.FileSystemObject").OpenTextFile(SaveName, 2, true)
For i = 1 To lastRow
objectSheet.Cells(i, 1).Select '<-- this is the line currently causing problems
strString = ""
For j = 1 To lastColumn
If j <> lastColumn Then
strString = strString & objectCells(i, j).Value & "|"
Else
strString = strString & objectCells(i, j).Value
End If
Next
outputFile.WriteLine(strString)
Next
objFileToWrite.Close
Set objFileToWrite = Nothing
Next
Set objWorkbook = Nothing
Set objExcel = Nothing
Set myFolder = Nothing
Set fileColl = Nothing
Set fso = Nothing
I don't really use vb that often, so I'm basically changing a line until it stops throwing errors then moving on to the next one.
I just cannot get this over the commented line. It is currently giving me the error "Select method of Range class failed" with code 800A03EC. Searching this has given me no real results...
The file pretty much has to be pipe delimited as the file contains a lot of the common delimiters (commas, tabs etc.).
Any help to get this to work is greatly appreciated. This is my first post here so apologies if I've given too much or too little info, just let me know and I'll update as required
Update
Have managed to get it working, my working code in answer below. If anyone has suggestions on how to make this faster it'd be appreciated :)
I managed to crack it, I had to activate the sheet I wanted before I could use it and also call the sheet by name instead of using "1". Working code is below in case it helps anyone else in the future. I know it's ugly and could probably be done better but it works :)
WorkingDir = "C:\Test\Temp"
savedir="C:\Test\Temp\"
Extension = ".xls"
neededextension= ".txt"
Dim fso, myFolder, fileColl, aFile, FileName, SaveName
Dim objExcel, objWorkbook
Dim lastColumn
Dim lastRow
Dim strString
Dim i
Dim j
Dim outputFile
Dim objectSheet
Dim objectCells
Set fso = CreateObject("Scripting.FilesystemObject")
Set myFolder = fso.GetFolder(WorkingDir)
Set fileColl = myFolder.Files
Set objExcel = CreateObject("Excel.Application")
objExcel.EnableEvents = false
objExcel.Visible = False
objExcel.DisplayAlerts = False
For Each aFile In fileColl
ext = Right(aFile.Name,Len(Extension))
name= Left(aFile.Name,Len(aFile.Name)-Len(Extension))
Set objWorkbook = objExcel.Workbooks.Open(aFile)
Set objectSheet = objExcel.ActiveWorkbook.Worksheets("MICE BOB")
Set objectCells = objectSheet.Cells
lastColumn = objectSheet.UsedRange.Column - 1 + objectSheet.UsedRange.Columns.Count
lastRow = objectSheet.UsedRange.Rows(objectSheet.UsedRange.Rows.Count).Row
SaveName = savedir & name & ".txt"
Set outputFile = CreateObject("Scripting.FileSystemObject").OpenTextFile(SaveName, 2, true)
For i = 1 To lastRow
objectSheet.Activate
objectSheet.Cells(i, 1).Select
strString = ""
For j = 1 To lastColumn
If j <> lastColumn Then
strString = strString & objectCells(i, j).Value & "|" ' Use ^ instead of pipe.
Else
strString = strString & objectCells(i, j).Value
End If
Next
outputFile.WriteLine(strString)
Next
objFileToWrite.Close
Set objFileToWrite = Nothing
Next
Set objWorkbook = Nothing
Set objExcel = Nothing
Set myFolder = Nothing
Set fileColl = Nothing
Set fso = Nothing
The only issue I have now is that the conversion takes a very long time. Does anyone have a suggestion on how to speed this up, or does the nature of this just mean it's going to be slow?

creating a VBScript to grab fonts from fileserver

I'm trying to create a VBS script that will grab all the fonts from the server font location so that the domain user will have the ability to use them. When I run this script I get a line 15 char 1 error: 800A400C.
Not sure what is wrong with it or if this script will do the job I'm wanting it to do.
'On Error Resume Next
'Option Explicit
Dim objShell, objFSO, wshShell
Dim strFontSourcePath, objFolder, objFont, objNameSpace, objFile, strFontsSytem
Set objShell = CreateObject("Shell.Application")
Set wshShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FilesyStemObject")
strFontSourcePath = "\\server\Fonts\"
strFontsSytem = WSHShell.SpecialFolders("Fonts") & "\"
Set objNameSpace = objShell.Namespace(strFontSourcePath)
Set objFolder = objFSO.GetFolder(strFontSourcePath)
For Each objFile In objFolder.Files
If LCase(Right(objFile, 4)) = ".ttf" Or LCase(Right(objFile, 4)) = ".otf" Then
Set objFont = objNameSpace.ParseName(objFile.Name)
If objFSO.FileExists(strFontsSytem & objFile.Name) = False Then
objFont.InvokeVerb("Install")
Set objFont = Nothing
End If
End If
Next
Set objShell = Nothing
Set wshShell = Nothing
Set objFSO = Nothing
Set objNameSpace = Nothing
Set objFolder = Nothing
WScript.Quit
Error code 800A004C means Path not found. Please check the existance of the strFontSourcePath and like Ansgar says also check if the user running this code has access to this share.
Anyway, Here's my code to copy and install fonts from a server share if that is any help
Call AddFonts("\\server\Fonts\")
WScript.Quit
Private Sub AddFonts(strFromPath)
' install fonts from a server location if not already present
Dim appShell, objShell, objFSO, colFiles, objFile, objFolder
Dim strToPath, flags, strFile, strExt
'SpecialFolder. See: https://technet.microsoft.com/en-us/library/ee176604.aspx
Const FONTFOLDER = &H14&
'CopyHere switches
Const FOF_MULTIDESTFILES = &H1&
Const FOF_CONFIRMMOUSE = &H2&
Const FOF_SILENT = &H4&
Const FOF_RENAMEONCOLLISION = &H8&
Const FOF_NOCONFIRMATION = &H10&
Const FOF_WANTMAPPINGHANDLE = &H20&
Const FOF_ALLOWUNDO = &H40&
Const FOF_FILESONLY = &H80&
Const FOF_SIMPLEPROGRESS = &H100&
Const FOF_NOCONFIRMMKDIR = &H200&
Const FOF_NOERRORUI = &H400&
Const FOF_NOCOPYSECURITYATTRIBS = &H800&
Const FOF_NORECURSION = &H1000&
Const FOF_NO_CONNECTED_ELEMENTS = &H2000&
Const FOF_WANTNUKEWARNING = &H4000&
On Error Resume Next
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = Createobject("Wscript.Shell")
Set appShell = CreateObject("Shell.Application")
'create an object for the systems fonts folder
Set objFolder = appShell.Namespace(FONTFOLDER)
'make sure these paths end in a backslash
strFromPath = FixPath(strFromPath)
'get the name of the system fonts folder (C:\WINDOWS\Fonts)
strToPath = FixPath(objShell.SpecialFolders("Fonts"))
'set flags to install as quiet as possible.
flags = FOF_SILENT Or FOF_NOCONFIRMATION Or FOF_NOERRORUI Or _
FOF_NOCONFIRMMKDIR Or FOF_NOCOPYSECURITYATTRIBS
If (Not objFolder Is Nothing) Then
If objFSO.FolderExists(strFromPath) Then
Set colFiles = objFSO.GetFolder(strFromPath).Files
If colFiles.Count > 0 Then
For Each objFile In colFiles
strExt = objFSO.GetExtensionName(objFile.Name)
Select Case LCase(strExt)
Case "ttf", "otf" ' can also be used for "fon", "pfm", "pfb", "afm"
'get the complete path and filename for this font file and check if already there
strFile = strToPath & objFile.Name
If Not (objFSO.FileExists(strFile)) Then
objFolder.CopyHere strFromPath & objFile.Name, flags
End If
End Select
Next
End If
End If
End If
'cleanup objects
Set appShell = Nothing
Set colFiles = Nothing
Set objFile = Nothing
Set objFolder = Nothing
Set objFSO = Nothing
Set objShell = Nothing
End Sub
Private Function FixPath(sPath)
'small helper function to ensure a path ends in a backslash
If Len(sPath) > 0 And Right(sPath, 1) <> "\" Then
FixPath = sPath & "\"
Else
FixPath = sPath
End If
End Function

Asking for a little assistance with cleanup and error

I have been given a task of creating a script that takes a log file (date is in the filename), pulls the data and posts it in event manager. I have a script that works as it should I know the script is ugly so please be gentle. I'm looking for 2 things.
some days nothing has happened and no log for the day was created. when this happens my script causes all kinds of slowness in the PC. I need help with a way for the script to not do its task if no new file has been added to the logs folder.
I would like a little help cleaning up the script.
Like i said i'm very new to this and i used scripts found on the web and fit them to do what i needed them to do.
any help would be greatly appricated.
Option Explicit
Const ForReading = 1
Dim strfolder
Dim FSO
Dim FLD
Dim fil
Dim strOldName
Dim strNewName
Dim strFileParts
Dim objShell
Dim objFSO
Dim objFolder
Dim strFileName
Dim objFile
Dim objTextFile
Dim strNextLine
Dim arrServiceList
Dim i
strFolder = "C:\Logs\"
Set objShell = CreateObject ("Wscript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.Namespace(strFolder)
Set objShell = CreateObject ("Wscript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile ("C:\Logs\logCatchAll.log", ForReading)
For Each strFileName in objFolder.Items
If len(objFSO.GetExtensionName(strFileName)) > 0 Then
Set objFile = objFSO.GetFile(strFolder & strFileName.Name)
If DateDiff("H",objFile.DateLastModified,Now()) > 24 Then
objFSO.DeleteFile(strFolder & strFileName.Name),True
End If
End If
next
Set FSO = CreateObject("Scripting.FileSystemObject")
Set FLD = FSO.GetFolder(strfolder)
For Each fil in FLD.Files
strOldName = fil.Path
If InStr(strOldName, "-") > 0 Then
strFileParts = Split(strOldName, "-")
strNewName = strFileParts(0) & ".log"
FSO.MoveFile strOldName, strNewName
End If
Next
Set FLD = Nothing
Set FSO = Nothing
Do Until objTextFile.AtEndOfStream
strNextLine = objTextFile.Readline
arrServiceList = Split(strNextLine , ",")
For i = 3 to Ubound(arrServiceList)
objshell.LogEvent 4, arrServiceList(i)
Loop
You can block your Dim'd variables
You are reactivating the objShell to many times
You have a for loop at the bottom of your code without a Next statement.
You don't need to iterate through the log file until it reaches AtEndOfStream, just store it in a variable first.
You can use the same objFSO more than once if your not resetting the object.
You need to include error handling so you know where your code breaks.
Revised code.
Option Explicit
'Handle errors manually.
On Error Resume Next
'Set Constants
Const ForReading = 1
'Set Strings
Dim strFolder, strOldName, strNewName, strFileName, strFileParts, strNextLine, TFStrings
strFolder = "C:\Logs\"
'Set Objects
Dim objShell, objFSO, objFolder, objFile, objTextFile
Set objShell = CreateObject ("Wscript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objShell.Namespace(strFolder)
TFStrings = split(objFSO.OpenTextFile("C:\Logs\logCatchAll.log", ForReading).ReadAll, vbcrlf)
'Set Other Variables
Dim FLD, fil, arrServiceList, i, executed
executed = false
'Delete file procedure...
For Each strFileName in objFolder.Items
If len(objFSO.GetExtensionName(strFileName)) > 0 Then
Set objFile = objFSO.GetFile(strFolder & strFileName.Name)
If DateDiff("H",objFile.DateLastModified,Now()) > 24 Then
objFSO.DeleteFile(strFolder & strFileName.Name),True
executed = true
End If
End If
Next
If executed then
If err.number <> 0 then
'File was found, but delete was unsuccessful, log failure of delete.
executed = false
err.clear
Else
'Delete file procedure executed successfully. Lets move on.
executed = false
End If
Else
'No file was found within the conditions. log failure of search.
End if
'Move file and rename procedure...
Set FLD = objFSO.GetFolder(strfolder)
For Each fil in FLD.Files
strOldName = fil.Path
If InStr(strOldName, "-") > 0 Then
strFileParts = Split(strOldName, "-")
strNewName = strFileParts(0) & ".log"
objFSO.MoveFile strOldName, strNewName
executed = true
End If
Next
Set FLD = Nothing
Set FSO = Nothing
If executed then
If err.number <> 0 then
'File was found, but move was unsuccessful, log failure of move.
executed = false
err.clear
Else
'Move file procedure executed successfully. Lets move on.
executed = false
End If
Else
'No file was found within the conditions. log failure of search.
End if
For Each line in TFStrings
strNextLine = line
arrServiceList = Split(strNextLine , ",")
For i = 3 to Ubound(arrServiceList)
objshell.LogEvent 4, arrServiceList(i)
Next
Next

Modifying multiple text files with VBScript

i need help with this VBScript
What I'm trying to do here is modify the logfile to remove the extra spaces inside. (I just got this script actually somewhere on the net.)
It works if i specify just a single file but I'm trying to modify multiple files. Using the wildcard character as i did below did not work either (sorry I'm not so good with vbs)
Also does anyone know how we can do this without creating a new output file? just modify the original file. Thanks in advance..
Set objFSO = CreateObject("Scripting.FileSystemObject")
'change this line to wherever you want to read the input from.
Set objTextFile = objFSO.OpenTextFile("D:\access*.log",1)
Set objNewFile = objFSO.CreateTextFile("D:\access*_new.log")
Do Until objTextFile.AtEndOfStream
myString = objTextFile.Readline
objNewFile.WriteLine(Replace (myString, " ", " "))
Loop
In addition to my comment: The Scripting Guy explains exactly your replacement case: multiple spaces by one, with a regular expression:
Set objRegEx = CreateObject("VBScript.RegExp")
objRegEx.Global = True
objRegEx.Pattern = " {2,}"
strSearchString = _
"Myer Ken, Vice President, Sales and Services"
strNewString = objRegEx.Replace(strSearchString," ")
Wscript.Echo strNewString
The Scripting Guy also explains how you can change a text file:
Const ForReading = 1
Const ForWriting = 2
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\Scripts\Text.txt", ForReading)
strText = objFile.ReadAll
objFile.Close
strNewText = Replace(strText, "Jim ", "James ")
Set objFile = objFSO.OpenTextFile("C:\Scripts\Text.txt", ForWriting)
objFile.WriteLine strNewText
objFile.Close
And on the same technet.microsoft you can find how you can easily iterate over all files. You can use a regular expression again to see if the file is matching your (wildcard) pattern, in your case ^access.*\.log$:
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder("C:\FSO")
Set colFiles = objFolder.Files
For Each objFile in colFiles
Wscript.Echo objFile.Name, objFile.Size
Next
This should give you all the ingredients to create your script.
The freeze-dried version:
Const ForReading = 1
Const ForWriting = 2
Dim goFS : Set goFS = CreateObject("Scripting.FileSystemObject")
Dim reZap : Set reZap = New RegExp
reZap.Global = True
reZap.Pattern = " +"
Dim oFile
For Each oFile In goFS.GetFolder("..\testdata\14620676").Files
WScript.Echo "----", oFile.Name
Dim sAll : sAll = oFile.OpenAsTextStream(ForReading).ReadAll()
WScript.Echo sAll
oFile.OpenAsTextStream(ForWriting).Write reZap.Replace(sAll, " ")
WScript.Echo oFile.OpenAsTextStream(ForReading).ReadAll()
Next
that makes no sense at all without #AutomatedChaos' admirable contribution (+1), but avoids growing the file's tail by using .Write instead of .WriteLine.

Resources