Replace Third line of each file inside a folder with second line using Macros - vba

I am using the below VBA code to replace few words in all the files inside one folder.in the same VBA code is it possible to copy the third line of each file and replace it with the second line.
Sub ReplaceStringInFile1()
Dim objFSO As Object, objFil As Object, objFil2 As Object
Dim StrFileName As String, StrFolder As String, strAll As String, newFileText As String
Set objFSO = CreateObject("scripting.filesystemobject")
StrFolder = "I:\Documents\ABC\AZ\"
StrFileName = Dir(StrFolder & "*.txt")
Do While StrFileName <> vbNullString
Set objFil = objFSO.opentextfile(StrFolder & StrFileName)
strAll = objFil.readall
objFil.Close
Set objFil2 = objFSO.createtextfile(StrFolder & StrFileName)
'change this to that in text
newFileText = Replace(strAll, "To:", "FROM")
'change from to to in text
newFileText = Replace(newFileText, "THIS", "THAT")
'write file with new text
'change from to to in text
newFileText = Replace(newFileText, "IS", "WAS")
'write file with new text
objFil2.Write newFileText
objFil2.Close
StrFileName = Dir
Loop
End Sub

I will tell you logic and use the logic accordingly and come up with the code if you got any issues.
Open Each Text file ForReading and read each line one by one using ReadLine and Check for end of stream using AtEndOfStream. Copy each line in one string but skip the second the line. Something like this
Do While Obj.AtEndOfStream <> True
Str = Obj.ReadLine
if i = 2 Then
Str = ""
Else
StrF = StrF & Vbcrlf & Str
End If
i = i + 1
Loop
Now Open the Text File ForWritingReplace the old text in files Using Obj.Write StrF and Close the file. Do the loop for all files in the folder.
Hope This Helps :)

Related

Can't write to zip File if using a string or variant in Shell.Application Copyhere

I am having troubles with NameSpace CopyHere function. I am trying to create a zip file containing a bunch of logs. I can create the zip file just fine, but when using the NameSpace.CopyHere, if I use a string or a variant containing a string, it won't write the file to the zip archive.
For example, I have a file located at P:\test2.txt .
If I use those lines :
objApp.Namespace(sZipArchive).CopyHere sFile
objApp.Namespace(sZipArchive).CopyHere vLogs(i)
where sFile = vLogs(i) = "P:\test2.txt
the file test2.txt won't be copied in the zip archive.
However, if I use this line :
objApp.Namespace(sZipArchive).CopyHere "P:\test2.txt"
Then, the file gets copied in the zip file.
If I put a check to see if the sFile or vLog(i) is = "P:\test2.txt", I can see that they are the same thing.
Is there something I am missing here on why the first 2 lines don't work, but the third one does?
Thank you for your time.
Full sub :
Private Sub BtnSaveToZip_Click()
Dim bEndRow, bTest As Boolean
Dim iRow, iCount As Integer
Dim sZipArchive, sDate, sFolderExists, sFile As String
Dim vLogs, vFilename As Variant
Dim objApp As Object
sDate = Date
sDate = Replace(sDate, "/", "") ' set date format to DDMMYYYY instead of DD/MM/YYYY
sZipArchive = LblLogArchive + "\" + sDate
sFolderExists = Dir(sZipArchive)
If sFolderExists = "" Then
CreateDir (sZipArchive) ' if the subfolder with the date does not exists, create it
End If
sZipArchive = sZipArchive + "\" + wsContacts.Range("B7").Value + " Logs_" + sDate + ".zip"
'Check if file is open
If FileLocked(sZipArchive) Then
MsgBox sZipArchive + " already open. Please close the archive."
Exit Sub
End If
'Creating the zip file from Ron de Bruin
NewZip (sZipArchive)
'filling the zip file
Set objApp = CreateObject("Shell.Application")
bEndRow = False
iRow = gFirstData
Do While bEndRow = False
If Not IsEmpty(wsLogs.Cells(iRow, gTestCase).Value) Then
If Not IsEmpty(wsLogs.Cells(iRow, gLog).Value) Then
vLogs = Split(wsLogs.Cells(iRow, gLog).Value, ";")
For i = 0 To UBound(vLogs) - 1
sFile = vLogs(i) ' Debug only
If sFile = "P:\test2.txt" Then 'Debug only
objApp.Namespace(sZipArchive).CopyHere vLogs(i) ' if I put "P:\test2.txt", it works correctly
'Keep script waiting 5s for debug purpose
Application.Wait (Now + TimeValue("00:00:05"))
End If
Next
End If
iRow = iRow + 1
Else
bEndRow = True
End If
Loop
MsgBox "Zip successfully created"
Set objApp = Nothing
End Sub
If this works
objApp.Namespace(sZipArchive).CopyHere "P:\test2.txt"
and sFile and vLogs(i) appears to be the same as P:\test2.txt then I believe it could be a leading or trailing space problem. Try this
objApp.Namespace(sZipArchive).CopyHere Trim(sFile)
or
objApp.Namespace(sZipArchive).CopyHere Trim(vLogs(i))
The other way to check if sFile and vLogs(i) contains a valid path is by using DIR
One more way of debugging is to step through your code and then type this in the Immediate window
?=vLogs(i)="P:\test2.txt"
?=sFile="P:\test2.txt"
You should get a true in both cases. If you don't then there is your problem :)

