I'm trying to figure out how to make multiple events happen with just one condition using .vbs. (Here I attempted to use the case statement.) Is there a such command, or do I have to rewrite the command for every line? (This is to be typed on notepad by having it already activated in previous lines of code.)
msgbox("I was woundering how old you are.")
age=inputbox("Type age here.",,"")
Select Case age
Case age>24
x=age-24
WshShell.SendKeys "I see you are "&x&" years older than me."
WshShell.SendKeys "{ENTER}"
Case age<24
x=24-age
WshShell.SendKeys "I see you are "&x&" years younger than me."
WshShell.SendKeys "{ENTER}"
Case age=24
WshShell.SendKeys "Wow were the same age!"
WshShell.SendKeys "{ENTER} "
End Select
I think you are looking for Select Case True, an enhanced use of the Select Case switch:
age = inputbox("I was wondering how old you are.")
Select Case True
' first handle incorrect input
Case (not IsNumeric(age))
WshShell.SendKeys "You silly, you have to enter a number.{ENTER}"
' You can combine cases with a comma:
Case (age<3), (age>120)
WshShell.SendKeys "No, no. I don't think that is correct.{ENTER}"
' Now evaluate correct cases
Case (age>24)
WshShell.SendKeys "I see you are " & age - 24 & " years older than me.{ENTER}"
Case (age<24)
WshShell.SendKeys "I see you are " & 24 - age &" years younger than me.{ENTER}"
Case (age=24)
WshShell.SendKeys "Wow were the same age!{ENTER}"
' Alternatively you can use the Case Else to capture all rest cases
Case Else
' But as all other cases handling the input this should never be reached for this snippet
WshShell.SendKeys "Woah, how do you get here? The Universe Collapse Sequence is now initiated.{ENTER}"
End Select
I put in some extra cases to show you the power of this enhanced switch. In contrary to If a And b Then statements, the cases with comma's are shortcircuited.
Encapsulate the redundant code in a procedure or function. Also a different control structure might be better suited for the kind of check you're applying:
If age>24 Then
TypeResponse "I see you are " & (age-24) & " years older than me."
ElseIf age<24 Then
TypeResponse "I see you are " & (24-age) & " years younger than me."
ElseIf age=24 Then
TypeResponse "Wow were the same age!"
End If
Sub TypeResponse(text)
WshShell.SendKeys text & "{ENTER}"
End Sub
Related
I am trying to export reminders data from the Reminders application. The script below will do so, but it takes a very long time (first iteration took 100 minutes, the second iteration is still running).
I have read that sending AppleEvents (in this case around 1000 of them) is what kills performance, but fixes are sparse (I have read about encapsulating the script inside script, end script, and run script but that did not seem to do anything).
A promising but tedious avenue I have not tried is to grab all ten columns separately and unix paste them together.
The real issue is of course looking up every cell of my table one-by-one. How can I just grab all objects (reminders) in rs with all of their detail, by value, and not just a list of references? Then I can parse it how I please.
#!/usr/bin/osascript
set output to "Title,Notes,Completed,Completion Date,List,Creation Date,Due Date,Modification Date,Remind Me Date,Priority\n"
tell application "Reminders"
set rs to reminders in application "Reminders"
repeat with r in rs
set output to output & "\"" & name of r & "\",\"" & body of r & "\",\"" & completed of r & "\",\"" & completion date of r & "\",\"" & name of container of r & "\",\"" & creation date of r & "\",\"" & due date of r & "\",\"" & modification date of r & "\",\"" & remind me date of r & "\",\"" & priority of r & "\"\n"
end repeat
end tell
return output
I'm about a year late, but perhaps someone else will find this solution useful. The trick is to store a reference to the reminders in the variable rs. That way, AppleScript is only having to go through every reminder once to retrieve its properties in the repeat loop.
use application "Reminders"
set text item delimiters of AppleScript to "|"
set output to {{"Title", "Notes", "Completed", "Completion Date", ¬
"List", "Creation Date", "Due Date", "Modification Date", ¬
"Remind Me Date", "Priority"} as text}
set rs to a reference to reminders
repeat with r in (a reference to reminders)
get {name, body, completed, completion date, ¬
name of container, creation date, due date, ¬
modification date, remind me date, priority} ¬
of r
set end of output to the result as text
end repeat
set text item delimiters of AppleScript to "\n"
return output as text
Alternatively, after defining the variable rs, one could get all the properties of all the reminders in one go like this:
set everything to the properties of rs
Then loop through this list instead:
repeat with r in everything
(* same as above *)
.
.
.
Part of a VBscript I'm writing inside of an HTA calls for the user to type a name into a text box which will generate a folder with that name. I am building checks into the script to make sure that no illegal characters or names are used. Where I am getting stuck at is trying to make sure that if a user enters COM1 or LPT1 they will be told that the name they tried to use is not allowed instead of getting a script error. The problem is I can't figure out how to do it without writing an If statement for every possible way the letters in COM1 through COM9 and LPT1 through LPT9 could be arranged in different cases (e.g. com1, Com1, cOm1, etc.). The code snippet below shows what I mean.
sFldrName = BasicTextbox.Value
sFldrBadMsg = "You've chosen an illegal folder name."
If sFldrname = "COM1" Then
Msgbox sFldrBadMsg
ElseIf sFldrname = "COM2" Then
Msgbox sFldrBadMsg
ElseIf sFldrname = "COM3" Then
Msgbox sFldrBadMsg
In the above example whatever the user enters into the text box is assigned to "sFldrname". Then the script checks whether the string assigned "sFldrname" is COM1 or COM2 or COM3. The problem is I can only check for those strings in the exact case specified. If the user enters COM1 they will get my warning message. But, if they enter com1 (all lower case) or CoM1 (mixed case) they will get a script error because it is still an illegal name regardless of case. In order to account for this with the method I used above I would have to do something like this:
sFldrName = BasicTextbox.Value
sFldrBadMsg = "You've chosen an illegal folder name."
If sFldrname = "COM1" Then
Msgbox sFldrBadMsg
ElseIf sFldrname = "Com1" Then
Msgbox sFldrBadMsg
ElseIf sFldrname = "COm1" Then
Msgbox sFldrBadMsg
ElseIf sFldrname = "cOm1" Then
Msgbox sFldrBadMsg
ElseIf sFldrname = "coM1" Then
Msgbox sFldrBadMsg
ElseIf sFldrname = "cOM1" Then
Msgbox sFldrBadMsg
ElseIf sFldrname = "CoM1" Then
Msgbox sFldrBadMsg
ElseIf sFldrname = "com1" Then
Msgbox sFldrBadMsg
And I would have to do that for COM2 through COM9 and LPT1 through LPT9 as well. I really don't want to have to do that. So, when I am checking the value of "sFldrname" to see what string it is, is there a way to ignore the case of that string? Or, is there a better way altogether to go about doing what I am trying to do? Thanks.
The canonical way, as others have already mentioned, is to uppercase (or lowercase) the value of the variable you want to compare:
If LCase(sFldrname) = "com1" Then
Msgbox sFldrBadMsg
ElseIf LCase(sFldrname) = "com2" Then
Msgbox sFldrBadMsg
ElseIf LCase(sFldrname) = "com3" Then
Msgbox sFldrBadMsg
End If
Using the StrComp function would be another option:
If StrComp(sFldrname, "COM1", vbTextCompare) = 0 Then
Msgbox sFldrBadMsg
ElseIf StrComp(sFldrname, "COM2", vbTextCompare) = 0 Then
Msgbox sFldrBadMsg
ElseIf StrComp(sFldrname, "COM3", vbTextCompare) = 0 Then
Msgbox sFldrBadMsg
End If
However, since you're doing an n-way comparison of the same variable, your best choice would probably be a Select statement in combination with UCase or LCase:
Select Case UCase(sFldrname)
Case "COM1", "COM2", "COM3" : MsgBox sFldrBadMsg
Case Else : MsgBox "OK"
End Select
Well, you could do something like:
If UCase(sFldrname) = "COM1" Then
Msgbox sFldrBadMsg
end if
That will uppercase your string, and then you can just compare the results with all uppercase. You are better off probably just looking for COM, and a colon. Now, for the BEST possible security,. and assurance that a path is correct, you want to look into something a little more serious, like Regular Expressions. Regular Expression can take the users input and test it for a valid "Path like" string.
Something like:
Dim RegEx, bFound
Set RegEx = New RegExp
RegEx.IgnoreCase = True
RegEx.Pattern = "^(?:\b((?#drive)[a-z]):\\((?#folder)[^/:*?""<>|\r\n]*\\)?((?#file)[^\\/:*?""<>|\r\n]*))$"
bFound = RegEx.Test(Data)
Will match when the users have entered a VALID drive, folder, and filename. Or, you use other iterations of the RegEx to test the matches. Keep in mind, you do not have to check for "COM1:", "LPT1:", etc, because the RegEx will not allow colons in the path, except at the very start for the drive letter...
Dim RegEx
Set RegEx = New RegExp
RegEx.IgnoreCase = True
RegEx.Pattern = "\b((?#drive)[a-z]):\\((?#folder)[^/:*?""<>|\r\n]*\\)?((?#file)[^\\/:*?""<>|\r\n]*)"
If RegEx.Test(sFldrname ) Then
' Successful match
Else
' Match attempt failed
End If
Now, lets just say that you want to test for DOS Device names in the input from the user. You can use a RegEx like the following to test for all combinations of COMn:, LPTn:, CON:, and NIL:. This RegEx, of course, requires that the input START with COM, LPT, CON, etc, if the string does not start with it, lets, say, for example, they typed in a directory name of Welcome, or heck, when WelCOM3: the RegEx would NOT match, indicating a clean path. If you want it to be able to search the ENTIRE input string for the appearance of COM{n}:, then remove the \b out of the pattern...
Dim RegEx
Set RegEx = New RegExp
RegEx.IgnoreCase = True
RegEx.Pattern = "\b(COM[0-9]+|LPT[0-9]+|CON|NIL)\:"
If RegEx.Test(sFldrname ) Then
' We discovered a DOS Device name as a PATH, and it is therefore invalid.
End If
Now, to address your actual, QUESTION, you'll note the RegEx.IGNORECASE = true. THAT is your ace in the hole there...
In my first example, I only showed you that as a lesson in how to do a case insensitive string comparison, something you will use OFTEN in writing just about any code in any language. I'm showing you the OTHER examples as more of a "proper" way, or an "easier" way, or a more "assured" way to search for bad things in a path. I think it's important that you look into something more solid, and much less code on your part, for a much more stable codebase. Since you are dealing with PATHS, which, as you know, is a serious ability for someone to enter path names that can put them in the wrong folder, (for example, entering a folder name like ..\..\..\..\..\..\Windows\System32\ now, they end up with a folder created in Windows System32, and depending on what your app does, this can be a SERIOUS security risk. So, don't just use the Regular Expressions I demonstrated. You an employ tactics like FORCING the starting directory to be your programs home directory, and eating any periods,back-slashes, and any other "path" chars, and force the directory to be created under your home dir. Hope this helps, sorry for the flood of data, but we've all been where you are!
Convert the input to uppercase, then compare to your uppercase forbidden string:
If uCase(sFldrname) = "COM1" Then
...
To avoid mistakes with the forbidden strings, uppercase them too:
If uCase(sFldrname) = uCase("COM1") Then
...
I am getting an "expected end of statement" error at line 26, the third to last line. If you look at the code, it is a simple game that has one person enter a word, the script replaces all consonants with underscores, and the second player has to guess the word. Line 26 is, I think, the only thing wrong with this program.
phrase=inputbox("Player 1: Enter a phrase","Guessing Game")
phrase=answer
phrase=Replace(phrase,"A","_")
phrase=Replace(phrase,"B","_")
phrase=Replace(phrase,"C","_")
phrase=Replace(phrase,"D","_")
phrase=Replace(phrase,"F","_")
phrase=Replace(phrase,"G","_")
phrase=Replace(phrase,"H","_")
phrase=Replace(phrase,"J","_")
phrase=Replace(phrase,"K","_")
phrase=Replace(phrase,"L","_")
phrase=Replace(phrase,"M","_")
phrase=Replace(phrase,"N","_")
phrase=Replace(phrase,"P","_")
phrase=Replace(phrase,"Q","_")
phrase=Replace(phrase,"R","_")
phrase=Replace(phrase,"S","_")
phrase=Replace(phrase,"T","_")
phrase=Replace(phrase,"V","_")
phrase=Replace(phrase,"W","_")
phrase=Replace(phrase,"X","_")
phrase=Replace(phrase,"Y","_")
phrase=Replace(phrase,"Z","_")
Do
result=InputBox "Player 2 enter your guess for" & phrase , "Guessing Game"
Loop until result==answer
msgbox "You got it!",vbokonly,"Guessing Game"
In VBScript, the 'equal' comparison operator is =. So change
Loop until result==answer
==>
Loop until result = answer
You're getting that error, because you used a function in an assignment without putting its parameter list in parentheses. Change this line:
result=InputBox "Player 2 enter your guess for" & phrase , "Guessing Game"
into this:
result=InputBox("Player 2 enter your guess for" & phrase , "Guessing Game")
This is one of VBScript's gotchas: depending on where/how you call a procedure or function, you must or mustn't put the parameter list in parentheses.
>>> String 3, "*" 'must not use parentheses here
>>> String(3, "*")
Cannot use parentheses when calling a Sub (0x414)
>>> Call String(3, "*") 'must use parentheses here
>>> Call String 3, "*"
Expected end of statement (0x401)
>>> v = String(3, "*") 'must use parentheses here either
>>> v = String 3, "*"
Expected end of statement (0x401)
To make matters worse, there are situations where parentheses can be used anyway, because they have a different meaning in that context:
>>> Hour(Now)
This actually works, because here the parentheses do not mean "parameter list", but "pass this argument by value". Take a look this article about the many interesting situations parentheses can create in VBScript.
The other mistake in your script, as Ekkehard.Horner already pointed out, is that you use == instead of = for comparing values.
As a side note: you seem to assume that the input will always consist of uppercase letters only, but you never enforce that anywhere. You may want to UCase your input or add a check to validate the input.
Seeing jmvp do such a good job optimizing your program made me want to do the same! :)
Here's my version. I added a constant to specify the application name (since it's used a few times) and also allow player 2 to quit playing by clicking Cancel (or entering nothing).
Const APP_TITLE = "Guessing Game"
strPhrase = InputBox("Player 1: Enter a phrase", APP_TITLE)
With New RegExp
.Pattern = "[^AEIOU]"
.Global = True
strDisplay = .Replace(strPhrase, "_")
End With
Do
strResult = InputBox("Player 2: Enter your guess for " & strDisplay, APP_TITLE)
Loop Until StrComp(strPhrase, strResult, vbBinaryCompare) = 0 Or Len(strResult) = 0
If Len(strResult) > 0 Then MsgBox "You got it!", vbOkOnly, APP_TITLE
Dim phrase As String = InputBox("Player 1: Enter a phrase", "Guessing Game")
Dim charCount As Integer = phrase.Length
Dim strMask As String = vbEmpty
For x = 1 To charCount
strMask &= "_"
Next
Dim guess As String = vbEmpty
Do
guess = InputBox("Player 2 enter your guess for " & strMask, "Guessing Game")
Loop Until phrase = guess
MsgBox("You got it!", vbOKOnly, "Guessing Game")
Ok, so I am almost done programming a module for an ecommerce store I run. I am pulling a value from the database :
shipChange = rs("ordShipType")
response.write rs("ordID") & vbTab & rs("ordTrackNum") & vbTab & shipChange & vbTab & OrderDate & vbCrlf
I need to detect if the value of shipChange is = UPS Ground, if it is I need it to be changed to UPS before printing, if the value is USPS First Class, I need it to be changed into just USPS. The results are spit into a tab delimited text file and there will be multiple values pulled, so it needs to keep checking until all values have been read and changed.
Use Select Case to determine what to change how and Split to get the first 'word' of your UPS*.
Option Explicit
Dim shipChange
For Each shipChange In Array("UPS Ground", "USPS First Class", "Reitender Bote")
WScript.Stdout.Write shipChange
Select Case shipChange
Case "UPS Ground", "USPS First Class"
shipChange = Split(shipChange)(0)
Case "Reitender Bote"
shipChange = "Horse"
Case Else
shipChange = "????"
End Select
WScript.Echo " =>", shipChange
Next
output:
cscript 21100431.vbs
UPS Ground => UPS
USPS First Class => USPS
Reitender Bote => Horse
shipChange = Replace(rs("ordShipType"), "USPS First Class", "USPS")
shipChange = Replace(shipChange, "UPS Ground", "UPS")
I have a table named: schoolInfo in access 2007 and it has two fields (schName and mjrName).
Now I'm trying to design a combo in Visual Basic 6 (cboMajors) which is related to the other combo (cboSchool).
As a matter of fact I want to have to cascading combo boxes. When I choose an Item in cboSchool the other combo should represents just the related majors for that school (records with schName=x and mjrName=y).
Private Sub Form_Activate()
connection
' the Connection is a code in module contains codes are needed to make the connection between form and the database
fill_schools
fill_majors
End Sub
Also,
Private Sub fill_schools()
With rs
.Open "select DISTINCT schName from tblSchoolsInfo", cn, 2, 3
Do While Not .EOF
cboSchool.AddItem (.Fields(0))
.MoveNext
Loop
End With
rs.Close
End Sub
Private Sub fill_majors()
With rs
.Open "select DISTINCT mjrName from tblSchoolsInfo where schName= '" & Me.cboSchool & " '", cn, 2, 3
Do While Not .EOF
cboMajors.AddItem (.Fields(0))
.MoveNext
Loop
End With
End Sub
Now: the first combo get correct values but the second one is completely empty.
In the snippet of code you have given us, I can't see anywhere where you actually select the school in Form_Activate(). This means that by the end of that procedure, there will be no selection in school, so fill_majors() will execute:
select DISTINCT mjrName from tblSchoolsInfo where schName= ' '
Incidentally, is that trailing space deliberate? In which case, this won't return records even if a school is selected.
The OP solved this in dreamincode.net. He was tacking an extra space on the end of his combo box string: Me.cboSchool & " '"
I've always wanted to say this: "This behavior is by design." :)
just a suggestion did you check the
cboMajors.AddItem (.Fields(0)) <--- .Fields()