Introduce a delay to allow printing of word doc to complete - vbscript

I have the following code to print a word document from vbscript
Set objWord = CreateObject("Word.Application")
objWord.Caption = "Test"
objWord.Visible = False
Set objDoc = objWord.Documents.Open("c:\test.doc")
'now print to default printer
objDoc.PrintOut()
MsgBox("Finished!")
'close word application
objWord.Quit 0
I would like to remove the message box and have the script silently run and complete, but when the delay of the message box is removed, the script finishes before the document is printed.
Is there a way to achieve this?
Many thanks
Dave

Replace it with a sleep command, like below. 1000 is one second, so adjust as needed. 200 might work well for your script.
WScript.Sleep 1000

Related

Open Microsoft Word and type text with SendKeys

I am trying to create a VBScript that opens Word and inputs text into it.
My code:
::Set wshshell = WScript.CreateObject("WScript.Shell")
::Set objShell = CreateObject("WScript.Shell")
::objShell.AppActivate "word"
::userProfilePath = objShell.ExpandEnvironmentStrings("%UserProfile%")
::WScript.Sleep 10000
::wshshell.SendKeys "Hello World!"
Perhaps surprisingly, you cannot interact with Word unless you actually started the program in the first place. As documented the AppActivate method activates an application window, i.e. brings the window of an already running application to the foreground.
To start Word programmatically use something like this:
Set wd = CreateObject("Word.Application")
wd.Visible = True
You can open a document like this:
Set doc = wd.Documents.Open("C:\path\to\your.docx")
or create a new document like this:
Set doc = wd.Documents.Add
Text can be entered for instance via the TypeText method:
doc.Selection.TypeText "some text"
Save the document like this:
doc.Save
doc.Close
or like this (if it's a new document or you want to save it under a different name/path):
doc.SaveAs "C:\path\to\new.docx", 16
doc.Close
Exit from the application like this:
wd.Quit
Do NOT use SendKeys for anything. EVER. Not unless you're being forced at gunpoint.
Also do NOT write Frankenscript that mixes different languages (like batch and VBScript) in the same file. It's a pain in the rear to debug and maintain.

VB script will not traverse every file in a given folder

I am new to VBscript and am looking to write a simple script that changes a couple cells in a few thousand csv files in a given folder location. I have a good start, and it all seems to be working, except for the fact that when I run the script (from a .bat file that just calls the script) it only changes and moves 3-8 files at a time. The number of files it changes is random, its not like it always changes 5 files or something. I am not sure what is wrong in the code as to why it will not edit and move every single file and only does a couple at a time, here is what I have so far, thanks in advance for any help:
Set objFSO = Wscript.CreateObject("Scripting.FileSystemObject")
Set colFiles = ObjFSO.GetFolder("C:\Users\xxx\BadCSVs").Files
Set xl = CreateObject("Excel.Application")
For Each objFile in colFiles
If LCase(objFSO.GetExtensionName(objFile)) = "csv" Then
Set wb = xl.Workbooks.Open(objFile)
Set sht = xl.ActiveSheet
If(sht.Cells(1,11) <> "") Then
sht.Cells(1,8) = sht.Cells(1,8) & sht.Cells(1,9)
sht.Cells(1,9) = sht.Cells(1,10)
sht.Cells(1,10) = sht.Cells(1,11)
sht.Cells(1,11) = Null
wb.Save
wb.Close True
Else
'if file is opened up and has only 10 columns of data, then it makes no changes, then closes it.
wb.Close
End If
End If
Next
xl.Quit
Your EVIL global
On Error Resume Next
hides errors. Disable/Remove it and test again.
Your
wb.Close SaveChanges=True
passes the boolean result of comparing SaveChanges (undefined/empty) vs. the boolean literal True. Perhaps you copied VBA code
wb.Close SaveChanges:=True
(mark the colon) that is not legal in VBScript?
And
Set xl = CreateObject("Excel.Application")
should be paired with an
xl.Quit
If you invoke Excel in the loop, terminate it there. I would try to start/quit Excel out of the loop, but you should test that approach carefully.

how to check that MS Word is running using VBScript

we have an application that runs MS Word (hidden) to print documents.
If one of the printers has a problem, then Word hangs while waiting for the spooler to return the 'queued' message.
We have found that if we make Word visible (by using VBA in Excel with GetObject and oWordApp.visible=true for example) then the process continues printing the other documents with no problem.
We would like to make this more automatic by having a VBScript check for Word in running processes, if it finds it, make it visible, wait for a few seconds, hide it, and quit...
But I have a problem that the VBScript GetObject function instantiates Word if it's not already running.
how should I check that word is running using VBScript without creating an instance of it?
here is the code I have in my VBScript file:
dim oWord, WScriptShell
set oWord = getobject("", "Word.Application")
set WScriptShell = CreateObject("WScript.Shell")
if isobject(oWord) then 'and oWord.Documents.count>0
wscript.echo("Word is running")
oWord.visible=true
WScript.Sleep 1000
oWord.visible=false
else
wscript.echo("Word not running")
end if
so what should I use to check if word is running without creating an instance of it?
Just change GetObject("", "Word.Application") to GetObject(, "Word.Application") and it doesn't start an instance.
But this throws an error if Word is not running, so you can use it like this:
msgbox wordIsRunning
function wordIsRunning
dim wdApp
on error resume next
set wdApp = GetObject(, "Word.Application")
wordIsRunning = (err.Number = 0)
set wdApp = nothing
end function
Word hangs
check "DisplayAlerts" property. allowed only if property "Visible" set to "True".
tasklist /FI "IMAGENAME eq winword.exe"
will show you, does m$word running or not

VB script: Message while Unzipping a file

I am using the below vb script to un-zip the files, so while un-zipping is going on, i am seeing a pop up messgae(Copying/extracting), is there any way to get rid of popup message?
FileToGetUnZipped = "InstallDir\UI_Files.zip"
DestPathForUnzippedFile = "InstallDir\system"
Set objFSO = CreateObject("Scripting.FileSystemObject")
If Not objFSO.FolderExists(DestPathForUnzippedFile) Then
objFSO.CreateFolder(DestPathForUnzippedFile)
End If
UnZipFile FileToGetUnZipped, DestPathForUnzippedFile
Sub UnZipFile(strArchive, DestPathForUnzippedFile)
Set objApp = CreateObject( "Shell.Application" )
Set objArchive = objApp.NameSpace(strArchive).Items()
Set objDest = objApp.NameSpace(DestPathForUnzippedFile)
objDest.CopyHere objArchive
End Sub
The CopyHere method takes a second argument which can be a combination of various options, including
(4)
Do not display a progress dialog box.
However, I have not had much success on getting many of these options to work reliably - I think it varies by Windows version as much as anything else.
As a side note, I think you may have issues with the CopyHere method being asynchronous - your script may complete before CopyHere does, which may kill the copying process.

How do I close Word (or other app) if an error occurs in a VBScript?

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

Resources