VBA Excel Not Responding when opened through QTP - vba

Action performed using QTP script --> After opening the Spreadsheet abc.xlsm ,when the Search macro is invoked, the search window opens and by providing search criteria in it when I hit "Enter" button, the Excel goes into Not Responding state (macro is not run completely) until the server itself gives the following:
408 timed out request
When the same above action is performed by manually invoking the spreadsheet. it works perfectly fine.
below is the code i am using to open the spreadsheet and performing Search macro run..
Dim wShell
Set oexcel= CreateObject("Excel.Application")
oexcel.Application.Visible=True
Set obook=oexcel.Workbooks.Open("C:\abc.xlsm")
Set osheet=obook.Worksheets("Search")
oexcel.Application.Run("search") 'This is the Search macro that we are runnig
wait 2
Window("search").Activate
Set wShell = CreateObject( "WScript.Shell" )
wShell.SendKeys ("%") ' this is the input search criteria
wShell.SendKeys "{TAB}"
wait 2
wShell.SendKeys "{ENTER}"
wait 5
After the above line of code is executed,the excel goes into not responding state.
However the same code works perfectly fine for another spreadsheet say xyz.xlsm for the same search macro. And it always works well manually.

XLSX/XLSM is not supported by UFT. Yea I ran into this as well. Real pain in the neck, but that's just the way it is. Just use old-style .XLS files and it will work just fine.

Related

MS Excel: using Shell in VBA to run an SSIS package as an embedded object in a worksheet

What I'm trying to accomplish:
I want to upload an Excel table to a SQL Server database table by pushing a button tied to a VBA macro.
I want the macro to wait for the process to complete before continuing.
My current method:
Currently, I have an SSIS package embedded as an object in a cell behind the button tied to the macro. My macro is pretty rough at this stage because I'm still trying to figure out how to run the SSIS package without it opening in the default app.
I want it to run in the background via a shell script. The macro would wait for a signal from the shell script saying that the upload was successful before continuing. I had this running previously with the SSIS package as an external file and ran the shell (which worked); but, I really want it to be contained inside the Excel file.
My code:
Sub UpdateGroupsMacro()
ActiveWorkbook.Save
ActiveSheet.Shapes.Range(Array("Object 1")).Select
Selection.Verb Verb:=Activate
' Shell ("DTEXEC.EXE /F " & ActiveWorkbook.FullName & "\xl\embeddings\oleObject1.bin""") <---This wasn't working even when I went one level deeper.
Application.Wait (Now + TimeValue("00:00:01"))
Worksheets("Macro").ListObjects("GetGroupsTableCount").Refresh
End Sub

MS Excel macro runs different from VB Script?

I have a VB Script file that I open using a task in Windows Task Scheduler each morning. The script opens MS Excel and then runs a macro stored in a workbook. The problem is that the macro runs differently if I use the VB Script file to kick off the macro versus when i run it myself from the workbook. Specifically, I find that "Refresh All" doesn't actually refresh all data connections when I run the macro starting from the VB Script file. It works fine if I run the macro from the workbook itself. I'm thinking that I am missing something in this VB Script to ensure MS Excel opens correctly and makes "refresh all" work properly. Anything plainly wrong with this VB Script?
Dim ObjExcel, ObjWB
Set ObjExcel = CreateObject("excel.application")
ObjExcel.Application.Visible = True
Set ObjWB = ObjExcel.Workbooks.Open("K:\Analytic Reporting\11.Projects\TonyAdHoc\Autorefresher\DashboardAutorefresher.xlsm")
objExcel.Application.Run "DashboardAutorefresher.xlsm!Main"
ObjWB.Close True
ObjExcel.Quit
Set ObjExcel = Nothing
It seems that you are trying to do a refresh to pull data from a database, but you are not seeing any new data from this script when you manually open the Excel file after the script runs.
You will need to save the Excel file after making modifications.
ObjExcel.Save
For anyone still caring about this, what I've found is that for connections to a database table, if the property "Enable Background Refresh" is selected, then the vba command in RefreshAll in the marco doesn't work. So I add a little loop to disable that property for all the connections just to make sure before I call RefreshAll. That fixed it for me.
' -- make sure enable background refresh is not checked else RefreshAll doesn't work
Dim cn As WorkbookConnection
For Each cn In ActiveWorkbook.Connections
cn.OLEDBConnection.BackgroundQuery = False
Next cn
' -- then ok to refresh all
ActiveWorkbook.RefreshAll

Why does Excel VBA calling an add-in function crash Excel?

I am running 32-bit Excel 2010 (Windows 10.1) with an add-in loaded (which I developed). I need to call one of the add-in functions (I will call it changeText) from VBA.
I've written the following VBA code behind one of the worksheets:
Sub MakeChange()
Dim result As String
result = Application.Run("changeText", "teststring")
Debug.Print result
Debug.Print "Complete"
End Sub
and assigned this Sub to a button on that worksheet.
If I run this function directly from within the VBA editor it works fine every time and returns the correct result to the Debug window.
If I call the function from within Excel by pressing the button, I get a Type Mismatch error (via a message box) the first time. If I then press the button again, everything hangs and the only way out is to kill the process.
If I move the function to a workbook-level module, more or less the same thing happens - I get a Type Mismatch error on the Application.Run line to which I click 'End', then the same again on the second click but this time the application hangs after pressing 'End'.
The add-in is mature and the function being called works perfectly when called directly from within Excel or otherwise invoked by the add-in. The XLL function being called takes a string and returns a string.
Does anyone have any idea what could be happening here, and in particular why the application is crashing?

Excel workbook only shows after running code is finished

