Create live copy of password protected excel workbook - excel

I have a workbook that is password protected and I’d like to create a read only copy that other users can view on a different location on the network drive.
I know it’s a strange request as the other people could open the original as read only, but we don’t want them to know the location of the original or have anything to do with it, should they figure out my colleagues password.
The other issue we had was that people were opening as read only and it was still telling my colleague that it was locked by another user and he needs it for most of the day so that issue is annoying
Thanks in advance

What you could do is add the following event procedure to the ThisWorkbook module:
Const RemotePath As String = "D:\YourRemoteLocation\"
Private Sub Workbook_AfterSave(ByVal Success As Boolean)
On Error GoTo CleanUp
If Success And InStr(ThisWorkbook.Name, "Copy of ") = 0 Then
Dim CopyFullName As String
CopyFullName = RemotePath & "Copy of " & ThisWorkbook.Name
Application.EnableEvents = False
Dim fso As FileSystemObject 'Requires the Microsoft Scripting Runtime Library
Set fso = New FileSystemObject
fso.CopyFile Source:=ThisWorkbook.FullName, Destination:=CopyFullName
Dim ReadOnlyWorkbook As Workbook
Set ReadOnlyWorkbook = Workbooks.Open(Filename:=CopyFullName)
Application.DisplayAlerts = False
ReadOnlyWorkbook.SaveAs Filename:=CopyFullName, Password:=""
Application.DisplayAlerts = True
ReadOnlyWorkbook.Close SaveChanges:=False
End If
CleanUp:
Application.EnableEvents = True
Application.DisplayAlerts = True
Set fso = Nothing
End Sub
This code will run every time the workbook is saved and export the current file to the remote location. Then it will open the copy and save it as a workbook without password.
Note that I've added InStr(ThisWorkbook.Name, "Copy of ") = 0 as a condition to the If-statement. Instr returns the position where a substring (arg2) appears in the main string (arg1) or zero if the substring is absent from the main string. In this context, we want it to be zero since we don't want to run the code in the workbook copy.
In this method, the owner of the original file will have to supply their password every time they save. You could automate this by passing the password as an argument to the Open method like this:
Set ReadOnlyWorkbook = Workbooks.Open( _
Filename:=CopyFullName, _
Password:="MyPassword")
However, the password would then be accessible by people looking into the VBA code.
Alternatively you could get the password from a local file that wouldn't be accessible from the Network, but then the file path would be visible.
And if the remote folder is not already set to be Read-only mode, you can make sure that people opening the remote version of the file do so in Read-Only mode by adding the following event procedure after the previous one.
Private Sub Workbook_Open()
If InStr(ThisWorkbook.Name, "Copy of ") = 0 Then
ThisWorkbook.ChangeFileAccess Mode:=xlReadOnly
End If
End Sub
Obviously this will only work if they enable macros.

Related

Workbooks.Open is not using the provided Password, but instead requesting password from user

I am opening a whole bunch of workbooks that all have the same password in order to check their sheets.
The program starts with a dummy password that will fail, and when it does a userform (named PasswordUserform) is shown in order to capture the password for all of the files. Subsequently, each workbook is opened via that password. As such, it should A) never fail, and B) never use the default password entry userform.
Private Function CheckFiles(ByRef WkbApp As Excel.Application, _
WkbFolder As String, _
FoundFile As String, _
NeededSheets As Scripting.Dictionary, _
ByRef Pass As String) As Boolean
Dim Wkb As Workbook
WkbApp.Visible = False
' Attempts to open the workbook. If it fails, then attempts to get a
' better password from the user. This password is saved for further
' attempts, but only during runtime.
On Error Resume Next
Set Wkb = WkbApp.Workbooks.Open(Filename:=WkbFolder & FoundFile, _
Password:=Pass)
If Err.Number > 0 Then
PasswordUserform.FileNameLabel.Caption = "'" & _
Left(FoundFile, 20) & "...'"
PasswordUserform.Show
Pass = PasswordUserform.PasswordBox.Text
Unload PasswordUserform
Set Wkb = WkbApp.Workbooks.Open(Filename:=WkbFolder & FoundFile, _
Password:=Pass)
End If
On Error GoTo 0
' Do Stuff within workbook, Setting function to True or False depending on contents
End Function
The function is called within a simple Do While loop:
Do While Len(FoundFile) > 0
FoundDate = FileDateTime(WkbFolder & FoundFile)
If FoundDate > LatestDate And CheckFiles(WkbApp, WkbFolder, _
FoundFile, NeededSheets, Pass) Then
LatestDate = FoundDate
LatestFile = FoundFile
LatestPass = Pass
End If
FoundFile = Dir
Loop
When stepping through, the first Set Wkb may or may not display the default password userform. If that pops up and is cancelled, the custom PasswordUserform displays. On proper entry, the second Set Wkb (in the IF scope) always displays the default password userform. But on the next file, the password is used properly and no userform is displayed. Finally, the occasional file will create the default password userform (on inputting the password that should have been provided, it opens fine, as all files in the folder use the same password).
I've tried setting the WriteResPassword as well, with no difference. Additionally, DisplayAlerts=False does not prevent the problem.
The culprit was WkbApp.Visible = False. By setting the Application invisible, when the macro inevitably crashed during future testing, it would not fail gracefully, and therefore the application and its workbooks would still exist, but be unviewable by the user.
When the macro is run again, it sees that the file is locked for editing, but instead of displaying the locked for editing alert, it just asked for the password again (not sure why this is what it does).
Changing the Application to:
Set ResultApp = New Excel.Application
ResultApp.WindowState = xlMinimized
ResultApp.Visible = True
Allows the user to close the window when things go horribly wrong.
Additionally, using the ReadOnly parameter allows the program to open a copy regardless of if it is open.
Set Wkb = WkbApp.Workbooks.Open(Filename:=WkbFolder & FoundFile, _
Password:=Pass, ReadOnly:=True)
Since I am saving to a new file anyway, this works for me, but may not if someone wishes to edit&save the file they open.
I would be happy to learn of any way to capture a hard crash and gracefully close~

