Excel VBA - SendKeys "{F2}" - keeps toggling num-lock - excel

After using setting a cell to select and then using SendKeys "{F2}" (So that the cell is ready for input) it likes to toggle num-lock every time this is ran.
I have seen people say to use SendKeys "{NUMLOCK}", True after the SendKeys "{F2}" but tat did nto help. even tried adding Application.Wait Now + TimeValue("00:00:01") between the two comands, but it still keeps toggling.
I have also read its a bug with Excel/VBA.
Is there a better solutions? I need to select the cell and then force it into edit mode in order for some validation checks to work properly, else it bypasses the check if it just selects the cell, the could continue on, forcing it into edit make it so they have to make a change if not and they leave the cell the validation kicks in again.
I also found this code and tried, but that doe not work, it just keeps toggling
Dim wshshell As Object
Set wshshell = CreateObject("WScript.Shell")
wshshell.SendKeys "{NUMLOCK}"
Set wshshell = Nothing
Even tried this and replaced with F2 but it still toggled numlock.
I need numlock to stay on at all times. is there another way to invoke the edit cell instead of F2?

Related

Attempting to automate text-entry into a number of text fields in an uncontrolled (manually-opened) webpage in Chrome or Edge

I'm attempting to automate a repetitive data-entry task on a webpage. I need to enter text into a series of text fields that appear in a sidebar, which means that I have to
click on the visible text field
send text data from Excel to that text field
click on a button so that the next text field is displayed
repeat 1-3
The problem is that in this particular case I have to log in to the webpage manually, so Excel doesn't have control of the browser, which means that I can't use most of the Selenium commands.
I managed to enter some of the data into different region of the webpage using the AppActivate statement and a series of SendKeys commands:
AppActivate ("Title")
Dim cellValue As Variant
cellValue = Range("B2").Value
SendKeys cellValue, True
SendKeys "{DOWN}"
cellValue = Range("B3").Value
SendKeys cellValue, True
SendKeys "{DOWN}"
I tried to rig up something like this for the text fields mentioned above, but SendKeys won't TAB over to the sidebar (despite the fact that I can TAB over manually).
I don't care at all if the solution is odd or inelegant, as long as it works! I'm new at this, so I may be making obvious mistakes and/or overlooking an obvious solution.

Excel VBA - Copy and Paste each cell Individually to another program

I'm fairly new to VBA but know my way around it a bit (sorta). What I'm needing to do is get a Macro set to copy data in one cell, switch to another program (2315), enter "6", [ENTER], paste the data, [ENTER] switch back to Excel, select the next row, copy, switch, paste, switch, until it reaches the end of the column. This is what I have, which works for the first cell. I just need to figure out how to loop it until it reaches the end. Thanks for any help/suggestions!
Range("A2").Select
Selection.Copy
AppActivate "2315"
Application.SendKeys "6~^V~"
Application.SendKeys "%{TAB}"
Thanks Again!
I doubt that this works, but you say it does and your question is about the loop. Here is the loop.
Dim R As Long
For R = 2 To Cells(Rows.Count, "A").End(xlUp).Row
Cells(R, "A").Copy
AppActivate "2315"
Application.SendKeys "6~^V~"
Application.SendKeys "%{TAB}"
Next R
For Excel's sake you don't need to select anything. The above code will loop through all the used cells in column A of the active tab. If your app "2315" needs the selection, add Cells(R, "A").Select before the copy instruction.
My doubt is based in the fact that you can't use VBA to send parameters to app "2315". This includes the instruction to "2315" to surrender control back to Excel and its VBA. Perhaps you have found such a way via the SendKeys. If so, the code will work. If not, it will get stuck after the first loop.
Logically, the code should run until AppActivate "2315", meaning the SendKeys are never sent until the other app has returned control. If that is what's going on there must be better ways to express whatever your two instructions get done. But that shouldn't be your immediate concern. If you can get "2315" to surrender control back to Excel with a simple command like Enter, and if the above macro really resumes work where it left off, most of your problem should be solved. This I hope for :-)

Change Axis Label font size in a funnel chart (Excel 2016)

