Excel workbook with macros using 50% CPU even when idle - vba

First:
Using excel 2010, Win 7
All additional add-ons have been disabled
All spreadsheets have had the last used cell reduced to its minimum row, column value
I have an old machine in today's standards, Dell Inspiron 6400, 1.73 GHz, 3.3 Gig ram
I have a spreadsheet that when open and active it uses at least 50% of the cpu even when idle. If I then run other programs this has caused the computer to over heat and shut down. I posted this problem on a different forum a few months ago and the end advice was, "Don't worry about it". Well, I can no longer do this. It's become a problem.
At first I thought it was any workbook with macros. I have since convinced myself this is not the case. I then thought it might be add-ons that I have add. This isn't the case either. I read to minimize the spreadsheets to their smallest size. This didn't help. This workbook has an auto-open which saves a backup, gathers some data off the internet and does some manipulations with that data. I totally removed this subroutine, and no effect. Another thing to note is if I open another workbook, leaving this open too, and make this second workbook the active workbook, te cpu usage goes to nearly zero. One last thing to note is I have several precursors to this "final version" of this workbook. They all do not have this cpu problem. Somewhere, somehow, I have added some code to this "final version" that is causing this problem.
I'm hoping someone can give me some clues as to what else to look for. I will be comparing these old backups to the current version, but this is going to be the long way around. Any advice would be greatly appreciated.

Subject to my earlirt comment, when the Auto_Open macro ran everytime the workbook was opened, it created a new connection to its Internet data without discarding previous ones. These ancient connection should be listed Data ► Connections ► Connections and/or Data ► Get External Data ► Existing Connections.
As I do not have the full method and parameters of the internet connection created, I'll offer this sort `` event macro that will remove all connections whenever the workbook is closed.
Private Sub Workbook_BeforeClose(Cancel As Boolean)
With ThisWorkbook
Dim cn As Object
For Each cn In .Connections
cn.Delete
Next cn
.Save
End With
End Sub
That macro goes into the ThisWorkbook code sheet. Note that it also saves your workbook; if this is not wanted behavior, move the code to a Module sheet and change it to a public macro that can be manually run.

Related

How to save two workbooks as and mirror the connections that they contain

I need some conceptual help from those more experienced than me --
I know you guys usually like code but I have many pages of code on this project and my question is not regarding any code I have but rather how I might code something I have not been able to figure out.
So basically I have two workbooks whose main purpose is labor tracking. one is the control workbook that has all my code, the other is a workbook where reports are made by field workers. The reason the field workbook cannot have code is because it will be operated from an ipad which I believe cannot yet run VBA. I know how to establish the connections necessary, however for every project a new copy of both the workbooks need to be made. I already have functions that clear out, reset and save the main workbook however I am struggling with the connected workbook. I know how to save the connected workbook, but I was hoping to preserve the connections between the two old workbooks when I run the macro that saves them as and also mirror those connections between the new workbooks. Is this possible or will I need clear all connections and re establish them every time a new set of job books needs to be created?
===> EDIT: I believe that I need to embed the report book into the main book, but that still begs the question on how I save the embedded workbook as at the same time I save the main workbook as in order to create a new book with all the same connections

Distributing macro as an Add-In to other users

I am looking for some tips how to resolve a problem with distributing macro to other users in my company.
I’ve created a specific workbook which holds a bunch of various types of data such as dates, strings and numbers. Each of the users have to manage the same types of data, so we use this workbook as a template. Data is stored in a columns to which I’ve applied a conditional formatting and data validation to prevent users from inserting wrong values. This Workbook contains few Worksheets with specific names. Names of this worksheets appear in the code – to make some specific calculations for each one of them (based on the name of the worksheet).
The problem is that there is a probability that in the future I would like to make some changes to the code for example to make my macro more efficient or to implement some changes that are necessary.
I’ve searched through the internet to find the best solution and I think the best is to create an Add-In to Excel. But I’ve some questions about that.
Is this really the best solution? Can someone give me a hint to make it in a better way?
If Add-In is the best, is there a way to add this only to specific workbooks (which are my template)?
Is it possible to install Add-in when someone opens a specific workbook (using Workbook_Open) and uninstall it when workbooks is closing (using Workbook_BeforeClose). I’ve looked for answers on the web, but this matter is not clear to me. If this is possible, would it affect speed of the closing/opening workbooks?
Thanks for any help/advice!
Put the add-in on the network drive and mark it as read-only. Use a local copy to make updates. Make sure to set it to read only each time you copy it, and make sure people are running off the network drive.
Often times when people install an Add-In, they answer YES to the question about copying it to their local drive and that is not the right answer. If they accidentally click YES you will need to edit their registry to remove the local reference.
For distributing an add-in through a shared drive with your own development copy I would highly suggest to read the following link.
It has a description of the installation process, including a very important point that braX brought up in his answer - answering No when asked about copying to personal add-in folder.
Below is an adjusted code from the link that I use to save add-ins. It goes into a normal module in the add-in itself. It saves an add-in a folder and sets its attribute to Read only so that whenever it is used by somebody it will not be locked. This setup allows you to update the file by running this macro at any time without needing to chase down users and get them to close Excel.
Private Sub Deploy()
Dim FolderOnSharedDrive as String
FolderOnSharedDrive = "Folder path to store add-in in here"
With ThisWorkbook
On Error Resume Next
SetAttr FolderOnSharedDrive & .Name, vbNormal
On Error GoTo 0
.SaveCopyAs FolderOnSharedDrive & .Name
SetAttr FolderOnSharedDrive & .Name, vbReadOnly
MsgBox "Deploy Completed to " & FolderOnSharedDrive & .Name
End With
End Sub
It is a good idea to add checks for filepath and perhaps some error-handling.
As to some other issues you bring up:
Add-ins can include worksheets that are not visible that you can use to store settings, paths, etc.
It is possible to make add-in appear only on specific workbooks but it will take some effort:
Include a ribbon for an add-in that includes callback for visibility. Set it to visible whenever specific workbook(template) is active. It will still be loaded to memory in any Excel instance
You can programatically add add-ins on open and remove on close as you suggested, check this question to see some options.
Adding/removing add-ins on close or open will definitely affect the speed, but I cannot say if it will be noticeable.