I have a program in an Excel workbook that opens a Powerpoint-File, updates the links within this file and closes it after that. This works fine. Here is my problem: When the links are updated an Excel file with the source data is opened. After Powerpoint is closed this file stays open. I want it to get closed because I repeat this process for many files and I can't end up with hundreds of open Excel files.
I tried the following:
WBKs=Application.Workbooks.count
For i = WBKs to 1 Step -1
If Workbooks(i).Name<>ThisWorkbook.Name then
Workbooks(i).close savechanges:=False
End if
Next i
Now comes the weird part. Whenever I just run my code, WBKs always returns 1 and the Excel file only pops up after the code is finished. If I go through my code in debug mode it works. The workbook pops up as soon as I enter debug mode.
I tried Applicatio.Wait in the hope that the file would show after a second. The file only showed after the code was finished.
I tried a Do While Loop to wait until the file is open. Excel crashes because I never leave the loop.
Edit: I tried DoEvents as suggested. Does not work either.
This is just a workaround, but try using a brute force after x times your macro has run. Store that x somewhere in workbook, save. And kill excel process (all instances, including self) :
Dim sKill As String
sKill = "TASKKILL /F /IM excel.exe"
Shell sKill, vbHide
Found here : VBA script to close every instance of Excel except itself
When running your macro next time, you will use that x as a starting point for next PPT file to update.

VBA Project Password-Protect with SendKeys not Working Correctly

I've spent the last two days working on this problem. Most of the content I've found on this topic doesn't address the issue I'm having, so I'm hopeful that someone here can help me.
I've been working on some code that does the following from a "master scorecard" workbook:
Takes each "student" sheet in the workbook and copies the sheet into a new workbook,
Does a few minor manipulations of the new workbook,
Imports a module of code into the new workbook,
Adds a Workbook_Open event and a Workbook_BeforeClose event to the new workbook (to make certain sheets xlVeryHidden depending on level of access),
Runs a subprocedure from the newly imported module,
Saves and closes the workbook.
Each scorecard uses code to ensure that only the person whose name is on the scorecard can access it. I've used Environ("username") in the workbook events to ensure security, but as you well know, if one and understands how to run macros, he/she could merely open the VBEditor and unhide the xlVeryHidden sheets in the workbook very easily.
So, my thought was to password protect the new workbook's VBAProject programmatically (see above: step number five). I found a few sources online of how to use SendKeys to achieve this goal (see below), but SendKeys is unreliable (at best) and isn't cooperating with my code. The code works like a charm if I run it by itself, but if I call it from another project using Run Macro:="filename!macroname" it doesn't set the protection. After the code has run and all the workbooks have been created, the VBAProject properties window(s) from the earlier code are all open and try to execute at the same time which crashes Excel.
Sub LockVBAProject()
Const VBAProjectPassword As String = "123"
Dim VBP As VBProject, openWin As VBIDE.Window
Dim wbActive As Workbook
Dim i As Integer
Set wbActive = ActiveWorkbook
Set VBP = wbActive.VBProject
Application.ScreenUpdating = False
' close any code windows to ensure we hit the right project
For Each openWin In VBP.VBE.Windows
If InStr(openWin.Caption, "(") > 0 Then openWin.Close
Next openWin
wbActive.Activate
With Application
'//execute the controls to lock the project\\
.VBE.CommandBars("Menu Bar").Controls("Tools") _
.Controls("VBAProject Properties...").Execute
'//activate 'protection'\\
.SendKeys "^{TAB}"
'//CAUTION: this either checks OR UNchecks the\\
'//"Lock Project for Viewing" checkbox, if it's already\\
'//been locked for viewing, then this will UNlock it\\
.SendKeys "{ }"
'//enter password\\
.SendKeys "{TAB}" & VBAProjectPassword
'//confirm password\\
.SendKeys "{TAB}" & VBAProjectPassword
'//scroll down to OK key\\
.SendKeys "{TAB}"
'//click OK key\\
.SendKeys "{ENTER}"
'the project is now locked - this takes effect
'the very next time the book's opened...
End With
ThisWorkbook.SaveAs Filename:=Sheets(Sheets.Count).Name, FileFormat:=xlOpenXMLWorkbookMacroEnabled
Debug.Print "It Worked " & Now()
End Sub
I'm not sure why this is happening; like I said, the code works fine when run on its own. I found this post where this link to a non-SendKeys approach was outlined, but it was written several years ago and I'm not sure how I'd need to modify it for my purposes since I've never coded in VB6...
Are there any thoughts as to why the SendKeys method is bunching up after the code has already run instead of executing when it's supposed to during the code? Should I abandon SendKeys in favor of this other method? I'm at a loss, so any help will be much appreciated!
EDIT: I think the reason the code isn't working is because the correct project isn't activated at the time the SendKeys code is executed. I had hoped that activating the proper workbook would solve the issue, but it doesn't appear to have helped.
Ok, so after another couple of hours of searching the web for alternative methods to achieve my goal, I stumbled across this post.
I created a template workbook (with the event code already in ThisWorkbook), password protected the project, and modified my code to use the template workbook for each new sheet. Now when the sheets are created, the project is already locked for viewing and requires a password. While I realize the security under this approach isn't very secure, it will help "keep honest people honest" as they say.
For those who stumble across this post and still wish to programmatically lock/unlock their VBA Project, see these resources:
This SO post
This blog
Both are great resources that walk through a way to do it in VBA.
To add a nuance to the otherwise fine piece of code originally posted here: If you change the Project Name for the workbook within the VBE, you'll need to change one line of code to:
.VBE.CommandBars("Menu Bar").Controls("Tools") _
.Controls(VBP.Name & " Properties...").Execute
(sigh)