Search list of strings in txt file via excel - excel

I have many txt files in my folder. I have also have a list of their names in column 1, i need to search separate 1 string in each files which are listed in column 2. If such txt is found then it should say "Found" or else not found.
i was trying to modify below code based on my requirement but i unable to do it as its giving me the error for which i don't know the solution.
Sub SearchTextFile()
Dim FName, SName As String
Raise = 2
Do While Raise <> ""
FName = Cells(Raise, 1)
SName = Cells(Raise, 2)
Const strFileName = "Y:\New folder\" & FName & ".txt"
Const strSearch = SName
Dim strLine As String
Dim f As Integer
Dim lngLine As Long
Dim blnFound As Boolean
f = FreeFile
Open strFileName For Input As #f
Do While Not EOF(f)
lngLine = lngLine + 1
Line Input #f, strLine
If InStr(1, strLine, strSearch, vbBinaryCompare) > 0 Then
Cells(Raise, 3).Value = "Found"
blnFound = True
Exit Do
End If
Loop
Close #f
If Not blnFound Then
Cells(Raise, 3).Value = "Not Found"
End If
Raise = Raise + 1
Loop
End Sub

Try this modification
Sub Search_Text_Files()
Dim b As Boolean
Dim sName As String
Dim sSrch As String
Dim strFile As String
Dim sLine As String
Dim f As Integer
Dim r As Long
Dim l As Long
r = 2
Do While Cells(r, 1) <> ""
sName = Cells(r, 1)
sSrch = Cells(r, 2)
strFile = "Y:\New folder\" & sName & ".txt"
b = False
f = FreeFile
Open strFile For Input As #f
Do While Not EOF(f)
l = l + 1
Line Input #f, sLine
If InStr(1, sLine, sSrch, vbBinaryCompare) > 0 Then
Cells(r, 3).Value = "Found"
b = True: Exit Do
End If
Loop
Close #f
If Not b Then Cells(r, 3).Value = "Not Found"
r = r + 1
Loop
End Sub

Related

I can't run VBA Macro on all workbooks inside a folder

