Check if a string contains specific characters using VBS script - vbscript

My script is doing the following point :
Retrieve all my selected folder files
Class them by date (From the recent one to the older)
Show them in a window
Here is my VBS Script (I retrieve it here):
Option Explicit
Const PathMDB = "C:\Users\C8461789\Desktop\test_script"
MsgBox TriRepertoire,,"Enumération " & PathMDB
'---lister les fichiers du répertoire ---
Function TriRepertoire()
Dim fso, fichier, fileItem
Dim i, imax, z, valeur, cible, liste
Set fso = CreateObject("Scripting.FileSystemObject")
imax = 0
'début de l'énumération
For Each fichier In fso.GetFolder(PathMDB).Files
Set fileItem = fso.GetFile(fichier)
imax = imax + 1
ReDim Preserve Tableau(2, imax)
Tableau(1, imax) = Fichier.Name
Tableau(2, imax) = FileItem.DateLastModified
'---trier les fichiers par ordre décroissant de création ---
Do
Valeur = 0
For i = 1 To imax - 1
If InStr(Tableau(1,i), "average", vbTextCompare) > 0 Then
If CDate(Tableau(2, i)) < CDate(Tableau(2, i + 1)) Then
For z = 1 To 2
Cible = Tableau(z, i)
Tableau(z, i) = Tableau(z, i + 1)
Tableau(z, i + 1) = Cible
Next
Valeur = 1
End If
End If
Next
Loop While Valeur = 1
Set fileItem = nothing
Next
'Affichage du résultat classé
For i = 1 To imax
'If IsNull(Tableau) Then
liste = liste &vbTab& Tableau(1, i) &vbCr
'End If
Next
TriRepertoire = liste
Set fso = nothing
End Function
In order to filter by name my retrieved files, I would like to add the following condition :
For each file name, if it contains "average", add the file name to the table
Else, do nothing
I tried to use
If InStr(Tableau(1,i), "average", vbTextCompare) > 0 Then
But it shows me this error :

You are using InStr incorrectly. Your code:
InStr(Tableau(1,i), "average", vbTextCompare)
The signature for InStr is:
InStr([start,]string1,string2[,compare])
But the gotcha here is that it has two optional parameters, one of them being in the front, with a special condition:
Optional. Specifies the starting position for each search. The search begins at the first character position (1) by default. This parameter is required if compare is specified
So because you are using the fourth parameter with the value vbTextCompare, you need to specify the starting point in the first parameter as well, which would be 1 (first character) in your case. So, the corrected code is:
InStr(1, Tableau(1,i), "average", vbTextCompare)
The error message you see basically complains that the first parameter is expected to be an integer, but you are feeding it a string.
See InStr docs.

Related

Count Items in file using VB

Kind of new to VBS. I'm trying to count the fields in the file and have this code.
Col()
Function Col()
Const FSpec = "C:\test.txt"
Const del = ","
dim fs : Set fs = CreateObject("Scripting.FileSystemObject")
dim f : Set f = fs.OpenTextFile(FSpec, 1)
Dim L, C
Do Until f.AtEndOfStream
L = f.ReadLine()
C = UBound(Split(L, del))
C = C +1
WScript.Echo "Items:", C
Loop
f.Close
End Function
It works however, I don't want to count the delim inside " ".
Here's file content:
1,"2,999",3
So basically, I'm getting 4 items for now but I wanted to get 3. Kind of stuck here.
For an example of my second suggestion, a very simple example could be something like this. Not saying it is perfect, but it illustrates the idea:
Dim WeAreInsideQuotes 'global flag
Function RemoveQuotedCommas(ByVal line)
Dim i
Dim result
Dim current
For i = 1 To Len(line)
current = Mid(line, i, 1) 'examine character
'check if we encountered a quote
If current = Chr(34) Then
WeAreInsideQuotes = Not WeAreInsideQuotes 'toggle flag
End If
'process the character
If Not (current = Chr(44) And WeAreInsideQuotes) Then 'skip if comma and insode quotes
result = result & current
End If
Next
RemoveQuotedCommas = result
End Function

Vbs - File Cont \ File Delete

I am creating a guy script read files in a folder, (Scripting.FileSystemObject), but I would like to relate a indice inpubox type int to determine which file in the folder I'll write on the screen.
Ex: indice = inputbox "" ← 4 grab the indice file in the folder 4 and esquever your name on the screen.
  I wonder if this is possible because already tried in many ways and even by matrix, but without result.