I want to change font size on axis xlCategory. I am running the code like below but it is failing. I am stuck in finding workarounds. Chart is "Funnel" type 123. On the other types of chart code is running fine.
With ActiveChart.Axes(xlCategory).TickLabels.font
.size = 12
.Name = "Arial"
End With
I get the error:
"object doesn't support this action"
I was also trying to run the othe code but also without any success.
ActiveChart.Axes(xlCategory).Select
With Selection.Format.TextFrame2.TextRange.font
.size = 12
End With
I get the error:
"method textframe2 of object chartformat failed"
This is a very peculiar bug!
I guess it has to do with the fact that the XlCategory axis becomes vertical when you are using the "Funnel" chart type:
I've tried all the standard VBA ways I could think of and this doesn't seem to work. I even tried to see if we could save a funnel chart as a template and then use VBA to apply this template, but "Save as Template" is not available for some reason...
So, the reason why I'm explaining all this instead of writing a solution is because there is a workaround, but this kind of thing should only be used as a last resort. And if you haven't guessed it, I'm talking about using the SendKeys method.
Disclaimer: As always, using SendKeys is somewhat tricky and can lead to unexpected results. I would recommend reading some articles to get yourself familiar with it before using it. This article would be a good starting point.
Furthermore, to avoid any issues, don't run a macro that has the SendKeys method using the Run button in the VBE since the keystroke must be sent to the Excel window and not the VBE window. I suggest launching the macro using a shortcut to launch your macro. For example, you could use the Application.OnKey method by runnning a macro similar to this:
Sub SetShortcut()
'Set the shortcut for the macro to be CTRL+ALT+m
Application.OnKey "^%m", "NameOfYourMacro"
End Sub
An example using Sendkeys
The idea is to use Sendkeys to send the sequence of keystrokes that would give us the result we want. Here, we want to change the size and the font name of the XlCategory axis. By using the correct Alt key shortcut sequence we can achieve this. I'm not sure if the sequence is the same for all versions of Excel, but with Office 365, if we wanted to change the font name, it would be:
Type Alt - to initiate the Alt Key shortcut sequence.
Type "H" - to get the Home tab
Type "FF" - to select the Font Name text box
Type "Arial" and then press Enter - to change the font to Arial.
For this to apply to the XlCategory axis, we need to make sure that it is already selected before we run the macro. If it is selected, the following code should do the trick:
Sub ChangeCategoryAxisFont()
'Font Name
Application.SendKeys Keys:="%", Wait:=True
Application.SendKeys Keys:="H", Wait:=True
Application.SendKeys Keys:="FF", Wait:=True
Application.SendKeys Keys:="Arial", Wait:=True
Application.SendKeys Keys:="~", Wait:=True 'Press Enter
'Size
Application.SendKeys Keys:="%", Wait:=True
Application.SendKeys Keys:="H", Wait:=True
Application.SendKeys Keys:="FS", Wait:=True
Application.SendKeys Keys:="12", Wait:=True
Application.SendKeys Keys:="~", Wait:=True 'Press Enter
'Restore Numlock (which gets disabled when your macro runs at least one SendKeys command)
Application.SendKeys Keys:="{NUMLOCK}", Wait:=True
End Sub
If it is not already selected (even if the chart is selected), you might have another problem: if you include ActiveChart.Axes(xlCategory).Select in your macro, the options available in the ribbon won't be updated correctly and the macro above won't work. To let the ribbon update, we would need to end the execution of any macros for a brief second and proceed with our macro after.
For instance, you could use the Application.OnTime method to schedule the macro to run one second later, like this:
Sub PreSelectAxisAndRunMainMacro()
ActiveChart.Axes(xlCategory).Select
Application.OnTime Now + TimeSerial(0, 0, 1), "ChangeCategoryAxisFont"
End Sub
I know what you might think: "All this just to make some font changes?!". Yeah, I know, but at least if you become familiar with how to use the SendKeys method, you'll be able to use this in other contexts that require it...

VBA - Closing or clicking OK in MsgBox from another workbook,

