Detect Keyboard present in VB6 [closed] - keyboard

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I have a legacy VB6 project that can now run on systems without a keybord attached. In that case the program opens the MS on screen keyboard. I need to detect if a keyboard is attached or not. If there is a keyboard attached then skip opening the the on screen keyboard. At the moment it opens the on screen keyboard and the user must then close it. It is Clunky. I cannot migrate this application because it supports some legacy equipment that cannot be accessed by VB.net. Any Ideas please.

Windows Management Instrumentation is one way you could go. The following code looks for keyboards with an OK status:
Private Function hasKeyboard() As Boolean
Dim WMIService As Object
Dim Items As Object
Dim Item As Object
hasKeyboard = False
Set WMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\cimv2")
Set Items = WMIService.ExecQuery("SELECT * FROM Win32_Keyboard")
For Each Item In Items
If InStr(1, UCase(Item.Status), "OK") > 0 Then
hasKeyboard = True
Exit Function
End If
Next
End Function

Related

How to detect if user clicks on File >> Print as option or presses CTRL+P from within MS word or Excel using VBA code?

I want to detect when user clicks File >> Print or CTRL+P inside ms word or excel and use this detection to run a batch file using vba code, is this possible?
This code should self start along with the program.
I tried to find similar code but was unable to find anything useful to my need.
Any help would greatly appreciated.
Thanks
The way your question is written seems ambiguous to me. At first read, it seems like you are trying to distinguish between these two methods of telling a file to print. I know of no way to do this in vba.
However, you can intercept the print event or command.
Another possible meaning is that you want your procedure to run whenever the user attempts to print. See Intercepting Events Like Save or Print by Word MVPs Dave Rado and Jonathon West. See also Application.WorkbookBeforePrint Event.
Note, this does not block screenshots or saving to another file. Do you mind sharing why you are trying to do this? What you hope to accomplish?
You can use the DocumentBeforePrint and WorkbookBeforePrint Events. Below quoted from linked pages on Intercepting Events and WorkBookBeforePrint documentation.
A DocumentBeforePrint event procedure looks like this:
Private Sub oApp_DocumentBeforePrint(ByVal Doc As Document, _
Cancel As Boolean)
'Your code here
End Sub
If you want to prevent printing from occurring in certain
circumstances, you can set the Cancel variable to True, e.g.:
Private Sub oApp_DocumentBeforePrint(ByVal Doc As Document, _
Cancel As Boolean)
Dim Result As Long
Result = MsgBox("Have you checked the " & "printer for letterhead paper?", vbYesNo)
If Result = vbNo Then Cancel = True
End Sub
From Excel documentation
This example recalculates all worksheets in the workbook before
printing anything.
Private Sub App_WorkbookBeforePrint(ByVal Wb As Workbook, _
Cancel As Boolean)
For Each wk in Wb.Worksheets
wk.Calculate
Next
End Sub
End Quoted Material
Intercepting the Command instead of the Event
Another, less effective, method is to Intercept the actual commands. You could name your procedure PrintPreviewAndPrint and have another called FilePrintQuick that calls your procedure PrintPreviewAndPrint. Earlier versions use FilePrint and FilePrintDefault. Thank #Timothy Rylatt for the command names. He adds: Note that neither of these will intercept the backstage command accessed via File | Print. For that you need to use an event.
Sub PrintPreviewAndPrint()
' Your code here
End Sub
Sub FileQuick()
FilePreviewAndPrint
End Sub
In Word, these would go in your template or in a Global Template.
In Word, you make a template a Global Template by placing it in your Word Startup Folder.
Dealing with making this Global in Excel
My understanding of how Excel handles global macros is far poorer than that for Word. To assist with this, I asked my own question in the Microsoft Answers Excel Programming forum. Here is a link to that question and the answers I received. Andreas Klinger, who is engaged in that thread, is an experienced and knowledgeable Excel programmer, which I am not.