This and my code. I do not know but where to go!
Dim sFO, NovaPasta, Folder,File, Indice
Dim inpast(4)
'Setup
Set sFO = CreateObject("Scripting.FileSystemObject")
Set Folder = sFo.GetFolder("C:\Users\502526523\Documents\Control")
NovaPasta = "Control"
'Development
If Not sFO.FolderExists (NovaPasta) = True Then
sFO.CreateFolder (NovaPasta)
Wscript.Sleep 900
WScript.Echo "Pasta Criada"
Else
WScript.Echo "Pasta Existente "
End If
' Line Verificas a quantidade de inpastas dentro da pasta, se > 5
' deleta os exedentes com data mais antiga
For Each file In folder.Files
If Folder.Files.Count > 5 And (DateDiff("d", file.DateLastModified, Now) > 7) Then
WScript.Echo (file.Name & vbLf)
WScript.Echo ("Total files :" & Folder.Files.Count)
File.Delete
End If
Next
For Each file In folder.Files
inpast(0) = (file.Name)
inpast(1) = (file.Name)
inpast(2) = (file.Name)
inpast(3) = (file.Name)
inpast(4) = (file.Name)
Indice = Inputbox ("Digite o valor do Indice de 0...30")
Select Case Indice
Case 0
WScript.Echo inpast(0)
Case 1
WScript.Echo inpast(1)
Case 2
WScript.Echo inpast(2)
Case 3
WScript.Echo inpast(3)
Case 4
WScript.Echo inpast(4)
End Select
Next
Still not sure if I understand your question correctly. You mean you have a list of filenames and you want to display the filename corresponding to the number the user entered via an InputBox? If that's what you want you should change your second For Each loop like this:
i = 0
For Each file In folder.Files
inpast(i) = file.Name
i = i + 1
Next
Indice = InputBox("Digite o valor do Indice de 0...30")
WScript.Echo inpast(CInt(Indice))
Note, however, that the condition in your first For Each loop does not guarantee you'll only ever have 5 files left after the loop. If for some reason the folder contains more than 5 files that were modified within the past 7 days the second loop would fail with a "subscript out of range" error.
There are several ways you could handle this:
Dynamically resize the inpast array so it can hold more than 5 items.
Sort the files in the folder by last modification date (e.g. like this) and delete everything except the 5 most recent files.
Cut off the second For Each loop after the 5th iteration (Exit For).
Note also, that you should sanitize your input. (What happens when users enter text, an invalid number, or press "Cancel"?)
Set fso = CreateObject("Scripting.FileSystemObject")
Dirname = InputBox("Enter Dir name")
'Searchterm = Inputbox("Enter search term")
ProcessFolder DirName
Sub ProcessFolder(FolderPath)
' On Error Resume Next
Set fldr = fso.GetFolder(FolderPath)
msgbox fls.count
Msgbox fls.item("computerlist.txt")
End Sub
To do the 7th
Set Fls = fldr.files
For Each thing in Fls
Count = Count + 1
If count = 7 then msgbox Thing.Name & " " & Thing.DateLastModified
Next

How do I find a repeating set of cells in Excel?

I Have a 2100 Rows and 6 Columns Table
Throughout the table there are only 12 Possible values, say A,B,C,D,E,F,G,H,I,J,K,L
The 12th value L is just a blank filler. It denotes blank cell.
Since there are only 11 possible values througout the table, patterns are observed.
First a Pattern Appears and it is later repeated somewhere in the table.
There can be any number of Patterns, but i have a specific format for a pattern which is to found and reported that way.
Solutions in EXCEL-VBA, PHP-MYSQL or C are welcome.
I have attached an example of what Iam looking for. Suggestions are most welcome to refine
the questions.
Information & Format : http://ge.tt/8QkQJet1/v/0 [ DOCX File 234 KB ]
Example in Excel Sheet : http://ge.tt/69htuNt1/v/0 [ XLSX File 16 KB ]
Please comment for more information or specific requirement.
Please try the code below, change the range to what you need it to be and the sheet number to the correct sheet number (I wouldn't put your full range in just yet because if you have 1000 pattern finds, you'll have to click OK on the message box 1000 times, just test with a partial range)
This will scan through the range, and find any pattern of two within a 10 row range, if you need it to find bigger patterns, youll need to add the same code again with an extra IF statement checking the next offset.
This will only find it if the same pattern exists and the same column structure is present, but its a start for you
Works fine on testing
Sub test10()
Dim rCell As Range
Dim rRng As Range
Set rRng = Sheets("Sheet1").Range("A1:I60") '-1 on column due to offset
'Scan through all cells in range and find pattern
For Each rCell In rRng.Cells
If rCell.Value = "" Then GoTo skip
For i = 1 To 10
If rCell.Value = rCell.Offset(i, 0).Value Then
If rCell.Offset(0, 1).Value = rCell.Offset(i, 1) Then
MsgBox "Match Found at: " & rCell.Address & ":" & rCell.Offset(0, 1).Address & " and " & rCell.Offset(i, 0).Address & ":" & rCell.Offset(i, 1).Address
End If
End If
Next i
skip:
Next rCell
End Sub
***UPDATE***
I have updated my code, the following now finds the pattern wherever it may appear in the next 10 rows:
Sub test10()
Dim rCell As Range
Dim rRng As Range
Dim r1 As Range
Dim r2 As Range
Set rRng = Sheets("Sheet1").Range("A1:I50") '-1 on column due to offset
i = 1 'row length
y = 0 'column length
'Scan through all cells in range and find pattern
For Each rCell In rRng.Cells
If rCell.Value = "" Then GoTo skip
i = 1
Do Until i = 10
y = 0
Do Until y = 10
xcell = rCell.Value & rCell.Offset(0, 1).Value
Set r1 = Range(rCell, rCell.Offset(0, 1))
r1.Select
ycell = rCell.Offset(i, y).Value & rCell.Offset(i, y + 1).Value
Set r2 = Range(rCell.Offset(i, y), rCell.Offset(i, y + 1))
If ycell = xcell Then
Union(r1, r2).Font.Bold = True
Union(r1, r2).Font.Italic = True
Union(r1, r2).Font.Color = &HFF&
MsgBox "Match Found at: " & rCell.Address & ":" & rCell.Offset(0, 1).Address & " and " & rCell.Offset(i, y).Address & ":" & rCell.Offset(i, y + 1).Address
Union(r1, r2).Font.Bold = False
Union(r1, r2).Font.Italic = False
Union(r1, r2).Font.Color = &H0&
End If
y = y + 1
Loop
i = i + 1
Loop
skip:
Next rCell
End Sub

