Excel Add-In - Alternative to ActiveMenuBar.Reset - vba

Problem: After an upgrade from Office 2010 to 2013, the Essbase Excel Add-in ("essexcln.xll", which Oracle ended support for in 2013) causes the focus to always return to a window with an active connection, when there is more than 1 window open. If the Essbase Add-In is loaded at startup, Excel also freezes. Note that Smartview has replaced this Add-In but for other reasons I need to continue using it. I can manually go to File > Options > Add-ins > Manage Excel Add-Ins and manually check/un-check when Essbase is causing these errors, but I'd rather do that with a quick keyboard shortcut.
Workaround: Create a custom add-in to quickly toggle the Essbase Add-In installed property to load and unload it. Maybe an add-in is overkill - but I don't really use a PERSONAL.XLSB, and I'd like this functionality to be available at all times.
Problem 2: When the Essbase add-in is unloaded, the "Add-in" Menu bar still shows a custom command: "About Oracle Essbase Spreadsheet Add-in." "Essexcln.xll" is notoriously buggy, and this "About Oracle Essbase Spreadsheet Add-in" can linger on even when the add-in is unchecked manually. My solution is to use ActiveMenuBar.Reset - only after I've unloaded the add-in. I don't want to reset if I've just toggled Installed to True.
Is there an alternative to ActiveMenuBar.Reset? This feels like a hack - kind of like using ActiveCell or ActiveSheet - but I don't want to manually check/un-check the Addin, which may or may not clear the "About Essbase..." anyway.
Notes: Yes, maybe it's not the most efficient to loop through Add-ins, but there's so few of them that I don't really care. I'd much rather avoid using ActiveMenuBar.
Sub Toggle_Essbase_AddIn()
Dim x As AddIn
Dim installed As Boolean
For Each x In Application.AddIns
If x.Name = "essexcln.xll" Then
' Get initial installed status
installed = x.installed
' Toggle
x.installed = Not x.installed
' Reset menu bar if Essbase was initially installed
If installed Then
ActiveMenuBar.Reset
End If
Exit Sub
End If
Next x
End Sub

