I need to process about 3000 sets of data through TableCurve 2D, to get the correlation coefficients of each data set, using the same equation model.
I have used autohotkey with success, but would rather use one program language (vba) instead of both vba and AHK.
With the below code, I am able to 1) Open TableCurve, 2) Import data from clipboard, and 3) Load the data for modelling.
Sub excel_TC2D()
TC2D = Shell("C:\Program Files (x86)\TableCurve2Dv5.01\TC.EXE", 5)
Application.SendKeys ("%FC~")
End Sub
But when I add more sendkeys to the one SendKey statement, it ignores them. I tried adding an application.wait, thinking that TableCurve 2D needed some pause time to complete the hotkey sequence, to no avail.
I tried adding one extra hotkeys, per the below schedule
Application.SendKeys ("%FC~%") ---> worked
Application.SendKeys ("%FC~%P") ----> worked
Application.SendKeys ("%FC~%PA") ----> worked
Application.SendKeys ("%FC~%PAL") ----> fails
I also tried splitting into 2 sets of Application.sendkeys as in the below, but it failed as well.
Sub excel_TC2D()
TC2D = Shell("C:\Program Files (x86)\TableCurve2Dv5.01\TC.EXE", 5)
Application.SendKeys "%FC~%PA", True
AppActivate TC2D, True: Application.SendKeys "L", True
End Sub
Any thoughts on why this and how to make it work.
Thanks,
Related
I routinely produce visio documents with images on each page that I paste in from another app. The files are large so need compressing, which isn't fun by hand. I want to be able to loop through each page and compress any images a set amount (75%). So far I've got a sub that selects all images on a page and I've got a sub that uses send keys to bring up the image compression window and run compression at 75%. The problem is the two won't run together. SendKeys compression works fine if I select all images first then run compression separately. But executing in the same sub doesn't work. Code I'm using below. All I can think is that something is breaking the sendkeys rhythm because instead of compressing I'll get mc 75 inserted as text below the image, which is the sendkeys keys. Or I'm stringing them together in the wrong way.
If I run the following separately they work. ie manually executing each one
'selects all images on a page
Sub SelectImagesOnPage()
Dim vsoSelection As Selection
'add all pictures to selection
Set vsoSelection = ActivePage.CreateSelection(visSelTypeByType, visSelModeSkipSuper, visTypeSelBitmap)
ActiveWindow.Selection = vsoSelection
End Sub
'uses sendkeys to bring up the compress image dialogue
Sub compressImageSelection()
'should check an image is selected.
SendKeys "%(jp)", True 'holds ALT while pressing JP
SendKeys "m", True
SendKeys "c"
SendKeys "{TAB}{TAB}"
SendKeys "75{ENTER}"
End Sub
But putting the two together like this doesn't work.
Sub compressPicturesOnPage()
'add all pictures to selection
Call SelectImagesOnPage
'compress
Call compressImageSelection
End Sub
Update: Turns out that for the context sensitive 'Compress Image' button and 'Picture Format' tab to appear on the ribbon menu all Sub's have to complete. ie. visio has to 'regain control'. Blows a hole in what I'm trying to do but at least I know now! Possible solution by Jon Fournier in the comments to try.
Is it possible to send a string and an enter with SendKeys?
I tried this:
Application.SendKeys "String? {ENTER}"
What am I doing wrong?
You should be fine submitting each key seperately, at least that is how i have done it when i have used send keys recently;
Application.SendKeys "MyString"
Application.SendKeys "{ENTER}"
I'm using excel 2013 and this works for me
Sendkeys "12345" & "{ENTER}"
It will output the 12345 and do a carriage return..
Makes the code a little cleaner to have all the text on one line for putty purposes
Previously I have succesfully used a variation of the code below. My code did not the Application. code. This should concatenate the two strings.
Application.Sendkeys "myString" + "{ENTER}"
Tested
SendKeys "myString" + "{ENTER}"
on Excel 2016 and it does work.
I have code that copies a code from excel and pastes it into and application. If the code succeeds the cursor in the application automatically highlights text 0. I then have the keyboard do "ctrl-c", which copies it correctly in the fact that I can paste 0 anywhere I choose by manually using my keyboard. But within the macro, using the paste function or directly accessing the clipboard doesn't give back this value, but other values copied in the macro at a prior line. Surprisingly enough, if I run my macro with a stop (big red dot) in the middle, after the "ctrl-c" command, it works fine, but then I have to run it in two steps.
Here's the code:
Public Sub CopyUPCtoRMS()
Dim UPC As String
Dim SomeInRMS As Boolean
Dim i As Integer
Dim sht As Worksheet
Set sht = Worksheets(1)
i = 2
'While Not IsEmpty(Cells(i, 5))
UPC = sht.Cells(i, 5).Copy
AppActivate "Retek - prd"
SendKeys "%r" & "{tab}{tab}{tab}", True 'reset the form
SendKeys "^v" & "{ENTER}", True 'paste UPC into retek
SendKeys "^c", True 'Copies '0' to a global clipboard.
'**I put a stop here and run the code in 2 portions as "Microsoft Visual Basic" lets you, and it works, but in two parts...
sht.Range("F10").Value = ClipBoard_GetText '<--- Pastes the UPC, not '0'
'Wend
End Sub
I've tried replacing the SendKeys with a function that does something similar to the same results (I can post that code if needed), to no avail. Anyway, that's all I can think of for now, it took several hours to figure out what was even wrong...
I've written an automation program like it seems you've done and have had similar issues. I think your last SendKeys call and the Clipboard_GetText call are happening in a timing where the copy function is not having time to complete before the next call executes. How I solved this in my application is grabbing the Sleep function from kernel32.dll (there is an article about it here: http://www.exceltrick.com/formulas_macros/vba-wait-and-sleep-functions/ - have to declare it differently for 64 bit systems) by placing this declaration in a place your code can see it (same module should be fine - all the way at the top prior to any functions or subs):
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
And then after each SendKeys call, you can force your code to pause a bit; since time is in milliseconds, 1000 is one second. So, for example, you can call
Sleep 500
and there will be a half second pause between the next line of code being run. I think this may work for you, because when you put a breakpoint (the red dot), have the code stop, and run it again manually, it works, apparently. So I think it may be a timing issue that Sleep can help you out with. If that's the issue, play with the sleep time to keep the operation time to a minimum. Good luck.
I have written a program to print multiple .pdfs with varying file extensions off of an Excel spreadsheet list.
The problem is that it takes anywhere from 30 seconds to a minute for the printer to receive the pdf after the line: Application.SendKeys "^p~", False is called.
To get by this I used Application.Wait (Now + TimeValue("0:01:03")) to wait for a minute (plus 3 seconds just to be safe) before closing the file.
To me there seems like there should be a better way than just causing the program to wait, so I looked around a little and found a question about this lovely gem known as Application.OnTime.
I tried a sample of one of the answers:
Sub test2()
ActiveSheet.Cells(1, 1).Value = ActiveSheet.Cells(1, 1).Value + 1
Application.OnTime Now + TimeValue("00:00:5"), "test2"
End Sub
However when I tried to stop the above code it kept going on an infinite loop and I was unable to stop it until I killed excel using the windows task manager.
I would like to be able to add in a little message box or something of the sort so that the user can click in between the wait time.
So that while the program is waiting for a minute, the user can either manually click and start the program on the next pdf, or click another button to exit if they need to stop printing early. Something like this:
Sub pdfPrinter()
'...
'Insert all the other code here
'...
Application.SendKeys "^p~", False
Application.OnTime Now + TimeValue("00:01:02"), "pdfPrinter"
continue= MsgBox("Click Retry to print again, or cancel to stop printer.", vbRetryCancel)
If continue = vbRetry Then
Call pdfPrinter
ElseIf continue = vbCancel Then
Exit Sub
End If
End Sub
Application.OnTime(unlike Application.Wait) is Asynchronous
so code after
Application.OnTime Now + TimeValue("00:01:02"), "pdfPrinter"
Runs Immediately.
If you want to print another PDF you need to call Application.OnTime with a different schedule of the 1st one.
Now, canceling Application.OnTime, when it is already started is a different story:
To do that you need to store that time that the respective function is scheduled to run and then Cancel it using the following code:
Application.OnTime Now + TimeValue("00:00:50"), "test", schedule:=False
I have a macro that takes roughly five seconds to execute and I'm using the code Application.ScreenUpdating = False so it looks like Word has locked up when it's running.
I use a message box at the end to tell them it's complete, but I'd like to display an image during its execution that tells the user the macro is running (primarily so they don't get worried, but also because it's nicer to look at).
There might be an easier way to go about this, but I decided to create an image, create a very basic user form, and simply set my image as its background. Then, I have that user form pop up as soon as the code starts to run.
The problem I'm having is that unless I close it, the rest of the code won't execute. It just hangs until I do something. Is there a way I can get the user form to be displayed without stopping the rest of the process? If not, is there another approach I can take to display an image while the macro is running?
You can show the userform as non-modal:
Userform1.Show False
'do more stuff (doesn't wait for form to close)
Userform1.Hide
I too have found that if you .show a userform at the beginning of the process, images contained within userform take a while to display and the result is less than smooth.
I have solved it by inserting a 1 second "wait" immediately after the userform.show instruction. In that split second, the image loads and displays successfully and the result is seamless.
Here the code. I have 2 macros: 1 to display and 1 to hide. I call the first macro at the beginning of the process just before freezing the screen and the second at the end of the process just before unfreezing the screen
Userform name is "myuserform"
Sub message_show()
userform.Show False
Application.Wait (Now + TimeValue("0:00:01"))
End Sub
Sub message_hide()
Application.Wait (Now + TimeValue("0:00:02"))
userform.Hide
End Sub