I am using dictonary in VBscript. I have some problems that I don't understand some of the behaviour:
Dim CmdData
Set CmdData = CreateObject("System.Dictonary")
CmdData.Add "11", "tttzz"
CmdData.Add "sssid", "KRN"
WScript.Echo(" ZZZZZZZZ= " & CmdData.Count) 'It prints zero and not 2
Dim s
s = CmdData.Item("11")
alert(s)
WScript.Echo(s) 'It prints empry box and not tttzz
Dim a, j
a = CmdData.Keys
For j = 0 To CmdData.Count -1
WScript.Echo(" ZZZZZZZZ= " & CmdData.Count)
WScript.Echo(a(j)) ' doesn not print
Next
If (CmdData.Exists("-ad")) Then
'WScript.Echo (" RR ") ' It prints it although not in the dictonary
End If
Thanks
VBScript's Dictionary is "Scripting.Dictionary":
>> set syd = CreateObject("System.Dictionary")
>> syd.add "a",1
>>
Error Number: 429
Error Description: ActiveX component can't create object
>> set scd = CreateObject("Scripting.Dictionary")
>> scd.add "a",1
>> WScript.Echo scd.Count, scd("a")
>>
1 1
Related
This is what I have:
Dim pathBefore
pathBefore = "product/subproduct/item/item"
This is what I need to get from pathBefore:
Dim pathAfter
pathAfter = "product/subproduct/item"
What I can do to achieve this?
I have tried with RegEx but it is not acceptable solution.
#Gurman:
>> s = "product/subproduct/item/item"
>> a = Split(s, "/")
>> ReDim Preserve a(UBound(a) - 1)
>> WScript.Echo Join(a, "/")
>> WScript.Echo goFS.GetParentFolderName(s)
>> WScript.Echo Left(s, InstrRev(s, "/") - 1)
>>
product/subproduct/item
product/subproduct/item
product/subproduct/item
Try this code:
Dim pathBefore, pathAfter, temp, i
pathBefore = "product/subproduct/item/item"
temp = Split(pathBefore,"/")
For i=0 To UBound(temp)-1
pathAfter = pathAfter & temp(i) & "/"
Next
pathAfter = Left(pathAfter,Len(pathAfter)-1)
MsgBox pathAfter
Output:
Find the last / then read upto that point - 1
pathAfter = left$(pathBefore, instrrev(pathBefore, "/") - 1)
The script below works in finding duplicates.
But most of the files i'm reading follow this format:
ServerName(1) = "Example1"
ServerName(2) = "Example1"
ServerName(3) = "Example3"
ServerName(4) = "Example4"
ServerName(5) = "Example5"
The 'cut' variable in the code below is supposed to cut the string at the "=" delimiter and return the value that comes after the "=" delimeter.
It should write to the duplicate file "Example1" but instead writes nothing. How would I make it so that the script below reads a file and only finds the duplicate in values after the "=" delimeter.
Const ForReading = 1
Const ForWriting = 2
Set objFSO = CreateObject("Scripting.FileSystemObject")
FileName = "Test.txt"
PathToSave = "C:"
Path = (PathToSave & FileName)
Set objFile = objFSO.OpenTextFile(Path, ForReading)
Set objOutputFile = objFSO.OpenTextFile(PathToSave & "Noduplicates.txt", 2, True)
Set objOutputFile2 = objFSO.OpenTextFile(PathToSave & "Duplicates.txt", 2, True)
objOutputFile.WriteLine ("This document contains the " & path & " file without duplicates" & vbcrlf)
objOutputFile2.WriteLine ("This document contains the duplicates found. Each line listed below had a duplicate in " & Path & vbcrlf)
Dim DuplicateCount
DuplicateCount = 0
Set Dict = CreateObject("Scripting.Dictionary")
Do until objFile.atEndOfStream
strCurrentLine = LCase(Trim(objFile.ReadLine))
Cut = Split(strCurrentline,"=")
If not Dict.Exists(LCase(Trim(cut(strCurrentLine)))) then
objOutputFile.WriteLine strCurrentLine
Dict.Add strCurrentLine,strCurrentLine
Else Dict.Exists(LCase(Trim(cut(strCurrentLine))))
objOutputFile2.WriteLine strCurrentLine
DuplicateCount = DuplicateCount + 1
End if
Loop
If DuplicateCount > 0 then
wscript.echo ("Number of Duplicates Found: " & DuplicateCount)
Else
wscript.echo "No Duplicates found"
End if
Cut is your array, so Cut(1) is the portion after the =. So that's what you should test for in your dictionary.
If InStr(strCurrentline, "=") > 0 Then
Cut = Split(strCurrentline,"=")
If Not Dict.Exists(Cut(1)) then
objOutputFile.WriteLine strCurrentLine
Dict.Add Cut(1), Cut(1)
Else
objOutputFile2.WriteLine strCurrentLine
DuplicateCount = DuplicateCount + 1
End if
End If
I makes no sense at all to ask Split to return an array with one element by setting the 3rd parameter to 1, as in
Cut = Split(strCurrentline,"=",1)
Evidence:
>> WScript.Echo Join(Split("a=b", "=", 1), "*")
>>
a=b
>> WScript.Echo Join(Split("a=b", "="), "*")
>>
a*b
BTW: ServerName(5) = "Example5" should be splitted on " = "; further thought about the quotes may be advisable.
Update wrt comments (and downvotes):
The semantics of the count parameter according to the docs:
count
Optional. Number of substrings to be returned; -1 indicates that all substrings are returned. If omitted, all substrings are returned.
Asking for one element (not an UBound!) results in one element containing the input.
Evidence wrt the type mismatch error:
>> cut = Split("a=b", "=", 1)
>> WScript.Echo cut
>>
Error Number: 13
Error Description: Type mismatch
>>
So please think twice.
this is the example.
what if the array should be from Mynum1="1" to MyNum100="100"
MyNum1="1"
MyNum2="2"
MyNum3="3"
wat is the best way to declare this.
To iterate through a 100 of these:
Dim myNum(99)
for i = 0 to 99
myNum(i) = i+1
next
for i = 0 to 99
wscript.echo i & " - " & myNum(i)
next
Declare it as an Array:
MyNums = Array("1", "2", "3")
You can access each one with:
foo = MyNums(1)
Which will assign foo to "2".
Technically it is feasible, but it is a very bad practice. You can execute code that is created on the fly with the Execute statement:
Dim i
for i = 1 to 100
Execute "Dim myNum" & i & " : myNum" & i & " = """ & i & """"
' Creates and executes strings like: Dim myNum1 : myNum1 = "1"
next
Again, don't do this if there is any other way, like the use of an array as DesertIvy and ServerGuy showed you.
Set objReadFile = objFSO.OpenTextFile(objFile.Path, ForReading)
strAll = Split(objReadFile.ReadAll, vbCrLf, -1, vbTextCompare) 'Gets each line from file
i = LBound(strAll)
Do While i < UBound(strAll)
If (InStr(1, strAll(i), "DAU SNo.-C0", vbTextCompare) > 0) Then
i = i + 4 'Skip 4 lines to get to first SN
Do Until InStr(1, strAll(i), "+", vbTextCompare) > 0 'Loop until line includes "+"
strSNO = Split(strAll(i), "|", -1, vbTextCompare)
'put strSNO into next cell in column A
**objSheet.Cells.Offset(1,0).Value = Trim(strSNO(1))**
i = i + 1
Loop
End If
i = i + 1
Loop
This code splits a text file successfully and puts the two values I want in strSNO(1) and strSNO(2). I want to write them into column A row 2 and column B row 2, then put the next value in row 3 in the next iteration of the loop. I tried the offset method and it gave errors. All the help I am finding is for VBA. Can anyone tell me what to put where the code is in bold to fix it?
EDIT:
Solved it.This is what I did:
strAll = Split(objReadFile.ReadAll, vbCrLf, -1, vbTextCompare) 'Gets each line from file
i = LBound(strAll)
c=2
Do While i < UBound(strAll)
If (InStr(1, strAll(i), "DAU SNo.-C0", vbTextCompare) > 0) Then
i = i + 4 'Skip 4 lines to get to first SN
Do Until InStr(1, strAll(i), "+", vbTextCompare) > 0 'Loop until line includes "+"
strSNO = Split(strAll(i), "|", -1, vbTextCompare)
i = i + 1
objSheet.Cells(c,1).Offset(1,0).Value = Trim(strSNO(1))
objSheet.Cells(c,2).Offset(1,0).Value = Trim(strSNO(2))
c=c+1
Loop
End If
i = i + 1
Loop
Replace
objSheet.Cells.Offset(1,0).Value = Trim(strSNO(1))
with
objSheet.Cells(i,1).Value = Trim(strSNO(1))
objSheet.Cells(i,2).Value = Trim(strSNO(2))
Edit: Are you certain you want the fields 1 and 2 of strSNO? VBScript arrays are 0-based, so the first index is 0, not 1.
To locate an error add some debugging code:
On Error Resume Next
objSheet.Cells(i,1).Value = Trim(strSNO(1))
If Err Then
WScript.Echo i & ": " & strAll(i)
WScript.Echo "strSNO(1) = " & strSNO(1)
WScript.Echo "strSNO(1) is of type " & TypeName(strSNO(1))
End If
Err.Clear
objSheet.Cells(i,2).Value = Trim(strSNO(2))
If Err Then
WScript.Echo i & ": " & strAll(i)
WScript.Echo "strSNO(2) = " & strSNO(2)
WScript.Echo "strSNO(2) is of type " & TypeName(strSNO(2))
End If
On Error Goto 0
If the problem turns out to be that strAll(i) doesn't contain a | for some i, so the Split() produces an array with just one element, you can work around that by something like this:
strSNO = Split(strAll(i) & "|", "|", -1, vbTextCompare)
Can you please tell me why I am getting the following error?
VBScript runtime error: This array is fixed or temporarily locked: 'temp'
This is the code that is generating the error. I am unsure of how to resolve it.
I am just trying to unpack a file that is in DRY folder and move it to ACS folder.
Thank you very much
Set FSO = CreateObject("Scripting.FileSystemObject")
Set fldr = FSO.GetFolder("C:\Ebooks\DRY\")
For Each fil In fldr.Files
If LCase( Right( fil.Name, 4 ) ) = ".zip" Then
zipFilePath = fil.Path
temp = file.Name
temp = Left( temp, LEN(temp) - 4 ) ' remove the .zip
temp = Split( temp, "_" ) ' split base name away from month-day-year
temp = temp( UBOUND(temp) ) ' get just month-day-year
temp = Split( temp, "-" ) ' get month day and year separately
mn = CINT(temp(0)) ' get the month number
dirName = MonthName(mn,True) & temp(2) ' True means get 3 letter abbrev for month
Response.Write "Unpacking " & fil.Name & " to directory " & dirName & "<br/>" & vbNewLine
objZip.UnPack zipFilePath, "D:\ACS\" & dirName & "\"
End If
Next
This is caused by:
temp = temp(ubound(temp))
and can be fixed by:
temp = (temp(ubound(temp)))
While you can assign to/overwrite an array variable with arbitrary values:
>> a = Array(1)
>> b = Array(2)
>> a = b
>> b = 4711
>> WScript.Echo Join(a), b
>>
2 4711
you can't assign an array element to the variable holding the array itself:
>> a = a(0)
>>
Error Number: 10
Error Description: This array is fixed or temporarily locked
>> a = Array(Array(1), Array(2))
>> a = a(1)
>>
Error Number: 10
Error Description: This array is fixed or temporarily locked
So re/mis-using the temp variable is one cause of your problem. The difference between "fil" and "file" will bite you next.
After reading Alex K's answer, I realise that you can avoid that error 10. I think that the outer () are 'pass me per value' parentheses, that create a copy ov the original array before the then harmless assignment. But I still believe that using proper variable names and not re-using variables is a better way.