Update VBA code module in distributed MS Project global.mpt files - vba

I am responsible to modify the Global file of MS Project. It contains a custom made module which is constantly updated. I am distributing it to other users which do not have the computer skills to update their own file (I know it's just copy paste).
I would like to know if there is a way I can code something in the Global file which checks for the latest version that is stored on a shared drive and copies and pastes in the other users computers?

Use the Project_Open event in the ThisProject module of your global.mpt file to periodically update the code in a different module in the same file (e.g. the "Main" module):
Dim LastUpdated As Date
Private Sub Project_Open(ByVal pj As Project)
' run update if more than 1 hour since last update
If Now - LastUpdated > (1 / 24) Then
With ThisProject.VBProject
.VBComponents.Remove .VBComponents("Main")
.VBComponents.Import "c:\temp\main.bas"
End With
LastUpdated = Now
End If
End Sub

Related

Ms Project VBA Macro Organiser to subproject copy issue

I have a simple line of code that attempts to copy text field via project organiser from a Master project/Global.mpt to subproject within the master project (active project). I have tried multiple ways but i'm failing either with
'Run-time error 1101, the file Schedule 1" was not found Or, "This value is not valid in this situation, check the field to see if it requires a text, date or a number, and that you typed the information correctly".
Appreciate your help. Thanks
'OrganizerMoveItem Type:=pjFields, FileName:="MASTER SCHEDULE.mpp", ToFileName:=" Schedule1.mpp",
Name:="Text27"
'OrganizerMoveItem Type:=pjFields, FileName:="C:\xx\MASTER SCHEDULE.mpp", _
'ToFileName:=ActiveProject, Name:="T27(Text27)"
OrganizerMoveItem Type:=9, FileName:="GLOBAL.MPT", _
ToFileName:=ActiveProject.Subprojects("Schedule1.mpp"), Name:="T27"
The issue is that the subproject file needs to be open in order to use the Organizer to move customizations into it. Viewing the subproject's tasks in the master schedule is not the same as the subproject file being open.
This code will loop through the subprojects and copy the customized Text27 field to each one by opening it, using the Organizer, then closing and saving it.
Sub CopyCustomFieldToSubprojects()
Dim master As Project
Set master = ActiveProject
Dim prj As Subproject
For Each prj In master.Subprojects
FileOpenEx prj.Path
Projects(prj.SourceProject.Name).Activate
Application.Alerts False
OrganizerMoveItem Type:=pjFields, FileName:=master.Name _
, ToFileName:=ActiveProject.Name, Name:="T27 (Text27)"
Application.Alerts False
FileCloseEx pjSave
Next prj
End Sub
Note that the OrganizerMoveItem method expects a file name (string) for the FileName and ToFileName parameters rather than a Project object (e.g. Filename:=master.Name).

Saving Template after VBA references are added

I have some code which adds the VBA references i require for using Access. (it checks if the user already has them included).
This all works fine. My problem is when i then go to close word I am prompted to save the Acronym Tools template (Where the macro that this code is stored). Is it possible to do this programtically so that is it done as soon as references are added and the user does not see it happening?
The code i use:
If Not isReferenceLoaded("Access") Then
MsgBox ("Access Object library not found, the script will now attempt to find the library for you.")
'Ensure access library is included so database actions can be done
ID.AddFromFile "C:\Program Files (x86)\Microsoft Office\Office14\MSACC.OLB"
MsgBox ("Access Object library added")
End If
If Not isReferenceLoaded("DAO") Then
MsgBox ("DAO library not found, the script will now attempt to find the library for you.")
'Ensure access library is included so database actions can be done
ID.AddFromFile "C:\Program Files (x86)\Common Files\microsoft shared\OFFICE14\ACEDAO.DLL"
MsgBox ("DAO library added")
End If
The function to see if reference is loaded:
Private Function isReferenceLoaded(referenceName As String) As Boolean
Dim xRef As Variant
For Each xRef In ThisDocument.VBProject.References
isReferenceLoaded = (xRef.Name = referenceName) Or isReferenceLoaded
Next xRef
End Function
If you don't want to save the document with the updated references (they'll be remade next time the doc is open, I guess) add to your Document object (supposedly named ThisDocument) the following subroutine:
Private Sub Document_Close()
ThisDocument.Saved = True
End Sub
This would inhibit the save-check only for ThisDocument. Add a Call ThisDocument.Save statement at the beginning, if you do want to save. However, I would count on the users to save their changes... but that's a matter of strategy, please do as you wish.
Nota Bene: Do not forget to save after adding the function: you'll lose the changes if you forget to; Word will ignore your changes because it was just instructed to do so by the function. :-)