Prevent >1 person from running VBA macro at a time (shared wkb)

What I'm aiming at is getting a list of all currently running scripts in order to check if other users aren't running the same VBA macro at the same time (and if yes, then stop the code etc., similar to what the OP of the below question wanted). This would be for a shared workbook (I learned it's not designed for this type of work, but I need to try it).
https://stackoverflow.com/a/36116091/5947935
I've been trying to make the code in the above answer work in VBA, but it seems it's a vbs thing and I would like to avoid that.
I'm not an expert to say the least, so I'm having trouble understanding how to get this to work in Excel VBA. I don't even know if it's possible at all.
I've found this as well: VBA Getting program names and task ID of running processes and it works fine but it only lists the running processes.
I've no idea however how to merge the two... or even if the WMI is the correct way to go.
I'd appreciate any sort of help.
I used to create a "locking file" which was just an empty text file with the name of the workbook followed by the username and an extension of .LCK
First thing my code did on auto open was look for a locking file then report back to the user which user had it open then cancel the open.
If it didn't find a locking file then it created one and proceeded as normal. If it found one but it was the same username (ie that user had it crash on them) it proceeded with the open.
The last thing the code did was delete the file.
No codes here and theory not tested yet, but the idea of preventing a different user executing a Macro on a shared workbook requires some thinking.
I would create a hidden worksheet, and use one of the cells to store the Environ("USERNAME") when the macro is first started - to indicate who has it running, then clear it when complete, first-in-first-out.
Lets say named range MUser (macro user) is range A1 in that hidden worksheet
When the macro runs, it will first check if MUser is empty, if so then change it's value to Environ("USERNAME") and Save the file before next step (here I am not certain the value is updated on others session).
If MUser is not empty, either abort or retry in a few second.
When macro completes, MUser will be ClearContents, and save the File to free up the workbook for macro.
Idea is here but please test. Post your own code for us to troubleshoot. You may also use Workbook events to "lock" the macro execution this way. Or even use this hidden sheet to make a log record for debug. Also some fail-safe needs to be implemented (such as a time stamp at macro start and override the lock after some minutes).

Excel. Use vba to record when someone removes the shared feature

We have a problem at work. Im not sure if this is due to an individual or the system admin applying patches during working hours but... we use an Excel sheet at work to track engineering work. It is a shared workbook so that multiple people can work at any time and is working well. Recently people have been losing their work because something is removing the shared status from the file during the day. It is only discovered when people go to save their work or open the workbook again after lunch. Is it possible to write a macro that records when the shared feature is applied or removed. I assume it is a property of the workbook collection/object but cant see how to do it from the docs
Take a look at the Workbook.MultiUserEditing property.
This code snippet (from Microsoft help) would save the workbook in shared mode if the workbook is not currently in shared mode.
If Not ActiveWorkbook.MultiUserEditing Then
ActiveWorkbook.SaveAs fileName:=ActiveWorkbook.FullName, _
accessMode:=xlShared
End If
You may consider placing this code (or similar) in the Workbook_BeforeClose() event or other relevant event.

Excel VBA: More efficient way to pull in data from another workbook?

As a temporary fix before we transfer the process over to our CRM system, I've written a tool with Excel/VBA that allows the user(s) to do some territory planning.
This tool opens a workbook that's located on a shared directory. It then pulls in data to the user's workbook on hidden sheets. The user then makes their desired changes via sheets they can see (there's a save button on these sheets that changes the appropriate data on the hidden sheets).
When the user is done making all desired changes, they hit a 'confirm' button. There is then a macro that reconnects to the workbook on the shared directory. It pushes the data back to this workbook on the shared directory. This workbook is [shared] so that more than one user can make changes concurrently, and the code is setup to prevent data from being overwritten inappropriately.
That said, I've come up with an annoying problem. We have offices in many locations internationally. It appears that the connection speed of users varies greatly. Users that have slower connections are encountering the following error:
'Microsoft Office Excel is waiting for another application to complete an OLE action.'
I suspect this is due to slower connections as microsoft's support site states that this error can come up when excel attempts to interact with another application which does not respond in a timely manner.
This error is coming up when the macro attempts to open the workbook in the shared directory, so connection speed is the main issue that makes sense.
I have discovered that I can block this error by using Application.DisplayAlerts = False but a better fix would be to make this process more efficient.
So my real question is, is there some more efficient method I can use to pull in that data, other than opening up the workbook?
Edit: Code where the worksheet opens the shared workbook:
Dim xlo As New Excel.Application
Dim xlw As New Excel.Workbook
Dim xlz As String, regions As String
xlz = Sheet1.Range("o1").Value & "\Region Planning\TestDB.xlsx"
Set xlw = xlo.Workbooks.Open(xlz)
Cell O1 contains the drive letter for the shared drive.