vbs execute another vbs script with dictionary as parameter

i am trying to execute a vbscript from another vbscript. The think is, i have to pass a dictionary as parameter, but i always get the same error message.
Here is my code so far:
dim objShell
Set objShell = Wscript.CreateObject("WScript.Shell")
dim dicExp
Set dicExp = CreateObject("Scripting.Dictionary")
dic.add 0, 10
objShell.Run "C:\Users\groeschm\Desktop\ODBCAktuell.vbs " & dicString
But i always get this error message:
Error 800A01C2 - Wrong number of arguments of invalid property assignment.
Greetings,
Michael
You cannot pass an object reference to WScript.Shell.Run. See http://msdn.microsoft.com/en-us/library/d5fk67ky(v=vs.84).aspx, it says the command line argument is a string, and nothing else.
You cannot pass a Scripting.Dictionary reference, nor can you encode that reference into the string argument.
It´s as simple as that!
And even if you could, this would be useless because the called VBS does not share the same global scope as the caller code.
You should consider alternatives to Run. You could put the ODBCAktuell.vbs code into a function, and call that instead. Or you consider ExecuteFile or one of the related intrinsics.
(Without knowing what ODBCAktuell.vbs contains, and without knowing what exactly you are trying to accomplish, it is difficult to advise you further than that.)
There is a similar question based on the same brainbug: Create instance for a class(resides in B.vbs) from another .VBS file
The OT's code is messed up. dicString is undefined. It does not throw the error claimed, but an "Object Required", because the dictionary is named dicExp, not dic.
While TheBlastOne is right to state that you can't pass anything except strings via the command line, the wish to communicate other (more complex) types of data is legitimate. Making numbers or dates from command line args is standard procedure. And: wanting to re-use code via some kind of import/using/include mechanism isn't a brainbug but essential for good programming.
A general approach to serialisation (via strings) is JSON, but it's not easy to use it in VBScript (cf).
The starting point(s) for a 'roll your own' approach for simple cases (dictionaries with numbers/scalars/simple strings as keys and values) is trivial:
Stringify:
cscript passdic.vbs
cscript recdic.vbs "1 2 3 4"
1 => 2
3 => 4
passdic.vbs:
Option Explicit
Function d2s(d)
ReDim a(2 * d.Count - 1)
Dim i : i = 0
Dim k
For Each k In d.Keys()
a(i) = k
i = i + 1
a(i) = d(k)
i = i + 1
Next
d2s = Join(a)
End Function
Function qq(s)
qq = """" & s & """"
End Function
Dim d : Set d = CreateObject("Scripting.Dictionary")
d(1) = 2
d(3) = 4
Dim c : c = "cscript recdic.vbs " & qq(d2s(d))
WScript.Echo c
Dim p : Set p = CreateObject("WScript.Shell").Exec(c)
WScript.Echo p.Stdout.ReadAll()
recdic.vbs:
Option Explicit
Function s2d(s)
Set s2d = CreateObject("Scripting.Dictionary")
Dim a : a = Split(s)
Dim i
For i = 0 To UBound(a) Step 2
s2d.Add a(i), a(i + 1)
Next
End Function
Dim d : Set d = s2d(WScript.Arguments(0))
Dim k
For Each k In d.Keys()
WScript.Echo k, "=>", d(k)
Next
Code re-use:
cscript passdic2.vbs
cscript recdic2.vbs
1 => 2
3 => 4
passdic2.vbs
Option Explicit
Function d2s(d)
ReDim a(d.Count - 1)
Dim i : i = 0
Dim k
For Each k In d.Keys()
a(i) = "cd.Add " & k & "," & d(k)
i = i + 1
Next
d2s = "Function cd():Set cd=CreateObject(""Scripting.Dictionary""):" & Join(a, ":") & ":End Function"
End Function
Dim d : Set d = CreateObject("Scripting.Dictionary")
d(1) = 2
d(3) = 4
CreateObject("Scripting.FileSystemObject").CreateTextFile("thedic.inc").Write d2s(d)
Dim c : c = "cscript recdic2.vbs"
WScript.Echo c
Dim p : Set p = CreateObject("WScript.Shell").Exec(c)
WScript.Echo p.Stdout.ReadAll()
thedic.inc
Function cd():Set cd=CreateObject("Scripting.Dictionary"):cd.Add 1,2:cd.Add 3,4:End Function
recdic2.vbs
Option Explicit
ExecuteGlobal CreateObject("Scripting.FileSystemObject").OpenTextFile("thedic.inc").ReadAll()
Dim d : Set d = cd()
Dim k
For Each k In d.Keys()
WScript.Echo k, "=>", d(k)
Next