Access not finding an excel file which was created in vba on a network

I have code that opens & alters an excel table, saves it to a new (network) location, and then imports data from the newly formatted excel. The issue I have is that the code can't find the newly created file, saying it doesn't exist. I've played around with adding a 'pause' function, but I'm wondering if there's a way to refresh the network link in vba? Or is there a better method? Files will vary by size.
If I add a break in the code and let it sit for a few minutes it finds the file fine.
Private Sub btnImport_Click()
[other code]
'save excel file onto network location
xlApp.ActiveWorkbook.SaveAs ("\\network\file.xlsx")
xlApp.Quit
'Import file to temp table.
DoCmd.TransferSpreadsheet acImport,acSpreadsheetTypeExcel9, "tblImport","\\network\file.xlsx", True
End sub
Run-time error '3011': The Microsoft Access database engine could not find the object '\network\file.xlsx'. Make sure the object exists and that you spell its name and the path name correctly.
Free up the Excel resources when finished:
xlApp.Quit
'free any other Excel resources, then..
Set xlApp = Nothing
If it is a network issue and you need a delay then you can use Application.OnTime. For 15 seconds:
Application.OnTime Now + TimeValue("00:00:15"), "my_Procedure"
This will run your procedure (my_Procedure()) after the delay, and this procedure can perform the import.

How do I extract from a password protected zip file using VBA?

I have been struggling with this problem for quite some time now, and have trawled through various forums trying to find an answer.
I have a mailbox which received 5 emails each morning which have zipped, password-protected .csv files which require opening and processing in Excel. I am semi-competent in VBA so the Excel side of things is no issue, but it would save me a lot of time if I could automatically unzip these files and save them to a folder.
These emails have the same subjects, attachments and passwords each day, and are from the same sender to the same mailbox. I have code which can automatically process and save the .zip files to a location, but I am still stuck with the problem of having to go into each one, enter the password, open the file, save it, etc.
I have refrained from attaching this code because I would like to see if there are better solutions to my one, and it is the unzipping and password entering that I really need help with. This being said if you would like me to attach my code I will be happy to do so :)
To expand my comment, no input is required - the password is obtained via an event so can be provided in code.
Download the demo project and DLL
In the outlook VBA editor, right click the Project in the tree, Import File and add
cUnzip.cls
mUnzip.bas
Put the DLL in \System32 (or \SysWoW64 on 64bit)
As a naive example, add a new class cWhatever:
Private WithEvents Unzip As cUnzip
Private Sub Class_Initialize()
Set Unzip = New cUnzip
End Sub
Sub RunUnzip()
With Unzip
.ZipFile = "c:\blah\qqq.zip"
.UnzipFolder = "c:\temp"
.Unzip
End With
End Sub
Private Sub Unzip_PasswordRequest(sPassword As String, bCancel As Boolean)
sPassword = "password123"
End Sub
Then to run from elsewhere:
Dim x As New cWhatever
x.RunUnzip
First time you run there is an error highlighting App.EXEName, just delete the App.EXEName &

Leaving a Project file open after retrieving it with GetObject

What is the right way to leave an MS Project file opened with GetObject() open and visible to the user after the end of a macro in a different app?
The information I found online suggests that setting the Application.UserControl property to True before the objects go out of scope should allow the user to continue using the opened file. However, for MS Project at least, the Application.UserControl property appears to be read-only. Is there a way to work around this?
A simplified example showing the problem:
Sub AddTasks()
Dim proj As Object
' Already have the file path from another part of the workflow
Set proj = GetObject("C:\projtest.mpp")
' perform some calculations and add new tasks to project
proj.Tasks.Add "additional task"
' Leave Project open and visible for the user
proj.Application.Visible = True
proj.Application.UserControl = True ' Gives "Type Mismatch" error
' without the UserControl line, runs ok, but Project closes after the end of the macro
End Sub
Instead of using GetObject, could you create an instance of the application and open the project file in the instance?
Sub AddTasks()
Dim msProj as Object
Set msProj = CreateObject("Project.Application")
msProj.FileOpen "C:\projtest.mpp"
'do stuff to project file here
msProj.Visible = True
End Sub
Something like the above (I can't test the above code because I don't have MSProject, but similar code works for MSWord)
For Project UserControl just indicates if the user started the application or not; it appears to be read-only because it is. I've not done what you're asking for with Project, although here is a similar example for Word trying to see and find running instances of Excel. Perhaps this helps a little:
can-vba-reach-across-instances-of-excel