MS-Project: GUID preservation when moving task between master/sub-projects and/or assistance with macro solution - api

A. I would like to know if there is any way to move a task between projects and preserve the GUID?
B. If this is not possible, then If someone could help me with a macro that would facilitate this.
I think clarification on this issue would help the community in general as I don't think I am the only one who has had this issue.
A. When trying to move a task from either a master project to a sub-project or vice versa gives the following error:
You cannot move a task or resource from one file into another.
Try copying the task or resource and then pasting it into the other project.
I realise that this is probably because the task is considered a unique item to that schedule. After doing high level planning, I like to split logical sub-projects out, but work may have already commenced and I use the GUID downstream so I need it preserved.
B. I am not adverse to a macro task moving solution and I think the pseudo code would be something like this:
1) User selects tasks to move
2) User Clicks Button
a. Macro copies GUID and resources into a spare text fields
b. Macro cuts the selected tasks out
3) User selects where tasks needs to be pasted
a. Macro prompts as to where tasks should be moved to OR
b. User selects row where tasks should be inserted and clicks another button which initiates the pasting component of macro / second pasting macro
4) Macro pastes in tasks
5) Macro updates newly generated GUID with copied GUID and also the resources
After having a look through Project 2013 SDK, I cannot see how to set GUID.
Plus I am a bit rusty in the VBA department.
Any help would be appreciated.
Cross Posted on: Office Dev Forums - Project forums > Project Customization and Programming
Thanks.

A) MS Project can't move a task from one project to another. Even drag+drop will just copy it. If you use cut+paste, the old one will be gone at least. But, in any case, the new task will have a new GUID.
B) A task GUID cannot be modified, neither manually in MS Project nor via a VBA macro. I.e., for your approach, you should create some kind of own unique code that the people can use to reference or to track the tasks, e.g. a WBS code or just an Outline Code.
Note: Copying a project will renew all GUIDs as well. But, copying a project keeps the Unique IDs. Perhaps this is a way for you: First creating one file, and later splitting it by copying the file and then removing the obsolete tasks...
Regards, KAwi42

Related

Best way for Excel workbooks to share VBA functions

I seek advice on how to manage userdefined VBA-functions that are used in several workbooks:
Background:
Over time i have created several Excel workbooks (wbs), each with a slightly different purpose, that are ultimately based on a library of my userdefined functions and class modules (From now on: library). The "master"-versions of the wbs are revision-controlled. The wbs are used by several people.
However, I do not use an addin for the library, and hence the modules and class modules are actually locally present in each wb's specific VBA project. This makes it a nightmare when doing either expansions or corrections, as I have to revisit and implement said alterations in each wb.
Furthermore, in each wb there are unique functions, understood such that those are not intended to be shared. Those functions, however, might utilize the library-functions.
Main-Question: How should one manage vba functions across several workbooks shared by several users?
My considerations/Sub questions:
Should I convert the library to a true addin and discard the local copies in each wb?
How do I tell the users that the add-in is required upon getting a copy of the maser-version?
How does one cope with legacy/local versions/branches that are spread among the users? Both current legacy copys and future legacy copies that might be used for reccuring tasks?
Where should such an addin-in be stored (in a shared folder or something)?
Would it be considered "bad practice" to force load the add-in using the workbook_opensub?
Any advice or guidance in best practice is appreciated.
Edit: I have tried to highlight the main question, please consider the sub questions as my own thoughts on the subject.
Until recently, I had several add-ins that lived on a shared drive. I had the users install the add-in using File - Options - Addins and wrote up the instructions to do it. The copy on the shared drive was read-only. For changes, I would code and test on the dev copy on my machine, then deploy it to the shared drive. The next time the user started Excel, the changes would be there.
Then we wanted more people to have the addins and not all of them had access to this shared drive. Also, people complained when they were off the network that it still tried to connect to the addins. So we went a different route.
We used a program called PDQ Deploy to put the addins in everyone's addins directory, so they had a local copy. We also deployed a script that copied the files from a company-wide shared drive to their addins directory. If they weren't connected to the nextwork, the script would fail silently. Finally, we used group policy to 1) create the registry entries to install the addins and 2) create a scheduled task that kicked off the script every night. Updating every day is overkill, but the files are only a few kbs, so we went with it.
Now I can deploy new versions to the company-wide shared drive and everyone will have the changes the next day (or the day after they're back on the network).
I put my vba stuff on the "personal" workbook (Windows menu : Unhide...) and whatever workbook I am using I can use them from there.
You do have to make sure about knowing which one is acrtive though...

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).

Logging When Files Are Saved, Modified or Deleted Using VBA

I work with VBA in MS Access databases. I'd like to be able to log when files are saved, modified or deleted without having to update the existing code to do the logging when the pertinent events take place. I want the time, location and the name of the file.
I found a good example here: when file modified
However, it only allows for monitoring a particular location (path). I want to be able to log regardless of where the save, modify or delete takes place. I'm only allowed to program in the MS Office environment in this situation. It seems as though using the Windows API is going to be how this task will be achieved. However, I don't have much experience working with the API. Is there an easier way to achieve what I want that doesn't involve using the API?
Have you worked with After_Updates or After_Insert macros? Also, is your application split? Meaning there's a front-end and a back-end of the database. You can create a separate table that mirrors that table that you need to track changes for. Every time a table is updates, run a macro that inserts a row to that table.
I'm assuming you're saving files to the database. If that's the case, add a after_update or after_insert macro that can keep track of when then files are being modified or added to the table.

Update VBAs in multiple workbooks

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.

Running a VBA excel macro at a certain time

Trying to figure out the best way to kick off an excel macro at a certain time. I found a few suggestions, but I still have plenty of questions on the idea and was hoping you guys could provide some clarification.
What I am trying to do: I have live excel workbooks that are connected to my database. So at 11:30PM on the last day of every month I want to go into several excel workbooks (I have one for every vendor that we sell), enable the security and editing and refresh the connection so all of the information in the sheets is up to date. Lastly I would like to then save a copy of that file in a sub folder inside the current folder.
Run on time method:
Here is this run on time method that I found on ozgrid. My question is, I am assuming that excel would need to be running at the time in order to execute the method? If so what would be one way of opening up excel and refreshing a workbook to be saved?
Running excel on Windows Task Scheduler Windows Task Scheduler
Essentially this method is using an Excel Controller to run excel using VBS...Seems more promising than the run on time method but I am not very familiar with how an excel controller works or VBS, so any help or ideas on this one would be greatly appreciated.
Any input is greatly appreciated. If my ideas are way out in left field could you guys help point me in the right direction?
Thanks for all the help in advance!
Turn the problem around. Create a workbook with normal Excel query tools and have it load the result set of the query when the workbook is opened (You don't specify a version, but see Refresh an external data connection for Excel 2013).
Then, either create a view in the database that contains the results you require, or to materialise the result of a view into a staging table that is then read by the workbook.
Users can then open the workbook whenever they require data, and the current results will be available. A parametrised version of the query could then access a history table to older periods.
This way all data is only prepared when required, and is always available without the scheduling complexity.