How do I reference a Cell value stored in an excel file on sharepoint in VBA

For the purpose of version control for my file, I want to be able to run a script that compares Cell A1 on Sheet VC, to the same cell/sheet of a version stored on Sharepoint when I run my script. Fairly new to using VBA and cant work out how to do it and cant find the answer im looking for on google.
The code I want to use:
Public Sub version_control()
Sheets("VC").Calculate
If Sheets("VC").Range("A1").Value <> (this is where I want it to check cell A1 sheet VC on the Sharepoint file)
MsgBox "Please download the latest version from the Sharepoint"
Application.Quit
End If
End Sub
Guessing, you don't already have the SharePoint file open ... if that's true skip down.
But if it's open you can reference it like any other open workbook ... e.g. both of these should work:
debug.Print Workbooks("MySharePointWorkbook.xlsx").Sheets("VC").Range("A1").Value
debug.Print Workbooks.Item(n).Sheets("VC").Range("A1").Value
Probably not already open right? Without getting into the weeds of external data links, I would just obtain the full URL of the SharePoint file (open it, ? Activeworkbook.FullName in the Immediate Window) and store that string in serverFileName like this:
Public Sub version_control()
Dim serverFileName As String 'obtain url for sharepoint filename, insert below
Dim valuesAreDifferent As Boolean 'so we can do housekeeping below
Dim x As New Excel.Application 'make a new session for the sharepoint version
Dim w As Workbook 'grab-handle for the sharepoint file
Sheets("VC").Calculate
valuesAreDifferent = False 'implicit, being explicit
serverFileName = "http://whatever-domain.com/MySharepointWorkbook.xlsx"
x.Visible = False 'so it doesn't flash up when checking
Set w = x.Workbooks.Open(serverFileName) 'open the sharepoint version
If Sheets("VC").Range("A1").Value <> w.Sheets("VC").Range("A1").Value Then _
valuesAreDifferent = True
'housekeeping in case we don't quit
w.Close
x.Quit
Set w = Nothing
Set x = Nothing
If valuesAreDifferent Then
MsgBox "Please download the latest version from the Sharepoint"
Application.Quit
End If
End Sub

The Updateing VBA Excel AddIn dilemma

