END GAME: A user saved Workbook opens and mirrors code from a target file.
I am trying to create a simple VBA application that has an Excel front-end and an Access back-end. There will be multiple users who would have the option to save the front-end Excel piece anywhere they desire.
I would like to know the most efficient way to be able to update macros in all user instances when I need to push updates.
Essentially, I would like to mirror code from a "global" file on Workbook_open. In the past I did actually set code to open a separate workbook and run code (dim x as workbook, open, app.runmacro and etc.), But I think that is not really the most efficient way to do it.
Four possible solutions pop to mind for this (other than your option of having an intermediary workbook), there are likely others:
Treat the Workbook as purely an interface, and move the code to the
Access database and have it accept the Workbook as a parameter if
needed. The advantage would be the code could be maintained in one
place (Access), but it would have two main disadvantages. Each user
would need to have Access installed in order for it to instantiate
the application to call methods on, and it would lock in your
"interface" - that is, changes to how it calls Access macros would
still require Workbook updates.
Create a canonical Workbook and have the user Workbook version check
against the canonical Workbook when opened. If the version is
different, open the new one, move all of the data to it, delete the
old one, and save the new copy to the same filename as the old one.
The main disadvantage of this method would be ensuring that old code doesn't run might be difficult, as you would need
to take measures to prevent situations where the user could abort
the update process and still have a working copy of the old code.
Automate the VBE (see this answer for implementation details -
there are numerous resources on how to do this). Depending on how
you wanted to do this, you could either store the current modules as
files and import them, or store the code in the database itself and
query for it. The main disadvantages of this method are that the
VBE can be fickle about changing code that is actually running. I'm
not sure that I'd trust it to change it's own implementation. You
would also need to allow access to the VBE in each user's security
settings, which may pose a security threat.
Store the location of the Workbooks themselves in the database, then
push out updated copies with external code. The Workbook would
report it's filepath when opened, and if it wasn't already recorded
in the database, check to see if it was the most current version,
and then write a record for itself. This has the disadvantage of
only being able to inform the user that they don't have the current
version if they (for example) move the Workbook in Explorer and
don't open it until after your push.
Note that these are all "pull" type as opposed to "push" type solutions with the exception of the last one. Regardless of the method you use for version checking, any push solution is going to share the disadvantage of number 4 - there is no reliable way to make sure that a push catches all the invalidated versions.
Related
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
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).
first time asking something here, so I'll apologize beforehand in case I do anything I shouldn't do.
I'm working on a workbook and there are some information in it that shouldn't be available to everyone else, save a few users.
While doing some testing around I've found that it was possible to use another instance of Excel, i.e. another workbook, to access that information (in this case, using VBA).
What I want to know is: is it possible to block another instance of Excel or another workbook from accessing this workbook with the information I want to protect?
The point of this sheet in working on is to be used as a 'database' of sorts for performance feedback of other employees. They fill a form with their self evaluation and then their manager also fill it, evaluating them. All this is stored in a sheet, which is hidden (veryhidden, to be more specific). Using a simple login system, I was able to enable access to this sheet to only one user (one with admin privileges), but assuming someone knows the existence of that sheet, it would be perfectly possible for them to, for example, just copy everything from that sheet to a blank sheet in a new workbook.
Ultimately, what I'm trying to achieve is some kind of restriction in this workbook, allowing only it's own subs and functions to work on it
Thanks in advance
EDIT: Added some info. Hope that helped clarify my problem
The only way to achieve this is encryption. As far as I know Excel only supports one form of encryption, full workbook encryption. In that case there is a password to open the workbook, a user either has access to the full workbook or none at all.
Any other form of encryption in Excel, protected cells, passwords on macros, etc. can all be bypassed easily by a knowledgable user.
However, you could achieve this using either an external database server or implementing your own encryption scheme in the workbook.
There is some information here on howto access the Windows CryptoAPI from VBA.
I am currently writing an utility that takes two different sets of data from an excel document and sends it to two different web services. Each set of data has it's own button that sends the data to the web service. When the a button is clicked, the corresponding web service then returns data depending on the input values.
What I am trying to do is so that this utility can be distrobuted and used by a wide variety of people. What they are going to do is they are going to be synchronizing there particular cells of their own excel document to the corresponding cell in my utility. Using simple excel formulas. For example:
c:\temp\[book1.xls]sheet1'!a1
Now what I am trying to do is automatically "click" the button, or update, on my utility when the user links their cell to its corresponding cell on my utility.
I have tried the selection change event on my page. But it doesn't actually process until my utility is active, or clicked on.
Is there a way to make my utility automatically update? It would be especially awesome if somehow it did this while my utility was closed. So when the user opens it it is already filled with their information, and the outputs are correct.
The requirements:
you need to guarantee that when a user is using excel your app can collect the data. Your app may not be running at the time. You need the Worksheet_SelectionChange() event to fire automatically not just when your app is active.
Solution:
Basically in order to guarantee that the Worksheet_SelectionChange() is running all the time, and in order to guarantee that whenever the user opens an instance of excel you are able to collect and process the data/formulas entered into the particular target range address you need to wire up the selectionchange event inside of a VB.NET Excel COM Addin. There are several ways to do this, but since your using VB.NET your best off using the newest approach which is building a VSTO COM Addin.
There are numerous other questons available on how to best build a VSTO addin (some in C# some in VB.NET but all this information is exactly the same for both, just different syntax).
So you will need two projects. Your existing one, plus a Excel VSTO addin (which you can also do in VB.NET).
Now inside the selectionchange event you should make sure that your code handles the target range correctly; ie. make sure you check for non-contigious groups of ranges with a selection... A1:B1;D2:E2 and copy the data to your app. You may consider using a format such as xml to serialise the latest data from excel so that if your app is not open at the time, it can deserialise and read back the data stored for it the next time it is opened. I guess it really depends how your handling the data (i.e. is it for loading into a datagrid?) and whether you are going to do further processing and store it somewhere else later (in which case maybe you can put it straight into a database from the addin in excel).
How can I cripple an excel document after a certain date? I want it to become unusable after, say, 12/31/2009.
I was thinking about putting one of those Must Enable Macros things in there that hides all the sheets on close and leaves one tab that says you must enable macros. Then having an on open macro that unhides all those tabs, but also will close itself if after a certain date. This has a few drawbacks in that someone could just enter in the macro code (without macros enabled) and change the expiration date... or even just change their system time. Any thoughts about good ways to do it? Is my method pretty much as good as you can get? or are there better ways out there?
Thanks.
You might want to have a look at Microsoft's Information Rights Management (IRM) technology. IRM lets you control which users are permitted to read, edit, print etc the content of a document. It is also possible to specify an expiration date.
IRM requires you to either have an ActiveDirectory infrastructure with a domain controller or you may use the IRM service hosted by Microsoft.
For further details check out Controlling workbook access in Excel with Information Rights Management.
Dan, I am not sure of the purpose you are trying to lock the excel sheet. However if you write the macro then you can password protect the VBA code so that no changes are made to the code.
Having said so, there is still a possibility to have workarounds and access the excel file; no method can be foolproof.
Cheers...