Hi I the following code in Excel VBA,
Sub A ()
Workbooks.open ("A.xls")
ActiveWorkbook.Worksheets("1").Select
ActiveSheet.CommandButton1.value = true
End Sub
I'm opening another workbook (the code inside is protected so I can't modify the workbook "B") and clicking a run button on the worksheet, and it returns a MsgBox with OK button.
I want to know how I can use VBA to close this MsgBox or clicking "OK" ...I tried to use,
`application.DisplayAlert = false`
before opening the workbook "B" but this does not work..
Thanks for your help!
There might be an approach using SendKeys -- but SendKeys is notoriously temperamental. Here is a more reliable approach:
1) If you don't already have it organized like this, have the click-event handler of the button a 1-line sub that looks like:
Private Sub CommandButton1_Click()
Process
End Sub
Where Process is the sub which actually does the heavy lifting. In general, I think it a good idea to have event handlers mostly functioning as dispatchers to subs.
2) Change the code for Process (or whatever you choose to name it) in the following way:
a) Modify the first line to look like
Sub Process(Optional Verbose As Boolean = True)
b) Where Process has something like
MsgBox "Processed!"
replace it by
If Verbose Then MsgBox "Processed!"
3) In the code you gave above, replace the line
ActiveSheet.CommandButton1.value = true
by the line
Application.Run "A.xls!Process", False
This approach will bypass the button entirely and run the code which the button normally triggers, but run it in silent mode.
On Edit: To use SendKeys you could do the following. Put the line
Application.SendKeys "~"
before the line
ActiveSheet.CommandButton1.value = True
~ is the character shortcut for Enter. SendKeys doesn't itself send the keystroke, instead it puts something on the Windows Message Queue. VBA doesn't have any direct control about exactly when this message will be processed. In this case the lack of control is a benefit. The VBA interpreter moves onto the next line, which triggers the MsgBox. By the time the SendKeys message is processed the default Okay button on the message box has the focus hence receives the enter key. This can even happen before the box is painted, making it seem that the MsgBox was never there -- but that is better to think of it as being destroyed before you have time to see it.
The reason why it is necessary to have the SendKeys line before the line which clicks the button is that once the message box appears it will cause the VBA interpreter to wait until it is closed -- hence the calling code will suspend its execution until after the message box is closed, hence the SendKeys wouldn't be processed until it is no longer needed.
I don't really trust SendKeys. I suspect that sometimes when you run the code what will happen is that A1 in the newly activated sheet will receive the enter key (shifting the selection from A1 to A2) before the message box appears. I'm not sure if this can happen, but if it does a workaround might be to move the SendKeys to a VBScript program. Launch this program (with window minimized and not waiting for return) before the button is clicked. The VBScript program can have say an 0.5 second pause before it uses SendKeys. The script will be running in a different thread so it won't be blocked by the message box.

How to copy-paste from DOS application to Excel using SendKeys?

I'm trying to simulate this action:
activate another application,
send keystroke ctrl+c,
go back to Excel,
send key stroke ctrl+v
and have that value in a cell.
It's a DOS window style application, so keystroke is the only way to manage it.
I managed to activate and to input keystrokes such as ENTER into that DOS style application, but when I try ctrl+C it is not seen to do anything.
I tried simulating it in Excel VBA with:
Range("E7").Select
SendKeys "^c"
Range("G7").Select
SendKeys "^v"
The E7 value is not copied, but G7 (paste destination) is highlighted as if it was selected for copying.
Note: I am not trying to copy things from Excel to Excel, but to execute keystrokes using Excel.
I ran into the same issue today.
I solved it by waiting a bit after sending CTRL-C to the application. It seems nothing is copied if you immediately execute another script line.
SendKeys "^c"
WScript.Sleep 100 ' wait a bit after CTRL+C (otherwise nothing is copied)
In fact, the same issue seems to happen when switching to another app and sending CTRL+V.
Again, I solved it by waiting a bit:
AppActivate "Microsoft Excel"
WScript.Sleep 100 ' wait a bit after making window active
SendKeys "^v"
The problem is that copying and pasting takes some time and VBA is not waiting for it.
First you need to specify second argument of send keys method which is "Wait". Set it to true. Thus VBA execution is waiting for until sending keys is completed.
Secondly you need to wait until process of copying data to clipboard is completed. "Wait" in sendkeys is not doing it because it's not about sendking keys by VBA but it's about Windows working with clipboard. To do it please use my function IsCopyingCompleted.
Here's how final can look like:
SendKeys "^a", True 'Select all
SendKeys "^c", True 'Copy
Do
DoEvents
Loop Until Me.IsCopyingCompleted()
YourSheet.Paste
Function IsCopyingCompleted() As Boolean
'Check if copying data to clipboard is completed
Dim tempString As String
Dim myData As DataObject
'Try to put data from clipboard to string to check if operations on clipboard are completed
On Error Resume Next
Set myData = New DataObject
myData.GetFromClipboard
tempString = myData.GetText(1)
If Err.Number = 0 Then
IsCopyingCompleted = True
Else
IsCopyingCompleted = False
End If
On Error GoTo 0
End Function
I had this same problem - I developed code and it worked on my computer - SendKeys "^v"...but it did not work on another user's computer! I was trying EVERYTHING...delays, appreciate, accessig access from Excel, having the user check various settings, selection.paste...no good. Finally I noticed different syntaxes...we were using the same office version, I'm not sure about Windows. But I entered 6 different syntaxes and had it skip over if it failed....SendKeys with a capital v, enclosed in squigley brackets, each component in squigleys separated by a plus sign, etc. IT WORKED! 2 of the commands put the ^V in the body of outlook...I remove those 2 and I'm golden.

Resources