Read Data from csv file using VB

This is the code i wrote in order to First open a csv file as excel, then find the required three columns, n then read data from them n save the data into another variables showing them in textbox. As about the csv file, it contains many columns out of which my focus is on only 3 columns under title ID, L, Lg.
Problem is Excel doesnt actually open but Excel.exe process runs in task manager.
But by this point its not the compile error; Compile error comes at 'Next' Statement. It says Compile Error: Next without For!!!!
I am Confused with this one. Please help me with this one, Thanks in Advance.
Private Sub cmdFind_Click()
Dim xlApp As Excel.Application
Set xlApp = New Excel.Application
Dim X As Double, Y As Double, FleetID As String
Dim F As String, FCol As Integer, LCol As Integer, LgCol As Integer, Srno As Integer, I As Integer
Dim xlWbook As Workbook
Dim xlSht As Excel.Worksheet
Set xlWbook = xlApp.Workbooks.Open("C:\Users\saurabhvyas\Desktop\test VB2\testfile.csv")
xlApp.Visible = True
Set xlSht = xlWbook.Worksheets("sheet1")
For I = 1 To 8 Step 1
If xlSht.Cells(I, 1).Value = "ID" Then
FCol = I
Else
If xlSht.Cells(I, 1).Value = "L" Then
LCol = I
Else
If xlSht.Cells(I, 1).Value = "Lg" Then
LgCol = I
End If
Next I
Set Srno = 2
Do
If xlSht.Cells(FCol, Srno).Value = Str$(txtF.Text) Then
Set X = xlSht.Cells(LCol, Srno).Value
Set Y = xlSht.Cells(LgCol, Srno).Value
End If
Srno = Srno + 1
Loop While xlSht.Cells(FCol, Srno).Value = vbNullString
txtL.Text = Str$(X)
txtLg.Text = Str$(Y)
xlWbook.Close
xlApp.Quit
Excel.Application.Close
Set xlSht = Nothing
Set xlWbook = Nothing
Set xlApp = Nothing
End Sub
You can open CSV format text files and operate on them using ADO with the Jet Provider's Text IISAM. Much less clunky than automating Excel. Or you can read the lines as text and Split() them on commas.
What you're doing does open Excel, but you haven't asked Excel to be visible... though I have no idea why you'd want that.
What are you really trying to do?
As for your compile error, that's because you are missing some End Ifs.
Write it as:
For I = 1 To 8 Step 1
If xlSht.Cells(I, 1).Value = "ID" Then
FCol = I
Else
If xlSht.Cells(I, 1).Value = "L" Then
LCol = I
Else
If xlSht.Cells(I, 1).Value = "Lg" Then
LgCol = I
End If
End If
End If
Next I
Or as:
For I = 1 To 8 Step 1
If xlSht.Cells(I, 1).Value = "ID" Then
FCol = I
ElseIf xlSht.Cells(I, 1).Value = "L" Then
LCol = I
ElseIf xlSht.Cells(I, 1).Value = "Lg" Then
LgCol = I
End If
Next I

Resources