In connection with another, very different project, I am trying to write a VBScript that will, when executed, do the following:
Open an instance of Notepad (as a hidden or minimized window)
Bring the instance of Notepad into focus
Write "Hello world" into the open notepad file
Issue the appropriate alt+S etc. commands to save the file on the Desktop as "PrototypeText.txt"
Close Notepad.
My biggest points of confusion are in steps "2" and especially "4" above. I know how to do all the other things in VBScript. Can anyone help me with these two steps?
Lastly, I realize that there are much more practical ways of accomplishing this, such as AutoHotKey, or writing directly to the *.txt file, in some other language perhaps. Please understand that the above program is a proof-of-concept for another project, not a deliverable in itself.
Your time spend responding is greatly appreciated. A link (that I haven't found yet) that specifies how to do "2" and "4" above would work as well.
In WSH object if you are running vbs in that environment (as is likely) then use appactivate. But a hidden window can't be activated so ...
Again sendkeys in the WSH object can do 4 (but not in a hidden window).
Here's a sample from vbscript help (https://msdn.microsoft.com/en-us/library/8c6yea83(v=vs.84).aspx) using both commands and note using sleep to give apps the chance to process commands.
set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "calc"
WScript.Sleep 100
WshShell.AppActivate "Calculator"
WScript.Sleep 100
WshShell.SendKeys "1{+}"
WScript.Sleep 500
WshShell.SendKeys "2"
WScript.Sleep 500
WshShell.SendKeys "~"
WScript.Sleep 500
WshShell.SendKeys "*3"
WScript.Sleep 500
WshShell.SendKeys "~"
WScript.Sleep 2500
Minimised windows can get the focus.
Use a string like this to get the desktop. Include quotes."%userprofile%\desktop\yourfilename.txt". Quotes are in case there are any spaces.
Also AppActivate returns a code. True if it can or is activated. You can use this to test for dialogs by apactivating the dialog title. It's really Window activating.
Assuming you don't want to change/keep adding to this text file via scripting while it's open the below should work.
Dim objFSO, objFileToWrite, WShell
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set WShell = CreateObject("WScript.Shell")
'Create Text File and write to it then close it
Set objFileToWrite = objFSO.CreateTextFile("C:\Users\***YOUR USER ID HERE***\Desktop\PrototypeText.txt", 1)
objFileToWrite.Write "Hello World"
objFileToWrite.Close
'Open newly created and saved text file
WShell.Run("Notepad.exe C:\Users\***YOUR USER ID HERE***\Desktop\PrototypeText.txt")
Related
I'm attempting to enter a NI number into a Powerbuilder application from an Access DB.
Whenever I attempt to enter "AA123456A" into my application, UFT passes the value in as 123456.
If f_GetAccessFieldValue("NINumber") <> "" Then
PbWindow("w_genapp_frame").PbWindow("Client Details").PbDataWindow("dw_ap010_03_02"). SetCellData "#1","custp_ni_code",f_GetAccessFieldValue("NINumber")
End If
The value from Access is definitely passed in as a string.
Is this a limitation of my application, or is there a simple way to fix this without having to split the string and enter the values using separated variables?
Edit: Just noticed that even sending letters on their own ("AA") does not work.
The solution was to use SendKeys and pass in a variable
If f_GetAccessFieldValue("NINumber") <> "" Then
strNINo = f_GetAccessFieldValue("NINumber")
PbWindow("w_genapp_frame").PbWindow("Client Details").PbDataWindow("dw_ap010_03_02").SelectCell "#1","custp_ni_code"
Set WshShell = CreateObject("WScript.Shell")
WshShell.SendKeys strNINo
WshShell.SendKeys "{TAB}"
End If
Sorry for the long title.
I have several .xlsm files which share a lot of code, so I moved the repeated parts to an addin .xlam file. I have been using a .vbs script to open all the files one after another and run a macro in each.
Problem
The problem I'm facing is that on the second run of the .vbs script, excel crashes and gives what seems to be a very generic error, said here to be an "Automation Error":
Script: C:\Users\~\Desktop\test\test.vbs
Line: 5
Char: 1
Error: The server threw an exception.
Code: 80010105
Source: (null)
To my surprise, I was able to reproduce this crash even after removing 99% of the content of my files.
test.vbs:
Dim xlApp
Dim xlBook
Set xlApp = CreateObject("Excel.Application")
Set xlBook = xlApp.Workbooks.Open("C:\Users\~\Desktop\test\test.xlsm")
xlApp.Run "Auto.Run" '<~~ error on this line
xlBook.Save
xlBook.Close (True)
xlApp.Quit
Set xlBook = Nothing
Set xlApp = Nothing
test.xlsm:
test.xlam has a module Module1, test.xlsm has a Module Auto and a Reference to test.xlam
test.xlsm, Auto:
Sub Run()
MsgBox "hello"
Test.Load
MsgBox "goodbye"
End Sub
test.xlam, Module1
Sub Load()
MsgBox "Load"
End Sub
Function Other()
End Function
With the function Other() commented out, the code works fine (saying hello, load and goodbye). It also works fine if the macro is run from within excel. Only when Other() is present, and Run() is run through the .vbs file is there an error (right after hello).
Workaround
If I open test.xlsm, save it, and close it again in between each run of test.vbs, there are no problems. I believe this has something to do with the addin, rather than the spreadsheet, because in my original script, which opened multiple excel files, only one file needs to be opened and saved.
I also noticed that the excel file is a little bigger in its "problem" state, and that once I open and save it, it returns to its slightly smaller original size. (EDIT: This is at least partly caused by new cache streams __SRP_4 and __SRP_5 inside the vbaProject.bin file, which I extracted using this answer (oh, and this). After manually deleting all SRP entries, I was able to run the .vbs script again without problems, although just like the open-save-close strategy, it's only temporary, and will then crash on the third run rather than the second.)
Question
Are addins not appropriate for shared code? May they not contain functions? Is there any way to work around this crash besides what I'm doing right now?
Any thoughts are appreciated.
It sounds to me like the first instance isn't being unloaded/released before the second instance is being called. Perhaps using the Application.Wait Method to wait a few seconds before each subsequent run in performed might help?
'Open file1
'Run macro from file1
'Close file1
Application.Wait(Now + TimeValue("0:00:10")) 'wait 10 seconds
'Open file1
'Run macro from file1
...
...
So on
To install your add-in to excel via vbscript you can use the following code
'Launch Excel
set objExcel = createobject("Excel.Application")
strAddIn = "ESP Assistant.xlam"
'~~> Path where the XLAM resides
SourcePath = "Your source path\" & strAddIn
'Add the AddIn
On Error Resume Next
With objExcel
'Add Workbook
.Workbooks.Add
'Show Excel
objExcel.Visible = True
.AddIns.Add(SourcePath, False).Installed = True
End With
If this fails you might have to clear your registry values first, then rerun the above script
'File to use just in case Add-In installation fails
'Refreshes Excel Registry Entries to allow for clean install of Add-In
Dim objFSO, objShell
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = WScript.CreateObject ("WScript.shell")
objShell.Run "cmd /c ""C:\Program Files (x86)\Microsoft Office\Office14\excel.exe"" /unregserver && timeout /t 3 && tskill excel && ""C:\Program Files (x86)\Microsoft Office\Office14\excel.exe"" /regserver",1,True
Set objFSO = Nothing
Set objShell = Nothing
x=msgbox("Excel registry refreshed." ,0, "Registry Update")
wscript.quit
Unfortunately, I still don't know why this is happening, but I found an automated solution that I'm going to stick with.
As I mentioned in my question, the test.xlsm file was a little bigger in its "problem" state, due at least partially to some kind of cache, of which I could only find one offical mention here:
2.2.6 SRP Streams
Streams that specify an implementation-specific and version-dependent performance cache. MUST be
ignored on read. MUST NOT be present on write.
The name of each of these streams is specified by the following ABNF grammar:
SRPStreamName = "__SRP_" 1*25DIGIT
My solution was to remove the cache, which I did manually at first with this tool. When that seemed to work, I wrote a Java program to do it automatically (gist here). It's glue between java.util.zip and Apache POIFS.
I also added a line to call the Java at the end of the .vbs script:
CreateObject("WScript.Shell").Run "java -jar clear-excel-cache.jar C:\Users\~\Desktop\test\test.xlsm", 1, false
In my actual .vbs file, which calls multiple excel files in a loop, this line is just inside the loop. There is a little cmd window that opens after each file is run but it no longer crashes on the second run, so I'm calling that a success.
Your issue could be the same issue which I am trying to resolve - Random 64-bit Excel 2013 VBA crashes (VBE7.dll errors). You can check the Application Event logs for a VBE7.dll crash to confirm this.
In my case various XLSM files become intermittently corrupted through manual use.
My fix as an alternative to yours is the following VBS (anything to trigger a VBA "recompile").
Resave "myfile.xlsm"
Sub Resave(filename)
Set objExcel = CreateObject("Excel.Application")
currentDirectory = left(WScript.ScriptFullName,(Len(WScript.ScriptFullName))-(len(WScript.ScriptName)))
objExcel.Application.AutomationSecurity = 3 ' Disable to avoid crash
objExcel.Application.enableevents = False
objExcel.Application.Workbooks.open(currentDirectory + "\" + filename)
objExcel.Application.Visible = True
objExcel.Application.DisplayAlerts = False
Set objSheet = objExcel.ActiveWorkbook.Sheets.Add
objSheet.Delete
objExcel.Application.DisplayAlerts = True
objExcel.Application.enableevents = True
objExcel.ActiveWorkbook.Save
objExcel.ActiveWorkbook.Close
objExcel.Application.Quit
Set objExcel = Nothing
End Sub
FYI - Microsoft released a patch which fixes the issue in Excel 2013 on 3rd May 2016.
https://support.microsoft.com/en-us/kb/3085486
I'm trying to update some data into a SharePoint document and while trying this in local environment I do not face any issue.
But when I try to do the same in virtual desktop, I couldn't make it. I'm being populated with Windows Alert to key-in username & password. I've tried using 'SendKeys' for this scenario, but it doesn't make sense.
....
SendKeys "abc\ATX123",5
SendKeys "Password1",5
SendKeys "{ENTER}",5
....
This snippet is just passing 'ENTER' without entering ID & Pwd. Can anyone suggest me some possible solution, please?
Finally, I've found a way to achieve this requirement,,,,, bit indirect, but that was the only way I could find at the end.
What I did is simple - just created one windows scripted file 'Logon.vbs' to handle that popup screen and called the vbs in VBA.
Refer to the sample below, if you're looking for something like this:
Windows Script:
'Creating an script object
Set oWSH = WScript.CreateObject("WScript.Shell")
'Activating alert screen
oWSH.AppActivate ("Windows Security")
'Passing the value UserName/UserID
oWSH.SendKeys "USERNAME" 'ensure to complete the username with apropriate domain e.g., abc/A123456
'Changing the focus to password textbox
oWSH.SendKeys "{TAB}"
'Passing the value password
oWSH.SendKeys "PASSWORD"
'Clicking enter to complete the screen
oWSH.SendKeys "{ENTER}"
'Releasing the script object
Set oWSH = Nothing
VBA code to call the VBS script - Logon.vbs:
Shell "WScript C:\Users\ABC\Desktop\Logon.vbs", vbNormalFocus
First of all you'll want to SendKeys "yourString", Boolean. As I know the SendKeys command wants a True or a False as second input.
You could also try "tabbing" from a field to another:
SendKeys "abc\ATX123", True
SendKeys "{TAB}", True
SendKeys "Password1", True
SendKeys "{ENTER}", True
if the first one didn't get get written, maybe the focus is on another component of the userform. Try "tabbing" to find out if your "Username" textbox is yet activated as the UserForm appears. In case it isn't you could also try to set some focus
I have a simple VBA code (see below), that goes to a webpage, selects some value, clicks the “Begin download” button, and then saves the file. The problem is I am stuck at the “clicking the download button” part. Can someone help?
Here is the code:
Sub Treasury_Auc_Notes()
Dim IE As Object
Set IE = Nothing
Set IE = CreateObject("InternetExplorer.Application")
IE.Visible = True
IE.Navigate "http://www.treasurydirect.gov/RI/OFAuctions?form=ndnld&typesec=notes"
While IE.Busy
DoEvents
Wend
IE.Document.All.Item("begYr").Value = "2012"
With IE.Document.getElementsByName("cols")
.Item(0).Checked = True
End With
'Click "Begin download" button (this is where I am stuck)
'Choose Save Open or Cancel (I haven’t got to this part yet)
ActiveWorkbook.SaveAs Filename
End Sub
This one's tricky, and due to restrictive security on my laptop, I'm not able to verify this 100%, but try:
While IE.ReadyState <> 4
DoEvents
Wend
IE.Document.All.Item("begYr").Value = "2012"
With IE.Document.getElementsByName("cols")
.Item(0).Checked = True
End With
Dim ele As Object
For Each ele In IE.Document.Forms
If ele.Action = "/RI/OFAuctions" Then
ele.Submit
Exit For
End If
Next
You may have to use SendKeys (I think Application.SendKeys "o") method to open the file then use VBA to save the ActiveWorkbook to the desired location. I'm not able to test SendKeys for reasons mentioned below.
Or, I'm pretty sure there is a WinAPI functions that can do this more reliably than SendKeys. You'll need to get the hWnd of the Save dialog and do some other stuff to force it to open/save. This is fairly advanced VBA that I probably have a reference to somewhere, but rarely need to use it. If you have trouble with this particular part, I would urge you to ask a separate question "How to get the hWnd of File Save dialog and download file from IE" or something like that.
NOTE: I can't test the SendKeys method. When I use the above code, I am fairly certain the file is being downloaded, but it is going to a temporary folder that is hidden, and difficult to find. In any case, it does appear to be downloading with some manual intervention. I get this warning:
I click to ignore that (I have no idea how to automate this part, I'm just trying to validate that the form .Submit method actually worked), and after some creative searching (temporary internet files get dumped in a strange/hidden folder usually) I verify the file is downloaded, although it is showing as a TXT extension instead of CSV.
If instead of using VBA, I click on the button manually, and I choose to "open" the file opens as CSV and has the same path to that temporary internet location.
I'm trying to write a simple script to fill in login details on a program that requires signing in using a keyboard shortcut.
set wshshell = wscript.CreateObject("wscript.shell")
WshShell.SendKeys "username{tab}passowrd{enter}"
This works as desired on my work computer (xp) but on my home computer (windows 8) the keyboard shortcut deactivates the current window so that the details are not entered.
Any help would be greatly appreciated.
You may want to look into the shell's AppActivate method. You could write something like this:
boolSuccess = False
do until boolSuccess = True
boolSuccess = WshShell.AppActivate("AppName")
WshShell.sleep 500
loop
WshShell.SendKeys "username{tab}password{enter}"
This will move the focus to your target app, and then send the keys. The tragically kludgey part is that you may need that 'sleep' between the AppActivate and the SendKeys to be sure that your target app has time to receive the focus.