Find a file in folder using different keywords VBA

I am a new to VBA. My issue is that I have a file that will be updated it into a specific folder by different users. Now everytime a user updates the file, the name of the file might not be the samefolder. However, I can narrow it down using specific keywords. I have been able to search for a file using a keyword but not multiple keywords. Please can you point me in the right direction on how I can use multiple keywords to find a file in a folder? Is it possible to write code that will work like the below?
Sub Start_countries()
Dim keyword, pathname, filename As String
pathname = "C:\XYZ\"
keyword = "lol" Or "rofl" Or "lmfao" Or "rotfl"
filename = Dir(pathname & "*.xls*")
Do While filename <> "*.xls*"
If LCase(filename) Like "*" & keyword & "*" Then
Set wb = Workbooks.Open(pathname & filename)
Find_count_sum_in_file filename
wb.Close SaveChanges:=True
Else
msgbox = "No file Found"
End If
Loop
End Sub
Try the following (adapted following your comment):
Private Const MAX_KWD = 5 ' use a constant to make sure everyone uses the same value
Sub Start_countries()
Dim keyword(1 To MAX_KWD), pathname As String
'Keywords for first file search
keyword(1) = "lol"
keyword(2) = "rofl"
keyword(3) = "lmfao"
keyword(4) = "rotfl"
pathname = "C:\XYZ1\"
search_for_files keyword(), pathname
'Keywords for second file search
keyword(1) = "omg"
keyword(2) = "fyi"
keyword(3) = "ok"
keyword(4) = "brb"
pathname = "C:\XYZ2\"
search_for_files keyword(), pathname
End Sub
Sub search_for_files(keyword(), pathname)
Dim filename As String, s As String
Dim i As Integer
filename = Dir(pathname & "*.xls*")
Do While InStr(filename, ".xls") <> 0
s = LCase(filename)
For i = 1 To MAX_KWD
If (InStr(s, keyword(i)) > 0) Then Exit For ' found!
Next i
If (i <= MAX_KWD) Then
Set WB = Workbooks.Open(pathname & filename)
Find_count_sum_in_file filename
WB.Close SaveChanges:=True
Else
MsgBox "No file Found"
End If
filename = Dir()
Loop
End Sub
Note that in Dim pathname, filename, s As String only s is declared as String; all others are declared as Variant (the As String does not apply to all variables declared on the line).
Note also that in your While filename <> "*.xls*" the test will be exact, i.e. it will look also for asterisks (*) in filename.

Passing a result from Dir to function, then trying to get next Dir result -- Getting invalid procedure call or argument

This code uses Dir to get sub-dirs. Each sub-dir needs to have its xls files processed. After it finishes processing the first batch of xls, I get invalid procedure call or argument. I am guessing when I pass dirLook to the function it creates a copy? Please assist. I need to move on to the next sub-dir.
dirLook = dir(strDir, vbDirectory)
Do While dirLook <> ""
If dirLook <> "." And dirLook <> ".." Then
If (GetAttr(strDir & adir) And vbDirectory) = vbDirectory Then
'Perform action on folder here
loopXls (dirLook)
Debug.Print dirLook
End If
End If
dirLook = dir
Loop
loopXls:
Function loopXls(dirStr As String)
Dim count As Integer
Dim strFilename As String
Dim strPath As String
Dim wbkTemp As Workbook
strPath = "C:\Users\pmevi\Documents\L7\L7_Master_Book\Input\" & dirStr & "\"
strFilename = dir(strPath & "*.xls")
Do While Len(strFilename) > 0
Set wbkTemp = Workbooks.Open(strPath & strFilename)
'
' do your code with the workbook
'
' save and close it
wbkTemp.Close True
count = count + 1
strFilename = dir
Loop
Debug.Print (count)
End Function
EDIT2
I am attemping to load each dir into an array, but for some reason when I loop through array I only see 3 folders instead of 5.
Dim dirs(5) As String
Dim i As Integer
Dim endNum As Integer
endNum = 4
dirLook = dir(strDir, vbDirectory)
For i = 0 To endNum
dirs(i) = dirLook
dirLook = dir
Next i
For i = 0 To endNum
Debug.Print (dirs(i))
Next i
output:
3-10-14
3-11-14
3-12-14
expected:
3-10-14
3-11-14
3-12-14
3-13-14
3-14-14
Edit3
Found issue to array. 2 indexes are used for "." and ".."
It's not exactly clear from the code, but if the code above is in the loopXls method, making this a recursive function then the problem is that you cannot use the Dir function recursively, as stated here, towards the bottom.
The answer here include shows an example class for recursing with the Dir function.