I am doing a user application that needs an AddIn which I want to update in the workbook_open event.
Here is my plan:
Add Reference to "Microsoft Visual Basic for Applications Extensibility 5.3"
Delete Reference to old AddIn
Delete old AddIn if existing
Copy AddIn from different Folder
Add Reference to new AddIn
This should be done all while the vbProject is password protected and hidden. Here is my code:
Private Sub Workbook_Open()
Dim wb As Workbook
Set wb = Thisworkbook
'
If common_DB.AddFSOref(wb) Then Debug.Print "Added Extensibility"
If common_DB.AddRegEx(wb) Then Debug.Print "Added Regular Expressions"
UpdateDBAddin
End Sub
That is my update code that works without password protection but when adding in the reference in the vbProject password is required. I want to suppress that because my users do not have to worry about that.
Public Sub UpdateDBAddin()
Dim UserPath As String
Dim AI As AddIn
Dim AddinSourcePath As String
Dim AddinName As String
Dim Addintitle As String
Dim RefName As String
Dim ref As Reference
RefName = "Ex_Ample_Name"
AddinName = "ExampleName.xlam"
Addintitle = "Example AddIn"
UserPath = Application.UserLibraryPath
AddinSourcePath = "E:\Xample\Path\"
Application.DisplayAlerts = False
For Each ref In Thisworkbook.VBProject.References
If ref.Name = RefName Then
Thisworkbook.VBProject.References.remove ref
End If
Next ref
If Application.AddIns(Addintitle).IsOpen Then
Workbooks(AddinName).Close False
End If
If common_DB.IsFile(UserPath & "\" & AddinName) Then
Application.AddIns(Addintitle).Installed = False
Kill (UserPath & "\" & AddinName)
End If
Application.AddIns.Add (AddinSourcePath & AddinName)
Application.AddIns(Addintitle).Installed = True
Application.DisplayAlerts = True
' Here the VBProject Password is requested from the user, I want to suppress that
Thisworkbook.VBProject.References.AddFromFile (UserPath & "\" & AddinName)
End Sub
Question: How do I suppress the password when I want to add a new reference to my Vbproject?
EDIT1: Dilemma because it only occures when the project is hidden and I cannot 'debug' in the hold-mode. I narrowed the issue down to the adding of the reference to the addin on the last line of UpdateAddin.
EDIT2: This has some funnny behaviour. If you just Cancel the password prompt it works just fine. So the reference gets added. It doesn't matter if you put in the password or if you just cancle it the line gets executed.
So far I do not have a solution, but I found the workaround.
Just leave user to cancel password for a first time.
Reference will be added from file.
Then force the main xlsm to be Saved (can't be opened as ReadOnly)
Upon next run, check if correct reference with correct name and path is already referenced. if yes skip adding reference from file .. no password popup.
Anyway I am still looking for a solution how to avoid the first popup. Especially because our users are opening main XLSM in ReadOnly mode ..

Open + Edit Excel file from Sharepoint

I am trying to open an excel file from a sharepoint library bearing the same name via VBA. Here are variables
Define Variables:
Private Master_File As String
Private Master_FileLocation As String
Private Master_Open As Workbook
Assign_Variables:
Master_File = "Master Data.xlsx"
Master_FileLocation = "http://sharepoint/page"
Sub Open_Master()
Application.ScreenUpdating = False
Application.AskToUpdateLinks = False
Application.DisplayAlerts = False
On Error Resume Next
Set Master_Open = Workbooks.Open(Master_File)
If Master_Open Is Nothing Then
Workbooks.Open FileName:=Master_FileLocation & "/" & Master_File, ReadOnly:=False
End If
End Sub
The code runs with no errors yet no excel file is opened. When I click on the file and copy the "shortcut" directly from my internet explorer browser, this is what appears:
http://sharepoint/org/%20Master%20Data/%20Master%20Data.xlsx
When I copy this path and paste it into a folder search bar I am able to open the folder. Therefore, I know the file + folder exists. I also understand some functions such as ChDir and GetOpenFileName don't work with HTTP. That said, my function is pretty simple and doesn't require those functions. Any help would be appreciated.

Password Protect Excel Workbook from MS Access

I need to password protect entire workbook for opening. There's no need to protect the sheets as user will do some edits once reports are generated.Code runs within MS Access. Office Version is 2003. There's no possibility of using "SAVE AS" password protect method due to certain restrictions.
Can you please point out what I am doing wrong here?
Here's what I have tried so far:
Sub testProtection()
Dim xl As New Excel.Application
Dim wkbook As Workbook
Dim fileToOpen As String
On Error GoTo ExitMe
fileToOpen = "filepath & name"
Set wkbook = xl.Workbooks.Open(fileToOpen)
error in following lines: Automation Error Object invoked has disconnection from its client
wkbook.Protect Password:="100", Structure:=True, Windows:=True
wkbook.Close savechanges:=True
ExitMe:
MsgBox err.Description
Set xl = Nothing
Set wkbook = Nothing
Call cleanAllXLInstances
End Sub
PS: It's an incentive if the workaround could be compatible with MS 2010 as the tools will be migrated in the future - but not mandatory at this point. Plus I could manage it when looking at the API later on if current code can be worked out.
All I need to make sure, at this point Display Alerts = False to suppress the alerts for Saving As file with same name in same location. Which is contradictory to the initial constraints of the question asked though...
If xlPwd <> 0 Then
wkBook.SaveAs fileName:=fileToSaveAs, Password:=xlPwd, CreateBackup:=False
wkBook.Close
strMssg = " : Report is Protected!"
Else
strErrMssg = " : Report is NOT Protected!"
isWrapped = False
GoTo ExitMe
End If

Resources