As it stands, your code is incredibly inefficient, to the point that it's tough to explain why. Looking at the core of your procedure (after removing wasted space) we have:
Sub Toggle_Essbase_AddIn()
Dim x As AddIn, installed As Boolean
If x.Name = "essexcln.xll" Then
installed = x.installed
x.installed = Not x.installed
If installed Then
ActiveMenuBar.Reset
End If
Exit Sub
End If
End Sub
First off, this line does absolutely nothing:
x.installed = Not x.installed
...since it's after the value of installed has been set.
I can only assume that your intention was to toggle the value that's being passed to variable installed?
It will save you a lot of confusion if you get a little more creative with your variable names, instead of risking a word that, for all intensive purposes, could be considered Reserved. Without picking apart semantics, it is best not to name your variables with words that VBA wants to use for other things, and this is a perfect example why. Even if VBA doesn't get confused, you might, and you have an almost infinite number of other, more meaningful names to pick from.
Assuming that the intention was to toggle the value that's being passed to variable installed then you could have gone:
If x.Name = "essexcln.xll" Then
installed = not x.installed
If installed Then
ActiveMenuBar.Reset
End If
Exit Sub
End If
Preferably you should use Exit commands sparingly, or not at all -- only when there isn't an option to leave the loop/sub/if "naturally" but I'm not going into that now since it's irrelevant in a moment.
...or better yet:
installed = Not ( x.Name = "essexcln.xll" )
If installed Then
ActiveMenuBar.Reset
End If
...or even shorter:
If Not ( x.Name = "essexcln.xll" ) then ActiveMenuBar.Reset
...so now your whole sub would be:
Sub Toggle_Essbase_AddIn()
Dim x As AddIn
Dim installed As Boolean
For Each x In Application.AddIns
If Not ( x.Name = "essexcln.xll" ) then ActiveMenuBar.Reset
Next x
End Sub
...but you're still being unnecessarily inefficient.
There is no reason to loop through the AddIns. A quick Google of Application.Addins shows that it's easiest to refer to the Add-In by it's name.
I've never used Essex, but another quick Google to find the add-in documentation tells me that the name of the add-in is "Oracle Essex".
Therefore, one line replaces your entire procedure:
If Not AddIns("Oracle Essbase").Installed Then ActiveMenuBar.Reset
(or I'm not sure if it was intended to NOT be NOT because your code was unclear) - but this is far more efficient and does the equivalent of your code - as long as you're sure the add-in actually exists (not the same as installed, Google it), then this does the same thing as your entire procedure.
If you're not sure if the add-in exists, then Google saves the day again with a link to a Stack Overflow question.
Since I don't have the add-in and you haven't included any specific example of the problem, I can't say for sure if this answers the question completely, but I assure you that taking some extra time on one's own due diligence in coding will safe a lot of effort for you - and others - in the end.
Heads up, I had a lot to write here to get to "one line" so I can't guarantee there were no oversights, but the lesson here is more about research-before-coding.
I suggest you study the documentation about add-ins and toolbars at MSDN as well as documentation specific to the 3rd party add-in at Oracle (via the links above, and sub-links from those pages) and I am confident that with some effort your solution will become clear.
If not, I suggest you add more information to your question. ...and please, don't attempt to write any "add-ins for add-ins"!
Good Luck (and welcome to Stack Overflow!)
...and after all that, I notice that you added a link to an image instead of adding an image, so it would have been more noticeable. I can't tell without clicking the toolbar but I'm pretty sure that's not a menu bar command. That's a ribbon group, and it's empty.

Related

MS Office - ActiveX Buttons switching places

There are several instances of this problem, but this one is predominant. This is in relation to updates (our most notable problem child being KB2726958). We have a Leave Spreadsheet that looks like this:
Leave Spreadsheet example
By pressing the grey Leave button, you end up here:
Leave Word doc
All the programming for these is written in VBA (i've never worked with VBA before, I can understand it to a degree).
Now, the issue is that using the ActiveX button in the 'Leave Spreadsheet example' causes the 2 buttons 'Send by Email' and 'Save' to switch functions; Send by email attempts to save and save opens up Outlook and creates the email message.
Both functions have completely retained functionality, just on the wrong buttons.
The thing I find weird is that a hyperlink to the very same file works; the buttons aren't switched and have full functionality. The only hint that I have towards resolution is that when using a hyperlink, it's directly opening the file. When using the ActiveX button, it seems to be creating a new file based off the file it's linking to. For example, the hyperlink directly opens C:\Report.dotm but the ActiveX button opens Document1.doc with a template based on Report.dotm.
I'm considering that maybe the activeX button is opening up Word with an incorrect extension? But i'm not sure how to figure this out (code below shows that the linked file on the activeX control is a .dotm).
What further throws a spanner into the mix is that it only affects some computers... Considering on-site we all use the same type of PC with the same image... :(
My question is, does anyone know why they may be swapping? They're located on the same network drive albeit different directories. They require the same permissions to access. The code for the buttons is as follows:
Excel Button:
Private Sub CommandButton1_Click()
' This button links the excel spreadsheet to the word doc
Dim wrdApp As Object
Dim wrdDoc As Object
Dim i As Integer
Set wrdApp = CreateObject("Word.Application")
wrdApp.Visible = True
Set wrdDoc = wrdApp.Documents.Add("\\networkdrive\directories\Request for Leave.dotm")
End Sub
Word buttons 1 and 2:
Private Sub cmdSend_Click()
' This is the code for the button 'Send by Email'
MsgBox "Send the following email to your Team Leader/Line Manager", vbInformation
SendDocumentAsAttachment "", "IPL Request for Leave"
End Sub
Private Sub cmdSave_Click()
' This is the code for 'Save'
modSend.SaveLeaveForm
End Sub
Please Note: The comments above are not in the code in VBA, i've written them in myself in this question to provide clarity.
Troubleshooting that i've done:
Removing all .exd files
Running the MS Hotfix (removes all .exd files in a GUI)
The next step would be to try running all 6 patches related to fixing ActiveX controls with the particular patches we've done to see if that fixes the problem. The reason I haven't done this yet is because of ITIL (Change management) although I may try testing this later today.
What is the outcome i'm after?
Ideally, I want to understand what is causing these buttons to, from what it looks like, swap their functions. I have different scenarios of button swaps, some of which are remedied by removing the .exd files, and some that aren't.
By understanding what is happening, I hope that I can apply the knowledge to the other scenarios (same problem, different coding).
Then, I'll be able to document my findings so that when we perform the next round of patching that is known to break ActiveX controls, my organization will know how to deal with it.
So the patch mentioned below has fixed this issue. There's still some other issues that I need to test this patch against, but I definitely should have started there. Lesson learnt.
From my work email:
I’ve just tried using the patch related to the ActiveX controls breaking, KB2920754. I’ve used it on two PC’s here in the training room; both had different issues:
- The first one had buttons that had switched around (save attempted to email, email attempted to save)
- The second one couldn’t use the buttons at all.
This patch cured both w/o requiring a restart or logging out and back in. I didn’t remove any .exd files, either.
It does state, however:
“Important For this fix to be fully effective, you also have to apply the other patches for Office 2013 that are listed in the "Resolution" section of the following Microsoft Knowledge Base article”
There are 6 in total.
Patches:
1. KB2920754 – (the one I’ve used successfully)
2. KB2956145
3. KB2956163
4. KB2965206
5. KB2956176
6. KB2956155

Background macro/subroutine which is not shown in the Call Stack

I have a workbook with lots of sheets and several macros. When I enter VBA and try to write a new Sub into ThisWorkbook module, I see:
"This will reset your project, proceed anyway?"
assuming, that some project is currently running.
If I press Ctrl + L right after opening the file to check the Call Stack, it just shows nothing.
I did non run any macro myself and there's not a macro, which would handle any event (as far as I checked all sheets and modules in the project) except a little sub for saving event:
Workbook_BeforeSave (ByVal SaveAsUI As Boolean, Cancel As Boolean)
but this one AFAIK should be activated only before saving, thanks to Captain Obvious.
Another mysterious thing with this book is abnormally slow filtering for structured tables, which may be cured by turning off event handler:
Application.EnableEvents = False
Since both these facts are related to Events, I guess they might be somehow connected to each other.
Updated to include comments below.
Well, the problem still exists and I appreciate any idea that may help to locate this pesky macro running totally hidden.
Hm. Anyone with any ideas?
One way to reproduce the behavior that you describe is as follows:
1) Have a public variable which is initialized in Workbook_Open()
2) Have the option Notify Before State Loss enabled (under Tools/Options/General)
In this case when you first open the workbook and try to create a sub you see the warning about resetting the project even though no macro is currently running.
If this is the case, a simple fix (if it still bothers you) is to disable Notify Before State Loss.
On the other hand, it seems that your project has more general problems. VBA projects can become inexplicably corrupt and this might be the case here. A fix which sometimes works is to export all modules, userforms, etc., delete them, and then reimport them. Rob Bovey (a highly respected VBA guru) has written an add-in called Code Cleaner to automate the process. I haven't used it personally but it might be worth a try.

Application.OnTime in Add-In Workbook_Open

I've built a custom Excel add-in and I'm currently trying to figure out a way to prompt users via VBA when new versions of the add-in are available.
I tried just using the workbook_open event to check for the latest version and then prompt the user with a userform, but I discovered that when Excel loads an add-in that trigger a userform, Excel stops loading the workbook the user actually tried to open and reloads the add-in. So while the userform works like I wanted, the user gets a blank (read no sheets) Excel shell with a loaded add-in.
So I considered using Application.OnTime to postpone the VBA until after the add-in and target file were both open. I got the impression both here and here that this is possible, but I am only able to make it work in an .xlsm file and not a .xlam file.
Here's the code I'm testing with:
Sub Workbook_Open()
Application.OnTime Now() + TimeValue("00:00:05"), "Test_Addin.xlam!Versioning.Notify_User"
End Sub
And in a regular code module:
Sub Notify_User()
MsgBox "Hello"
End Sub
So, my question: Am I doing something wrong here?
I'm wondering if there's something about how an add-in is loaded/designed that keeps it from allowing this type of action to be performed.
Alternatively, is there a different way to do this that you can think of?
I read an interesting blog post (and comments) by Dick Kusleika on this topic, but it sounded like some people put a version check in each sub procedure... I have a lot of procedures, so this doesn't sound like a good alternative, although I may have to resort to it.
Well, time is of the essence so I resorted to the least desirable option: a check at the beginning of each procedure.
To the interested parties, here's how I did it:
Somewhere towards the beginning of each sub procedure I put this line of code:
If Version_Check Then Call Notify_User
And in my Versioning module I put this function and procedure:
Function Version_Check() As Boolean
Installed = FileDateTime(ThisWorkbook.FullName)
Available = FileDateTime("\\NetworkDrive\Test_AddIn.xlam")
If Installed < Available Then Version_Check = True
End Function
Sub Notify_User()
Update_Check.Show
End Sub
So each time a procedure is run this code checks for a version on our corporate network with a modified datetime greater than the datetime of the installed add-in.
I'm still very open to alternative ways of checking for new versions so feel free to post an answer.

Spurious change in code name of ActiveX control command button

Not a duplicate because the issue described here happens despite having deleted the *.exd files as suggested in the answer to Excel renaming Activex Controls on other computers and elsewhere.
One particular machine on our network (let's call it "Computer 2") spuriously and silently changes the code name of ActiveX command buttons placed in Excel workbooks. Whatever the (Name) property of a button was before, it returns it to the default CommandButton* scheme. (CommandButton1, CommandButton2... etc.)
Witness the screenshots below. The code name of btn2 changes to CommandButton1 when opened on Computer 2.
Why? How do I fix this?
I can even have the exact same workbook opened from the same Book1.xlsm file on a network drive simultaneously on both machines (one of them read-only, obviously). Looking at both screens at the same time, the button names are different! Computer 2 changed it.
This, of course, breaks the functionality of the buttons, because they no longer trigger their intended event code. In the example below, btn2 used to call Private Sub btn2_Click() from the sheet module and execute the code in that Sub. But on Computer 2, the button is no longer named btn2, so it doesn't trigger that event; it does nothing — or worse, if there happened to be a button called CommandButton1 before, it triggers that unrelated event.
Workbook opened on Computer 1:
Exact same workbook, but this time on Computer 2:
Now, this has happened to me before. Once or twice over the years, on a couple different machines, all my commandbuttons got renamed like that. But I've never been able to reproduce this, and I thought, corrupted workbook, no big deal.
But this happens consistently on Computer 2, every single time.
Non-ActiveX, Form Control buttons, such as "Form Button 1" in the example above, are unaffected by this issue. An obvious but tedious fix would be to get rid of all my ActiveX buttons (as suggested in this answer) and convert them into e.g. Form Control buttons, but the aim is to avoid this nuclear option.
First, I have very limited knowledge of VBA.
Second: I have no idea why this happens, but I have an idea for how to fix it... In workbook_open could you run code that renames any CommandButtons to your desired name? It would be annoying, sure, but it would be at least a temporary fix until someone can find out why on Earth this happens! :)
Sub Not_Workbook_Open()
Dim btn As OLEObject, increment As Integer
increment = 1
For Each btn In Sheets("Sheet1").OLEObjects
btn.Name = "btn" & increment
increment = increment + 1
Next
End Sub
Since none of any recommended solution worked for me, I am assuming some people still have that problem and are interested in the fix that helped me:
Make your button names shorter!
Sounds stupid, but I found out that button name length has it's limits.
Try this out by making a new sheet with one ActiveX CommandButton in it.
Then add this code and execute it repeatedly by pressing F5:
Public Sub test()
For Each o In ActiveSheet.OLEObjects
Debug.Print Len(o.Name); Tab(5); o.Name
o.Name = o.Name & "X"
Next
End Sub
You will notice that the code stops executing after
31 CommandButton1XXXXXXXXXXXXXXXXX
And yeah, I found this fix because I was desperate enough to try seadoggie's solution, which failed because you can't read a button's caption to identify which name the button should get. :)
A colleague found out that this can occur if there is a mix of Office 2010 and Office 2013 products installed on a machine. The procedure to fix this is:
Download these patches:
Office 2010 patch: http://support.microsoft.com/kb/2553154/EN-US
Office 2013 patch: http://support.microsoft.com/kb/2726958/EN-US
Close all Office programs (including Lync if you have it).
Install the Office 2010 patch.
Install the Office 2013 patch.
Remove *.exd files from your profile and for all other user profiles. For instructions, see this Stack Overflow answer and this Microsoft solution.
Restart your machine.

Sheet.Activate is not working in Office 2010 - 64 bit

I have created a Macro which is working just perfect in my machine (Windows 64 bit & Office 32 bit)
But client is facing issue. He is having Windows 64 bit & Office 64 bit.
Don't know why but Sheet.Activate is not working on his machine. Refer below screen prints.
Based on your input, I cannot find back a declaration of "Recordsheet".
Since you input this code in the event routine "Workbook_open", I doubt that you did the declaration anywhere.
If you want to apply
RecordSheet.Activate
The least thing you should do is:
Set oRecordSheet = thisworkbook.sheets("Records")
oRecordSheet.activate
I strongly doubt that your version of Office / Windows has anything to do with it.
Vba is not supported by Microsoft anymore and no further developments to the language are made.
If it's a client, take into account the possibility that this client might have changed the name of the sheet.
In case you properly set the sheet object, this may also be the source of the problem.
Edit:
After looking at your file received by mail, I confirm that the above solution fixed the bug.
Replace the entire
UserForm_Initialize
Subroutine with:
Private Sub UserForm_Initialize()
Dim oRecordSheet As Excel.Worksheet
Set oRecordSheet = ThisWorkbook.Sheets("Expense Report")
oRecordSheet.Activate
EnableDisableConrols (False)
Call FillDropDowns
Navigator.Max = RecordSheet.UsedRange.Rows.Count
If RecordSheet.UsedRange.Rows.Count = 1 Then
RowNumber = 1
Else
RowNumber = 2
Call FillDataIntoControls
End If
End Sub
Edit 2:
The above solution is correct, BUT, if indeed the codename of your sheet is set to RecordSheet, you can use this solution too. However, note that the codename can only be used with the workbook.
I would think there may be missing references.
go to Tools -> References, and see if any are listed as missing
Remove the checkmarks there, and the basic stuff like date will start working again. If those references are critical to the code you are running, you will have to search out the 64 bit equivalents
More about references - normally resolving "Missing" fixes it, but, from here
What you're describing is typical of corrupted references. This can
be caused by a referenced file being a different version or in a different
location between the machine on which the code was developed, and the
client machines. Our company also tries to keep all the machines configured
the same way, but I've found it's essentially impossible to manage.
Open any code module (or open the Debug Window, using Ctrl-G, provided you
haven't selected the "keep debug window on top" option). Select Tools |
References from the menu bar. Examine all of the selected references.
If any of the selected references have "MISSING:" in front of them, unselect
them, and back out of the dialog. If you really need the reference(s) you
just unselected (you can tell by doing a Compile All Modules), go back in
and reselect them.
If none have "MISSING:", select an additional reference at random, back out
of the dialog, then go back in and unselect the reference you just added. If
that doesn't solve the problem, try to unselect as many of the selected
references as you can (Office may not let you unselect them all), back out
of the dialog, then go back in and reselect the references you just
unselected. (NOTE: write down what the references are before you delete
them, because they'll be in a different order when you go back in)
(as a side note, disambigulating as VBA.xxxx will work, since Excel no longer has to
look through all of the references.)
The first line of your code shows a UserForm. Some widely-used form controls (those defined in the ComCtl library) don't exist in the 64-bit version of Office so it's highly likely that the UserForm is the problem.
There's no easy solution unless you can convince the client to use 32-bit Office instead or alter your UserForm so as not to use the affected controls.
Affected controls are: ImageCombo, ImageList, ListView, ProgressBar, Slider, StatusBar, TabStrip (although there is an alternative version of TabStrip in the normal MSForms library), Toolbar, Treeview
Details of the problem are discussed in this thread and confirmed here