I just started working with VBA.
I have a VBA code that counts the number of the occurence of words inside the excel file. It works fine.
I want to run this VBA macro on all files I have inside a specific folder.
Could you help me out?
My code below:
I am getting values right only for the file from which I ran the macro. For the rest of the files, the reults obtained are wrong
Sub LoopThroughFiles()
Dim xFd As FileDialog
Dim xFdItem As Variant
Dim xFileName As String
Set xFd = Application.FileDialog(msoFileDialogFolderPicker)
If xFd.Show = -1 Then
xFdItem = xFd.SelectedItems(1) & Application.PathSeparator
xFileName = Dir(xFdItem & "*.xls*")
Do While xFileName <> ""
With Workbooks.Open(xFdItem & xFileName)
Dim wordList As New Collection
Dim keyList As New Collection
Dim c
Worksheets("Sheet1").Activate
Dim RangeToCheck As Range
Set RangeToCheck = Range("A1:A1000")
For Each c In RangeToCheck
Dim words As Variant
words = Split(c, " ")
For Each w In words
Dim temp
temp = -1
On Error Resume Next
temp = wordList(w)
On Error GoTo 0
If temp = -1 Then
wordList.Add 1, Key:=w
keyList.Add w, Key:=w
Else
wordList.Remove (w)
keyList.Remove (w)
wordList.Add temp + 1, w
keyList.Add w, Key:=w
End If
Next w
Next c
Dim x
Dim k
k = 1
For x = 1 To wordList.Count
With Sheets("Sheet1")
.Cells(k, "E").Value = keyList(x)
.Cells(k, "F").Value = wordList(x)
k = k + 1
End If
End With
Next x
End With
xFileName = Dir
Loop
End If
End Sub
Try this
Public Sub LoopThroughFiles()
Dim xFd As FileDialog
Set xFd = Application.FileDialog(msoFileDialogFolderPicker)
xFd.AllowMultiSelect = False
If xFd.Show <> -1 Then
MsgBox "No Folder selected": Exit Sub
End If
Dim Folder As String: Folder = xFd.SelectedItems(1) & "\"
Dim Files
Files = Dir(Folder & "*.xls*")
Dim Xls As String
On Error Resume Next
Dim CrWB As Workbook, CrSheet As Worksheet
Dim ClnW As New Collection, ClnC As New Collection
Dim Cols As Integer: Cols = 1
Do While Files <> ""
Xls = Replace(Folder & Files, "\\", "\")
Set CrWB = Application.Workbooks.Open(Xls, , True)
Set CrSheet = CrWB.Sheets("Sheet1")
If Err.Number > 0 Then
MsgBox "Can't open File " & Xls & vbCrLf & Err.Description
Err.Clear
GoTo 1
End If
Dim c As Range
Set ClnW = New Collection: Set ClnC = New Collection
For Each c In CrSheet.Range("A1:A1000")
If c.Value <> "" Then
Words = Split(CStr(c.Value), " ", , vbTextCompare)
For Each s In Words
Err.Clear
tmp = ClnW(s)
If Err.Number > 0 Then
ClnW.Add Item:=s, Key:=s
ClnC.Add Item:=1, Key:=s
Else
x = ClnC(s) + 1
ClnC.Remove s
ClnC.Add Item:=x, Key:=s
End If
Next
End If
Next
Set CrSheet = ThisWorkbook.Sheets("Sheet1")
With CrSheet
.Cells(1, Cols).Value = Files
.Cells(2, Cols).Value = "Word"
.Cells(2, Cols + 1).Value = "Occurance"
.Range(.Cells(1, Cols), .Cells(1, Cols + 1)).Merge
Dim I As Integer: I = 3
For Each s In ClnW
.Cells(I, Cols).Value = s
.Cells(I, Cols + 1).Value = ClnC(s)
I = I + 1
Next
End With
Cols = Cols + 2
1
CrWB.Close False
Files = Dir()
Err.Clear
Loop
End Sub

How to Automatically Open Text File: Find, Copy Data, and Paste

So I'm trying to automate a task that involves opening a whole folder of .ist documents that are similar and paste the data. I already have code that allows me to click each item but I'm trying to make this task completely automatic. I'm pretty new at this. I have experience coding in C but I've been coding vba for only a week.
So here's what I have:
This is the code that works
Sub Figureitout()
Dim fileName As Variant, text(1 To 890) As String, textline As String
Dim num As Integer
Dim strDir As String, fso As Object, objFiles As Object, obj As Object, fileCount As Integer
Dim myFile As Variant
Dim posTorque As Integer, posOffset As Integer
'specify folder path
strDir = "C:\Users\Desktop\Folder\"
'create filesystemobj
Set fso = CreateObject("Scripting.FileSystemObject")
'get the folder
Set objFiles = fso.GetFolder(strDir).Files
'count all the files
fileCount = objFiles.Count
'Total number of files in folder
MsgBox fileCount
'read file name
'fileName = Dir(strDir)
'MsgBox fileName
'counter intitialize
num = 1
Do Until num = fileCount
'choose file
myFile = Application.GetOpenFilename("Text Files(*.IST),*.ist", , , , False)
'open file
Open myFile For Input As #num
'copy file contents
Do Until EOF(num)
Line Input #(num), textline
text(num) = text(num) & textline
Loop
'find data
posTorque = InStr(text(num), "Torque:")
posOffset = InStr(text(num), "Offset:")
'close file
Close #num
'make sure offset value exists in document
If InStr(text(num), "Offset:") <> 0 Then
'paste data
Range("A" & num).Value = Mid(text(num), posTorque + 12, 4)
Range("B" & num).Value = Mid(text(num), posOffset + 13, 4)
End If
'delete chosen file
Kill (myFile)
'increment prior to loop
num = num + 1
'Reset data
posTorque = 0
posOffset = 0
Loop
End Sub
So I'm thinking about having something that is like:
For Each fileName in fileCount
FileName = "Dir(strDir)"
Open fileName for Input As #num
but I keep getting type mismatch errors. I'm assuming that's because fileName is a string in this scenario?
Tips? Tricks? Advice?
No need to store the complete text from all the files in an array, just check each lines as you read it.
Sub ProcessFiles()
Const FOLDER = "C:\Users\Desktop\Folder\"
Dim ws As Worksheet
Dim sFilename As String, textline As String
Dim i As Integer, ff As Integer, p As Integer, count As Long
sFilename = Dir(FOLDER & "*.ist") ' first file
Set ws = ActiveSheet
i = 0
Do While Len(sFilename) > 0
ff = FreeFile
i = i + 1
Open FOLDER & sFilename For Input As #ff
Do Until EOF(ff)
Line Input #ff, textline
p = InStr(textline, "Torque:")
If p > 0 Then
ws.Range("A" & i).Value = Mid(textline, p + 12, 4)
End If
p = InStr(textline, "Offset:")
If p > 0 Then
Range("B" & i).Value = Mid(textline, p + 13, 4)
End If
Loop
Close ff
sFilename = Dir ' get next
count = count + 1
Loop
MsgBox count & " files proccessed in " & FOLDER, vbInformation
End Sub

Display search text in text file with VBA Excel

I am new to VB and have a problem.
I have a text file named data.txt. It has 1 lines in it
IamanewstudentHeisanewstudentthestudentinthisclassisveryfunnythisuniversityhave300studentthestudentisveryfriendlywithnewcommer
I write a script which reads this text file and look for the string such as "stutent" and print all the "student" we can found in cell in excel (B1,C1,D1....). In this example we have 5 "student". It will display in cell B1,C1,D1,E1,F1 in sheet.
I tried till this point but it just give me only one "student" not five.
Sub SearchTextFile()
Const strFileName = "C:\data.txt"
Const strSearch = "student"
Dim strLine As String
Dim f As Integer
Dim lngLine As Long
Dim blnFound As Boolean
Dim lPosition As Long
f = FreeFile
Open strFileName For Input As #f
Do While Not EOF(f)
lngLine = lngLine + 1
Line Input #f, strLine
If InStr(1, strLine, strSearch, vbBinaryCompare) > 0 Then
blnFound = True
lPosition = InStr(1, strLine, strSearch, vbTextCompare)
MsgBox "Search string found" & strSearch, vbInformation
Exit Do
End If
Loop
Close #f
If Not blnFound Then
MsgBox "Search string not found", vbInformation
End If
End Sub
I would use RegEx to count the number of occurences in the line with the following function
Function noInStr(line As String, pattern As String) As Long
Dim regEx As Object, matches As Object
Set regEx = CreateObject("vbscript.regexp")
With regEx
.MultiLine = False
.Global = True
.IgnoreCase = True
.pattern = pattern
End With
Set matches = regEx.Execute(line)
noInStr = matches.count
End Function
You could use it in your code like that
Sub SearchTextFile()
Const strFileName = "C:\data.txt"
Const strSearch = "student"
Dim strLine As String
Dim f As Integer
Dim lngLine As Long
Dim blnFound As Boolean
Dim lPosition As Long
f = FreeFile
Open strFileName For Input As #f
Do While Not EOF(f)
lngLine = lngLine + 1
Line Input #f, strLine
Dim count As Long
count = noInStr(strLine, strSearch)
If count > 0 Then
blnFound = True
MsgBox "Search string found " & count & "- times: " & strSearch, vbInformation
Exit Do
End If
Loop
Close #f
If Not blnFound Then
MsgBox "Search string not found", vbInformation
End If
End Sub
If you also need the positions you could retrieve them with RegEx, too.
Update: This is how you could also retrieve the positions
Function colInStr(line As String, pattern As String) As Collection
Dim regEx As Object, matches As Object
Set regEx = CreateObject("vbscript.regexp")
With regEx
.MultiLine = False
.Global = True
.IgnoreCase = True
.pattern = pattern
End With
Set matches = regEx.Execute(line)
Dim col As New Collection
Dim i As Long
For i = 0 To matches.count - 1
col.Add matches(i).FirstIndex
Next i
Set colInStr = col
End Function
You also need to modify your code, below only the relevant part
Dim count As Long, col As Collection
Set col = colInStr(strLine, strSearch)
count = col.count
If count > 0 Then
blnFound = True
MsgBox "Search string found " & count & "- times: " & strSearch, vbInformation
Exit Do
End If
The positions are stored in the collection.
This will help find all the student strings and their right positions. I have commented my changes. I run the test using your file
Sub SearchTextFile()
Const strFileName = "C:\data.txt"
Const strSearch = "student"
Const strReplaceSearch = "tneduts"
Dim strLine As String
Dim f As Integer
Dim lngLine As Long
Dim blnFound As Boolean
Dim lPosition As Long
f = FreeFile
Open strFileName For Input As #f
Do While Not EOF(f)
lngLine = lngLine + 1
Line Input #f, strLine
'' For every line retreived, loop for all occurences of student
Do While (InStr(1, strLine, strSearch, vbBinaryCompare) > 0)
blnFound = True
lPosition = InStr(1, strLine, strSearch, vbTextCompare)
MsgBox "Search string found" & strSearch, vbInformation
'' remove the string student found and search for the next, we replace the word student with tneduts, that helps us keep the lPosition right
strLine = Replace(strLine, strSearch, strReplaceSearch, 1, 1)
Loop
Loop
Close #f
If Not blnFound Then
MsgBox "Search string not found", vbInformation
End If
End Sub

Creating array with Split generates Type Mismatch error

I have an inventory list for tools. The point of this program is to search for tools based on tool number entered and based on tool information to locate the corresponding tool file in the specific folder. The name of the files contain part of the tool information.
I loop through the inventory list first, once locating a specific tool, retriving corresponding information and trying to match with the file names within the folder. Here I created another loop to go through the files.
Sub openBaseline(tn)
Dim objFSO As Object
Dim objFolder As Object
Dim objFile As Object
Dim intpath As String
Dim path As String
Dim pn As String
Dim ps As String
Dim varr()
Dim partnum As String
Dim toolsize As String
Dim toolnumber As String
Dim i As Integer
'Testing If Me.idBox.Value = "" And Me.beadBox.Value = "" And Me.partBox.Value = "" Then Exit Sub
If tn = "" Then tn = InputBox("Scan or enter tool number.", "Load Baseline", "")
If tn = "" Then Exit Sub
'If Right(Left(tn, 2), 1) <> "-" Then
'If Len(tn) = 5 Then
'tn = Left(tn, 1) & "-" & Right(tn, 4)
'Else:
'MsgBox "Tool numbers should be in the format of '1-1234'", vbOKOnly + vbExclamation, "Error"
'Exit Sub
'End If
'End If
toolnumber = tn
'Debug.Print toolnumber
With ThisWorkbook.Sheets("Tool Log")
intpath = "H:\PROCESS\PROCESS SAMPLES\SI-Baselines\JSP" 'Switch to \woodbridge.corp etc
Set objFSO = CreateObject("Scripting.Filesystemobject")
Set objFolder = objFSO.getfolder(intpath)
'For Each objFile In objFolder.Files
'varr = Split(objFile.Name, " ")
'ReDim Preserve filename(objFolder.Files.count, 2)
For i = 2 To .Cells(Rows.count, 1).End(xlUp).row Step 1
'Debug.Print .Cells(Rows.count, 1).End(xlUp).row
Debug.Print .Cells(i, "A")
If .Cells(i, 1).Text = toolnumber Then
Debug.Print i
pn = .Cells(i, 3).Value
ps = .Cells(i, 4).Value
Debug.Print pn
Debug.Print ps
End If
'i = 1
For Each objFile In objFolder.Files
Debug.Print objFile.Name
'Debug.Print objFile.path
varr() = Split(objFile.Name, " ")
partnum = varr(0)
toolsize = varr(1)
Debug.Print partnum
Debug.Print toolsize
path = objFile.Name
'Does not work for family tools
Select Case toolsize
Case Is = ps
If partnum = pn Then
Workbooks.Open filename:=objFile.path, UpdateLinks:=False, ReadOnly:=True
Exit For
End If
Case Is = Right(varr(1), Len(varr(1)) - 1)
If partnum = pn Then
Workbooks.Open filename:=objFile.path, UpdateLinks:=False, ReadOnly:=True
Exit For
End If
End Select
Next objFile
'And toolsize = Right(ps, Len(ps) - 1) Then
'path = objFile.Name
'path = Right(path, Len(path) - Len(pn) - 1)
'If Left(path, Len(ps)) = ps Then
'Workbooks.Open filename:=objFile.path, UpdateLinks:=False, ReadOnly:=True
'Exit For
'End If
'End If
'i = i + 1
Next i
End With
End Sub
It gives a Type mismatch error on line
varr() = Split(objFile.Name, " ")
Declare you array variable as array of String (preferable) or as a single Variant, but not as an array of Variant
Also, you should omit the brackets when assigning the result of the split-command.
Dim varr() as String
' or: Dim varr as Variant
...
varr = Split(objFile.Name, " ")

modify macro to make it run faster

Who can help with this macro?
It's merging csv files into one.
csv files can be more than 500 and its running slow.
By the way it's taiking all data in csv file (2 rows). it will work for me if macro can take just second row from file..
Any ideas?
Option Explicit
Sub ImportCSV65()
Dim strSourcePath As String
Dim strDestPath As String
Dim strFile As String
Dim strData As String
Dim x As Variant
Dim Cnt As Long
Dim r As Long
Dim c As Long
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
'Change the path to the source folder accordingly
strSourcePath = Worksheets("Tarpinis").Range("AJ8").Value
If Right(strSourcePath, 1) <> "\" Then strSourcePath = strSourcePath & "\"
strFile = Dir(strSourcePath & "*.csv")
Sheets("+65").Select
Application.ScreenUpdating = False
Do While Len(strFile) > 0
Cnt = Cnt + 1
If Cnt = 1 Then
r = 1
Else
r = Cells(Rows.Count, "A").End(xlUp).Row + 1
End If
Open strSourcePath & strFile For Input As #1
If Cnt > 1 Then
Line Input #1, strData
End If
Do Until EOF(1)
Line Input #1, strData
x = Split(strData, ",")
For c = 0 To UBound(x)
Cells(r, c + 1).Value = Trim(x(c))
Next c
r = r + 1
Loop
Close #1
Name strSourcePath & strFile As strSourcePath & strFile
strFile = Dir
Loop
Application.ScreenUpdating = True
If Cnt = 0 Then _
MsgBox "No CSV files were found...", vbExclamation
Application.ScreenUpdating = False
End Sub
How about the following, it will read the second line from each CSV file in the given folder and write that line in the Sheet +65:
Option Explicit
Sub ImportCSV65()
Dim strSourcePath As String
Dim strDestPath As String
Dim strFile As String
Dim strData As String
Dim x As Variant
Dim Cnt As Long
Dim r As Long
Dim c As Long
Dim counter As Long
Dim ws As Worksheet: Set ws = Sheets("+65")
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
counter = 0
'Change the path to the source folder accordingly
strSourcePath = Worksheets("Tarpinis").Range("AJ8").Value
If Right(strSourcePath, 1) <> "\" Then strSourcePath = strSourcePath & "\"
strFile = Dir(strSourcePath & "*.csv")
Do While Len(strFile) > 0
Open strSourcePath & strFile For Input As #1
Do Until EOF(1)
Line Input #1, strData
r = ws.Cells(Rows.Count, "A").End(xlUp).Row + 1
counter = counter + 1
If counter = 2 Then 'counter to get only second line
x = Split(strData, ",")
For c = 0 To UBound(x)
ws.Cells(r, c + 1).Value = Trim(x(c))
Next c
r = r + 1
Exit Do
End If
Loop
Close #1
Name strSourcePath & strFile As strSourcePath & strFile
strFile = Dir
counter = 0 'reset counter before next file
Loop
Application.ScreenUpdating = True
End Sub
The only obvious place that I can see that could be done better is the loop that writes the trimmed values into the cells.
If you must trim each value, then you'll still need to loop through the array and Trim it:
For c = 0 To UBound(x)
x(c) = Trim(x(c))
Next c
But to write to the cells, you can speed things up by writing the array directly to the range:
Cells(r, 1).Resize(1, UBound(x) + 1).Value = x
You might also gain a little bit of time by qualifying the destination sheet, preferably as a With.
So the whole thing would look like this:
Sub ImportCSV65()
Dim strSourcePath As String
Dim strDestPath As String
Dim strFile As String
Dim strData As String
Dim x As Variant
Dim Cnt As Long
Dim r As Long
Dim c As Long
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
'Change the path to the source folder accordingly
strSourcePath = Worksheets("Tarpinis").Range("AJ8").Value
If Right(strSourcePath, 1) <> "\" Then strSourcePath = strSourcePath & "\"
strFile = Dir(strSourcePath & "*.csv")
With Sheets("+65")
.Select
Application.ScreenUpdating = False
Do While Len(strFile) > 0
Cnt = Cnt + 1
If Cnt = 1 Then
r = 1
Else
r = .Cells(.Rows.Count, "A").End(xlUp).Row + 1
End If
Open strSourcePath & strFile For Input As #1
If Cnt > 1 Then
Line Input #1, strData
End If
Do Until EOF(1)
Line Input #1, strData
x = Split(strData, ",")
For c = 0 To UBound(x)
x(c) = Trim(x(c))
Next c
.Cells(r, 1).Resize(1, UBound(x) + 1).Value = x
r = r + 1
Loop
Close #1
Name strSourcePath & strFile As strSourcePath & strFile
strFile = Dir
Loop
End With
Application.ScreenUpdating = True
If Cnt = 0 Then _
MsgBox "No CSV files were found...", vbExclamation
Application.ScreenUpdating = False
End Sub
Workbooks.Open Filename:=strSourcePath & strFile, Format:=2
This code will open csv file as excel type.
And get data as variant vlaue and will fill your sheet by variant value.
Sub ImportCSV65()
Dim strSourcePath As String
Dim strDestPath As String
Dim strFile As String
Dim strData As String
Dim Ws As Worksheet, rngT As Range
Application.Calculation = xlCalculationManual
Application.ScreenUpdating = False
'Change the path to the source folder accordingly
strSourcePath = Worksheets("Tarpinis").Range("AJ8").Value
If Right(strSourcePath, 1) <> "\" Then strSourcePath = strSourcePath & "\"
strFile = Dir(strSourcePath & "*.csv")
Set Ws = Sheets("+65")
Application.ScreenUpdating = False
With Ws
Do While Len(strFile) > 0
Workbooks.Open Filename:=strSourcePath & strFile, Format:=2
With ActiveWorkbook.ActiveSheet
vDB = .UsedRange
End With
ActiveWorkbook.Close
Set rngT = .Range("a" & Rows.Count).End(xlUp)(2)
rngT.Resize(UBound(vDB, 1), UBound(vDB, 2)) = vDB
strFile = Dir
Loop
End With
Application.ScreenUpdating = False
End Sub

Resources