First off I'm sorry that i'm very very new to VBS, but i'm trying to create a little script that will complete a series of key strokes then on a website for work then go to another website and complete another series of key strokes.
Whilst on the first website there I need to ask a question like did the action complete. Yes or No.
If No then the script needs to go back to the start of the script. If yes then the script needs to continue.
Later on, on the second website after a few keystrokes I need to ask another question weather to loop the whole process or to stop.
I've googled a few message box solutions but it doesn't seem to work. I have
The first question box.
intSerialNumber = _
Msgbox("Was there a problem?", _
vbYesNo, "Problem?")
If intSerialNumber = vbYes Then
LoopShip
Else
Continue
End If
Continue
The Second question box.
If msgbox("Continue?", vbYesNo) = vbNo Then
WScript.quit
End If
if LoopShip = True Then
LoopShip
End If
Wend
Try using nested loops with functions for readability like this. The user can rerun the code from the first website as many times as they want and can rerun the code from both websites as many times as they want.
Dim problemsOccurred
problemsOccurred = vbYes
Do
Call firstWebsite()
problemsOccurred = secondWebsite()
Loop Until (problemsOccurred = vbNo)
Sub firstWebsite()
Dim firstWebsiteProblem
firstWebsiteProblem = vbYes
Do
'First Website code Goes here
firstWebsiteProblem = Msgbox("Was there a problem?", vbYesNo, "Problem?")
Loop Until (firstWebsiteProblem = vbNo)
End Sub
Function secondWebsite()
'Second WebSite code goes here
secondWebsite = MsgBox("Continue Whole Process?", vbYesNo)
End Function
Related
I'm facing a random problem. When executing SAS programs with VBScript and the SASEGObjectModel.Application.7.1, looping through CodeCollection get stuck sometimes, even if the program execution was succeeded (the final data bases are correctly created in our server). The script simple doesn't go to the next program of CodeCollection (the prompt executing the script still open... ad infinitum). The SAS program It happens is random, also the frequency. I'm going with something like this:
Dim oSasApp
Set oSasApp = CreateObject("SASEGObjectModel.Application.7.1")
oSasApp.SetActiveProfile("some-profile")
Dim oSasProj
Set oSasProj = oSasApp.Open("some-project.egp", "")
Dim oProgramList
Set oProgramList = oSasProj.CodeCollection
Dim programOrder
Set programOrder = ...here I assign the SAS programs order array reading from a .txt...
For Each program in programOrder
For Each sasProgram in oProgramList
If sasProgram.Name = program Then
sasProgram.Run
sasProgram.Log.SaveAs "some-folder/" & sasProgram.Name & ".txt"
End If
Next
Next
oSasProj.Close
oSasApp.Quit
The problem is not the Log saving, as the log txt file of the stucked program is also correctly created.
Any idea? Maybe problems in our SAS server? Should I declare some kind of options?
SAS Guide version: 7.15
Windows: 10
Tks
So... for people facing the same problem. As I commented above, if I press enter on prompt the script flows again. So it is waiting for my input, for reasons I can't tell. I did 2 things to get around it. Not sure if all of them are necessary or if only one solves it, but here it goes:
First, by VBScript I turned off a list of generations and I applied a delay after the SAS program runs:
For Each program in programOrder
For Each sasProgram i oProgramList
If sasProgram.Name = program Then
sasProgram.GenSasReport = False
sasProgram.GenHTML = False
sasProgram.GenListing = False
sasProgram.GenPDF = False
sasProgram.GenRTF = False
sasProgram.Run
WScript.Sleep(2000)
sasProgram.Log.SaveAs "some-folder/" & sasProgram.Name & ".txt"
End If
Next
Next
Them, in my batch file, wich I use to call the VBScript with the "cscript" command, I set it to apply "y" to every single message the VBScript could ask:
cd ./script-folder
echo y | cscript script-file-name.vbs
And that is it.
I've ran into a problem with one of my scripts.
The script automates our shared mailbox (outlook). It auto-assigns mails to the correct person.
Everytime the script runs, it loops all the mails in the folder and checks if it has a category. If not, it assigns it to the right user.
Problem is, when a mail with no category gets dragged to another folder while running the script, it throws an error when trying to execute mail.Categories
Line: 222
Error: Could not complete the operation due to error 8004010f.
Is there a way to check if the mailItem is still viable?
I tried using IsEmpty, but the msgbox doesn't trigger.
Set outlook = CreateObject("Outlook.Application")
Set namespace = outlook.GetNameSpace("MAPI")
Set Account = namespace.Folders("accountName")
Set Inbox = argentaAccount.Folders("Inbox")
For Each mail in Inbox.Items
If IsEmpty(mail) Then
MsgBox("test")
End If
'check if item has a category'
If mail.Categories <> "" Then
'has a category'
Else
'Execute mailhandling code'
End If
Next
If anyone has any solution, I would be forever grateful.
With this line as a clue:
If IsEmpty(mail) Then
VBScript may work the same as VBA where For Each works like:
For i = 1 to Inbox.Items.Count
When item 1 is moved (or deleted), item 2 moves into position 1. On the next loop, position 2 with item 3 is processed. Every second item is skipped. In the second half of the loop there is nothing to process.
One way of dealing with this in VBA is to step in reverse order:
For i = Inbox.Items.Count to 1 step -1
Set mail = Inbox.Items(i)
If mail.Categories <> ""
Part of my code copys info from one worksheet in Excell to another. Every time I run this cood it gives me a run time error '1004' for the last line of code (activeSheet.Paste). Does anyone know how to fix it?
Sub CopyData()
ActiveWindow.SmallScroll Down:=-9
Sheets("sponsor & contributions 2012").Select
Range("A1:K93").Select
Application.CutCopyMode = False
Selection.Copy
Sheets("remaining payments").Select
Selection.PasteSpecial Paste:=xlPasteFormats
ActiveWindow.SmallScroll Down:=-12
Range("A1:K93").Select
ActiveSheet.Paste
End Sub
Rather than simulating a user 'copy+paste', it's easier, quicker and more robust to set the value of your target range to that of your source range. e.g.
Public Sub Copy()
Sheet2.Range("A1:K93").Value = Sheet1.Range("A1:K93").Value
End Sub
Determining the cause of a 1004 error can be very difficult without being able to look over the spreadsheet, so I would definitely recommend the above approach
I ask this partly because I want to know the best practice way of doing this, and partly because the top google result I got was a forum thread from 2002 in which the question wasn't even answered.
I inherited some VB6 code, and there are some MsgBox calls in said code, many of which display messages that end users would probably find very annoying after a short time (e.g. "Printing Complete," "Record Added," etc.)
I would like to add the standard user interface control of a checkbox on the MsgBox saying "Don't ask me this again", so that when checked and OK is clicked, a setting is saved that lets the program know, you know...to never ask that again. Pretty standard control, the idea is fairly self-explanatory.
What I would like to know is what is the best practice way of doing this in VB6. There is the obvious way of just making a new form for these type of msgboxen and replacing the old MsgBox call with a .Show on that form, but do the VB6 gurus on Stack Overflow have a better way?
Thanks in advance
As far as I know, there is no other way. You need to make your own message box form with the check box. Of course, you'll also need to modify the code to store and retrieve this setting (and acting appropriately based on the setting).
I have done this in my own application many times. One thing to think about.... suppose the user checks the box "don't show me this again". In my opinion, there should be a way to reset the setting. Since the message box form won't show again, I added this to the configuration form (for my app).
One thing you may want to consider is sub-classing the MSGBOX function. You could create a function within your app that has a similar parameter list, but with a couple extra. If the extra parameters are missing, simply call vba.MsgBox (to get the standard behaviour). If you pass in extra parameters, you could call your new form instead.
Well... You are not absolutely correct guys ;)
Starting from Win2000, there's SHMessageBoxCheck function that does the trick.
VB6 declaration:
Private Declare Function SHMessageBoxCheck Lib "shlwapi" Alias "#185" (ByVal hWnd As Long, ByVal lpszText As String, ByVal lpszTitle As String, ByVal dwType As VbMsgBoxStyle, ByVal iDefault As Long, ByVal lpszId As String) As Long
For everything else follow the link :)
If you provide such a functionality, it might require "turning-on" of showing messagebox.
i.e. user should have an option to see the msgbox again using some setting.
Instead of that, you could use statusbar to display notifications OR have a label with the notification messages and turn it off after a few seconds.
This was my down and dirty solution:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
myfile = Workbooks.Application.ActiveWorkbook.Path & "\noprompt.txt"
If Dir(myfile) <> "" Then Exit Sub
exportData = MsgBox("Export data?" & vbCrLf & "Select Cancel (or × top right) to prevent this prompt from displaying again.", vbYesNoCancel, "Close Workbook")
If exportData = vbYes Then
Call ExportValues 'a separate function...
ElseIf exportData = vbCancel Then
'create file noprompt.txt
Open myfile For Output As #1
Write #1, "Delete this file to restore prompt to Export Data when workbook is closed."
Close #1
Exit Sub
ElseIf exportData = vbNo Then
Exit Sub
End If
End Sub
Documentation for my app explains that deleting the file restores the prompt.
I wrote a VBScript app to open Word and Excel documents and search and replace blocks of text and various sections, pulling the new text from a plain text file. I purposely avoided any error checking, primarily because I couldn't figure it out at the time (and the script ran reliably anyway). Now months later on my local machine, I am inexplicably getting error messages about Normal.dot being changed and a message box asking what I want to do about it (which requires three more dialogs to finally answer). Of course this kills my ability to run the script and simply walk away, as it causes the script to fail. Currently when this happens, I have to open the Task Manager, find Winword.exe (of which the GUI isn't running) and kill it then re-run my script.
What's a reasonable way of catching the error and successfully shutting down Word (or Excel). Based on this question I'm trying this:
Set objDoc = objWord.Documents.Open(curDir1 + "\docs\template_spec.dot")
If Err.Number <> 0 Then
WScript.Echo "Error in Word Open:" & Err.Description
objWord.Quit
Else
Set objSelection = objWord.Selection
'Do replacement activities'
ReplaceText(objSelection)
objDoc.SaveAs(curDir1 + "\docs\mynewdocument.doc")
objWord.Quit
End If
Set objShell = Nothing
Set objWord = Nothing
Set objExcel = Nothing
Of course, as fate would have it, I cannot replicate the problem, so it works like normal. Does this solution seem reasonable? And a side question: How the heck do I get Word to stop complaining about Normal.dot (or get the script to handle it)? It's as if Word leaves itself open in the background after I have closed the GUI in some cases.
have you considered wrapping everything into an 'On Error Resume Next' statement so that your script ignores all the errors and continues to run as much as possible before calling the objWord.quit regardless of success or fail.
if you want more information on the correct use of 'On Error Resume Next' then go over to the msdn article on it!
Hope this helps!
Paul
I'm afraid that
WScript.Echo "..."
if it ever fires, is going to stall your script. Other than that, everything looks right. I'll play with it when I get home.
Edit: Word does hang out in the background, quite frequently. For one thing, if you use Outlook, and use Word as your Outlook editor, Word won't go away until Outlook is gone.
I'd agree with the use of "on error resume next".
If you really need to forcefully terminate Word, you can use WMI and the Win32_Process class to find and kill the process. This should be a last resort if everything else fails.
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colProcess = objWMIService.ExecQuery("Select * from Win32_Process Where Name = 'winword.exe'")
For Each objProcess in colProcess
objProcess.Terminate()
Next
This was a modified example from:
http://www.computerperformance.co.uk/vbscript/wmi_process_stop.htm
Also, make sure all your references to the Word automation object are closed and/or set to nothing before you terminate the process.
The most reliable way to terminate all ActiveX instances, clean up garbage, and release resources is to put the code for that purpose into Sub Class_Terminate() of a dummy class, created instance of the class allows to handle script quit event.
Option Explicit
Dim objBeforeQuitHandler, objWord
' create a dummy class instance
Set objBeforeQuitHandler = New clsBeforeQuitHandler
' create word app instance
Set objWord = CreateObject("Word.Application")
objWord.Visible = True
objWord.Documents.Add.ActiveWindow.Selection.TypeText "80040000 error was raised. About to terminate the script." & vbCrLf & "Word will be quitted without saving before script termination just you close popped up error message."
' your code here...
' raise an error
Err.Raise vbObjectError
Class clsBeforeQuitHandler
' dummy class for wrapping script quit event handler
Private Sub Class_Terminate()
Dim objDoc
On Error Resume Next ' to prevent errors in case of unexpected word app termination
If TypeName(objWord) <> "Object" Then ' word app has not been closed yet
objWord.DisplayAlerts = False
For Each objDoc In objWord.Documents
objDoc.Saved = True ' to prevent save as dialog popping up
objDoc.Close
Next
objWord.Quit
End If
End Sub
End Class