VBA Excel Function for returning file size in byte

I wish to return the file size of some files in the same folder or in a different one with VBA in Excel 2010.
There is a very nice and simple VBA function, which was not mentioned so far, FileLen:
FileLen("C:\Temp\test file.xls")
It returns the size of the file in bytes.
In combination with looping through files in a directory it's possible to achieve what you originally wanted (get sizes of files in a folder).
Here how to use it in Excel Cell:
=GetDirOrFileSize("C:\Users\xxx\Playground\","filename.xxx")
If you have a german Windows than:
=GetDirOrFileSize("C:\Users\xxx\Playground\";"filename.xxx")
Here is the function for the VBA modul: (Just enable the Developer tools, and copy and paste this into a new modul)
Function GetDirOrFileSize(strFolder As String, Optional strFile As Variant) As Long
'Call Sequence: GetDirOrFileSize("drive\path"[,"filename.ext"])
Dim lngFSize As Long, lngDSize As Long
Dim oFO As Object
Dim oFD As Object
Dim OFS As Object
lngFSize = 0
Set OFS = CreateObject("Scripting.FileSystemObject")
If strFolder = "" Then strFolder = ActiveWorkbook.path
If Right(strFolder, 1) <> "\" Then strFolder = strFolder & "\"
'Thanks to Jean-Francois Corbett, you can use also OFS.BuildPath(strFolder, strFile)
If OFS.FolderExists(strFolder) Then
If Not IsMissing(strFile) Then
If OFS.FileExists(strFolder & strFile) Then
Set oFO = OFS.Getfile(strFolder & strFile)
GetDirOrFileSize = oFO.Size
End If
Else
Set oFD = OFS.GetFolder(strFolder)
GetDirOrFileSize = oFD.Size
End If
End If
End Function '*** GetDirOrFileSize ***

How do I open a file if I only know part of the file name?

I need to open a file whose full filename I do not know.
I know the file name is something like.
filename*esy
I know definitely that there's only one occurrence of this file in the given directory.
filename*esy is already a "shell ready" wildcard & if thats alway the case you can simply;
const SOME_PATH as string = "c:\rootdir\"
...
Dim file As String
file = Dir$(SOME_PATH & "filename*esy" & ".*")
If (Len(file) > 0) Then
MsgBox "found " & file
End If
Just call (or loop until empty) file = Dir$() to get the next match.
There is an Application.FileSearch you can use (see below). You could use that to search for the files that match your pattern. This information taken from here.
Sub App_FileSearch_Example()
With Application.FileSearch
.NewSearch
.LookIn = "c:\some_folder\"
.FileName = "filename*esy"
If .Execute(SortBy:=msoSortByLastModified, SortOrder:=msoSortOrderDescending) > 0 Then
For i1 = 1 To .FoundFiles.Count
' do something with matched file(s)
Next i1
End If
End With
End Sub
If InStr(sFilename, "filename") > 0 and InStr(sFilename, "esy") > 0 Then
'do somthing
end if
Or you can use RegEx
Dim RE As Object, REMatches As Object
Set RE = CreateObject("vbscript.regexp")
With RE
.MultiLine = False
.Global = False
.IgnoreCase = True
.Pattern = "filename(.*)esy"
End With
Set REMatches = RE.Execute(sFilename)
REMatches(0) 'find match
I was trying this question as a function. This is the solution that ended up working for me.
Function fileName(path As String, sName As String, ext As String) As Variant
'path is Full path from root. Can also use path = ActiveWorkbook.path & "\"
'sName is the string to search. ? and * are wildcards. ? is for single char
'example sName = "book?" or sName ="March_*_2014*"
'ext is file extention ie .pdf .xlsm .xls? .j*
Dim file As Variant 'Store the next result of Dir
Dim fname() As String 'Dynamic Array for result set
ReDim fname(0 To 0)
Dim i As Integer ' Counter
i = 0
' Use dir to search and store first result
fname(i) = path & Dir(path & "\" & sName & ext)
i = i + 1
'Load next result
file = Dir
While file <> "" 'While a file is found store that file in the array
ReDim Preserve fname(0 To i) As String
fname(i) = path & file
file = Dir
Wend
fileName = Application.Transpose(fname) 'Print out array
End Function
This works for me as a single or array function.
If you know that no other file contains "filename" and "esy" in that order then you can simply use
Workbooks.Open Filename:= "Filepath\filename*esy.*"
Or if you know the number of missing characters then (assuming 4 characters unknown)
Workbooks.Open Filename:= "Filepath\filename????esy.*"
I use this method to run code on files which are date & timestamped to ignore the timestamp part.