unexpected excel crash at saving [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
Anyone could tell me why excel crashes at line
Workbooks(strFichero).Save 'Here
'Cierro libro, guardando
Do Until Workbooks(strFichero).Saved
Workbooks(strFichero).Save
Loop
Workbooks(strFichero).Close
You are not giving it enough time to save. Also you do not need a loop like #BigBen mentioned. Simply use Workbooks(strFichero).Save.
You need to give time after the save command so that excel can save. Add DoEvents before Workbooks(strFichero).Close and it will be ok.
For example
Workbooks(strFichero).Save
DoEvents
Workbooks(strFichero).Close
Alternatively you can also use this one liner
Workbooks(strFichero).Close (True)
'OR
Workbooks(strFichero).Close SaveChanges:=True
You can use the SaveChanges parameter of Workbook.Close method (Excel)
expression.Close (SaveChanges, FileName, RouteWorkbook)

Getting a not Definded error when the program tries to close the window? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
Experimenting with Tkinter and Gui creating and cant seem to run two commands off of one button press.
I've already tried moving the second definition out of the first definition to the same error as before. The problem is that it is a separate window to my main window and so is under a different definition meaning. When I've tried the previous threads answers it isn't working for me.
def cheese():
fll = Tk()
#The two commands linked together
def fildes():
filling2()
fll.destroy
fll.title=("Test")
ll = Label(fll, text ="Would you like to choose another topping?").pack()
#The button under this runs fildes()
bb = Button(fll, text ="Yep", command = fildes).pack()
bbb = Button(fll, text ="No", command = fll.destroy).pack()
It should create a window and when the yes button is pressed open a new window while closing the current window.
It opens the new window but fails too delete the current window due to fll not being defined
def fildes():
filling2()
fll.destroy()
this does not work either
Solution:
Always try to pass the arguments to your functions. If I'm seeing this right, Tkinter only calls the standalone filedes() function, without any knowledge about local variables in cheese.
Pass the window you want destroyed to filedes like this:
def fildes(old:Tk):
old.destroy()
filling2()
Then add fll as parameter to the command of your button. (Can be done like this.)
bb = Button(fll, text ="Yep", command = lambda: fildes(fll))
PS:
When I tried to run your code I had to call .pack() like this or else it wouldn't work:
sample = Button()
sample.pack()

Why can't VBA module actions be reversed? i.e., Ctrl+Z'ed [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
For the past several months I've been writing VBA scripts, and have noticed that, if I write a module that acts upon an Excel workbook/sheet, I'm not able to Ctrl+Z these actions. This, from what I've noticed, applies to any and every action that's performed by the module.
A simple example would be:
Sub test()
Cells(1,1) = "Hello World"
End Sub
Why can't module actions be "reversed"? i.e., undone through Ctrl+Z, or, by utilizing the 'undo' arrow.
P.S. I think this behavior might also apply to any module action within any MS application, though, I could easily be wrong.
No they can't be reversed but you can use my method:
You could save your workbook (ActiveWorkbook.Save) at beginning of each macros then if you want to undo:
Const pathToTheFile as String = "C:\Users\VbaProject\"
Sub Undo()
wb = ActiveWorkbook.Name
Workbooks(wb).Close savechanges:=False
Workbooks.Open Filename:=pathToTheFile & wb
End Sub
You can even bind it to a shortcut...

Side-Step Application.MsgBox in VBA (Excel)

In order to head off a storm of "comment it out" replies, here is my situation:
I have a process is normally run 1 iteration by 1 iteration. A user manually hits a button that calls a macro which, upon completion, pops up a message box that reports the total time length the macro ran for. It's pretty handy for diagnosing issues. This code is locked down and I cannot modify it.
I am trying to do this at scale. Because the code in the main spreadsheet and workbook are locked, I have a separate workbook open in the same instance of excel with a macro that operates the locked down workbook. Rather than 1 by 1, I've got a set of 300 I'm trying to run through. Right now I have to babysit the thing and hit space to get past the MsgBox. Does anyone know of any tricks to prevent me having to monitor the thing? Either disabling the pop-ups or some way to make them non-modal. Maybe a trick to make the mouse click?
You're right in knowing that the best way to fix the issue is to correct the code. In which case you would probably make the pop-ups toggle-able.
However, I wrote this for you which could be used as a potential work around. It utilizes VBScript to "sort-of" simulate multithreading so that you can send a key to the modal Msgbox. Assuming you can do what you want to do via code, simply call SendDelayedKeys before the action that will cause a Msgbox. You may have to tinker with the Delay based upon your circumstances as 100 milliseconds may not be enough. To change the Delay, just call like this: SendDelayedKeys 500 for 500 milliseconds.
Sub SendDelayedKeys(Optional Delay As Long = 100, Optional keys As String = """ """)
Dim oFSO As Object
Dim oFile As Object
Dim sFile As String
sFile = "C:\SendKeys.vbs" 'Make this a valid path to which you can write.
'Check for the .vbs file.
If Not Len(Dir$(sFile)) Then
'Create the vbs file.
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oFile = oFSO.CreateTextFile(sFile)
oFile.WriteLine "Set WshShell = WScript.CreateObject(""WScript.Shell"")"
oFile.WriteLine "WScript.Sleep CLng(WScript.Arguments(0))"
oFile.WriteLine "WshShell.SendKeys WScript.Arguments(1)"
oFile.Close
End If
Shell "wscript C:\SendKeys.vbs " & Delay & " " & keys
End Sub
Sub ProofOfConcept()
'Using default parameters which sends a space after 100 milliseconds
SendDelayedKeys
MsgBox "I disappear on my own!"
End Sub
A word of warning: Any solution that utilizes SendKeys is a fragile solution and should be avoided when possible. However, when your options are limited and you need to avoid a manual process, sometimes it's your only option.
Since SiddhartRout rightly pointed out that this could be solved using API calls: here's a link with C# code that would close your msgbox every second.
The problem here really isn't strictly a problem more code can (or indeed should) solve.
There are a great many things to consider and any solution will be more complex AND less reliable than the problem it is initially trying to solve. But lets look at your options...
SendKeys is not reliable for that kind of use, what happens if the dialogue says "would you like me to save this workbook?" just after making a change that was meant to be temporary or "would you like to play global thermonuclear war?" Plus with a batch process like that you want to get on with something else while you wait, even if it's only to come here to downvote trolls. If nothing else you may not be in control of this code so what kind of mess will it cause when the maintainers realise msgbox is bad UX and kill it?
FindWindow API calls would let you check the content in the window to make sure it says what you're expecting but then you're potentially asking some bit of quick & dirty vbscript to go into a race condition until the right window comes up. Can you guarantee that the threads won't lock up?. What about platform issues - what happens if someone wants to run your code on their shiny new surface? What happens when your 64 bit modal Excel dialogue window can't be seen by the 32-bit api calls you were making? What about a new version of office that doesn't present modal dialogues in the same way? None of those problems are insurmountable but each adds complexity (aka opportunity for failure.)
The best solution is fix the actual problem you have identified from the outset which is that the original code throws up an unnecessary modal dialogue. Someone needs to fix that - it doesn't have to be you but if you estimate how much time that modal dialogue wastes in lost productivity that should get you a solid business case for getting it sorted.

Resources