VB Macros for Office 2016 for Mac require Permissions every time they try to access a file! Is there any way to get around this behavior? - excel

Any VB Macro in Office 2016 shows a dialog box to the user asking for permission, every time the Macro tries to access a file! Is there a way to avoid it.

Unlike VB Macros in Office for Mac 2011, VB Macros in Office 2016 for Mac do not have access to external files by default. The Office 2016 for Mac apps are sandboxed and hence they lack the required permissions to access external files. Existing macro file commands are changed to prompt the user for file access if the app doesn’t already have access to it. This means that macros that access external files cannot run unattended; they will require user interaction to approve file access the first time each file is referenced.
Developers should use the GrantAccessToMultipleFiles command (see following section) to avoid this experience. This command lets your app get permission for all the files at one time, thereby avoiding a difficult user experience.
GrantAccessToMultipleFiles
This lets you input an array of file paths and prompt the user for permission to access them.
Boolean GrantAccessToMultipleFiles(fileArray)
Parameters
fileArray -- An array of POSIX file paths.
Return Values
True - The user grants permission to the files.
False - The user denies permission to the files.
Note: Once granted, the permissions are stored with the app and user need not grant permission to the file anymore.
Example: 
 
Sub requestFileAccess() 
 
'Declare Variables 
    Dim fileAccessGranted As Boolean 
    Dim filePermissionCandidates
 
 'Create an array with file paths for which permissions are needed 
    filePermissionCandidates = Array("/Users/<user>/Desktop/test1.txt", "/Users/<user>/Desktop/test2.txt")
 
'Request Access from User 
    fileAccessGranted = GrantAccessToMultipleFiles(filePermissionCandidates) 'returns true if access granted, false otherwise 
     
 
End Sub

I wanted to delete a file in Excel using VBA's Kill syntax and got the permission prompt when the VBA attempted to execute the command. My script is supposed to run once every 3 minutes day and night so responding to separate prompts wouldn't cut it.
To workaround the issue, I created a wrapper for VBA's Kill function called myKill. To implement it I:
Globally replaced all calls to Kill with myKill in my VBA code.
Added a new VBA subroutine called myKill (code below)
Created an AppleScript file to actually remove the file (code below)
Granted Excel Full Disk access in System Preferences/Security & Privacy/Privacy. Not sure this step was necessary but I mention it as it's my current configuration. It's worthless without the first three steps.
Here is the myKill subroutine:
Sub myKill(fname As String)
Dim s As String
If Left(Application.OperatingSystem, 3) = "Mac" Then
s = AppleScriptTask("Kill.applescript", "Kill", fname)
Else
Kill fname
End If
End Sub
Here is the Kill.applescript file contents:
on Kill(fileName)
# implementation of vba kill command on Mac. Mac sandboxes Microsoft's
# kill command
tell application "System Events" to delete alias fileName
end Kill
The Kill.applescript file must be stored in
/Users/your user name/Library/Application Scripts/com.microsoft.excel/Kill.applescript
The first time the Apple Script executes, Mac OS will ask for permission for Excel to manipulate files in the directory where the file to be deleted is located. Once given, future file deletes in the directory won't trigger the permission request. I tested that by exiting Excel, reentering and deleting another file.
RANT
How anyone thought making programmers jump through all these hoops or click "OK" each time a file had to be deleted was an acceptable implementation is beyond me. Because someone in Microsoft dropped the ball on abstracting simple file manipulations like Kill over 10,000 programmers have seen this web page trying to figure out what they have to do to delete a file in Microsoft Excel.
Yo Microsoft VBA Project Manager! I'm talking to you! Your job exists because Joel Spolsky convinced Bill Gates that a macro language for Excel was a good idea despite Gates' doubts. Your job is to ensure that Excel VBA abstracts os weirdness so programmers can get their job done and not have to hack in another language.

Related

RTE5 using `Shell` in VBA

Background:
Recently, a macro I use via VBA (in Excel) to run a script has stopped working; this subroutine worked for the previous six years. This is on a work device in which I do not have full admin privileges. The script file is stored on a network drive which I have access to, and can open and double-click to execute.
I have read from multiple sources, each not having an answer (including here on SO), that people have begun to see RTE5 when using Shell(), which may be related to security settings from the administrator.
One suggestion was to use use ShellExecute, which I have not had luck using.
Issue:
I receive RTE5 (invalid procedure call or argument) on the line for Shell() within the below code.
Question:
Has anyone had this same issue and been able to resolve said issue? Please indicate how you resolved.
Code:
'To open file, which previously worked:
Dim Loc As String
Loc = "Z:/filename.bat"
Call Shell(Loc, 1)
'Attempt at using ShellExecute, which gives Network Access error
Dim Loc As String
Loc = "Z:/filename.bat"
Call CreateObject("Shell.Application").ShellExecute(Loc, 1)

Start OneDrive Under Full Admin Rights

Summary
I necessarily run Excel with Admin privileges and I have UAC set to Never Notify. Excel VBA opens Word. Word has a macro button that restarts OneDrive. The error message is that "OneDrive can't be run using full admin rights." How can I restart OneDrive without the error massage?
Note: There is a sister post at How to Restart OneDrive via VBA When Running Excel Elevated, but that post poses an entirely different question.
Workflow
Excel VBA opens Word:
Sub m_Test_Finish_WordDoc()
Const strpath = "C:\Users\ssttr\OneDrive\Documents\Investing\Automation\Static Inputs\Restart_OneDrive.docm"
Dim Wd As Object
Dim InstrDoc As Object
Dim f As Boolean
On Error Resume Next
Set InstrDoc = GetObject(strpath)
With InstrDoc.Parent
.Visible = True
.Activate
End With
End Sub
Word macro restarts OneDrive:
Private Sub CommandButton1_Click()
Application.Run "Restart_OneDrive"
End Sub
Sub Restart_OneDrive()
'Restarts OneDrive
Dim shell
Set shell = CreateObject("wscript.shell")
shell.Run """C:\Users\ssttr\OneDrive\Documents\Investing\Automation\Static Inputs\OneDrive Restart - Copy.bat""" 'bat.zzz
End Sub
Contents of OneDrive Restart - Copy.bat
REM Restarts OneDrive from the command line.
REM From https://stackoverflow.com/questions/29872973/syncing-onedrive-skydrive-with-batch-file-via-cmd.
REM If the /background switch is omitted then Explorer is opened to the OneDrive folder in your user profile but OneDrive does not start.
REM If restarting OneDrive from a batch file then add the START command or the batch file won't end.
REM start %LOCALAPPDATA%\Microsoft\OneDrive\OneDrive.exe /background <-- the original '~error-producing' command
RunWithRestrictedRights %LOCALAPPDATA%\Microsoft\OneDrive\OneDrive.exe -w -v
One Possible Path to a Solution
I downloaded the RunWithRestrictedRights.exe standalone executable from https://www.coretechnologies.com/products/RunWithRestrictedRights/ into the C:\Windows\System32 directory and the implementation (shown above) in VBA was replacing the
start %LOCALAPPDATA%\Microsoft\OneDrive\OneDrive.exe /background
line in my batch file (which BTW is from Syncing OneDrive (SkyDrive) with Batch File (via cmd))
with
RunWithRestrictedRights %LOCALAPPDATA%\Microsoft\OneDrive\OneDrive.exe.
Note that, as required at the very bottom of https://www.coretechnologies.com/products/RunWithRestrictedRights/, I added the Administrator to the security policy settings for "Replace a process level token" and for "Adjust memory quotas." See below Notes > SecPol.msc §.
The hang-up is when that the batch file, when called in the above process (Important: remember Excel is Run As Admin), runs (i.e. cmd window flashes) but it does not open OneDrive.
Is my problem, as I suspect, in my batch file, or somewhere else? If somewhere else, then you may wish to see my sister post (it is the same underlying issue but pursing a very different question) at How to Restart OneDrive via VBA When Running Excel Elevated.
Notes:
Things that didn't work for me:
There was some stuff about UAC being required relative to an elevated launch of OneDrive, but that's a non-starter for me because if a user needs to attend to a UAC prompt, then my code's purpose of full automation is negated. Also, for my purposes, I have UAC set to Never Notify.
From https://superuser.com/questions/171917/force-a-program-to-run-without-administrator-privileges-or-uac/450503#450503 -- The MS RunAsInvoker Application Compatibility Toolkit shim does not apply bc I have UAC turned off by default.
FWIW, I did try setting UAC to Always Notify but it did not remove the error. I also tried RunAs /trustlevel:0x20000 %LOCALAPPDATA%\Microsoft\OneDrive\OneDrive.exe, and it did not seem to work, which is because per https://www.coretechnologies.com/products/RunWithRestrictedRights/ I have UAC disabled.
Origins of the solution I am pursuing:
From https://www.coretechnologies.com/blog/alwaysup/onedrive-hates-admin-rights/ -- "UAC enables an administrator to run OneDrive normally" section -- this is a really informative and provided the final solution
SecPol.msc
From https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/replace-a-process-level-token -- "This policy setting determines which parent processes can replace the access token (editor's note - describes the security context of a process or thread) that is associated with a child process." That's the lynch pin setting.
I set that per https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/user-rights-assignment and https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/how-to-configure-security-policy-settings.
I also had to set Adjust memory quotas for a process per https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/adjust-memory-quotas-for-a-process and https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/how-to-configure-security-policy-settings.
Per https://learn.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/how-to-configure-security-policy-settings, "any change to the user rights assignment for an account becomes effective the next time the owner of the account logs on." so I restarted (after I tested and confirmed it did not work without a restart).
Update 2022-01-07-18.7
I've moved from a *.bat because I was passing multiple commands, to attempting to directly implement the command by way of:
Sub Restart_OneDrive()
Dim RWRR As Variant
RWRR = shell("RunWithRestrictedRights.exe ""C:\Users\ssttr\AppData\Local\Microsoft\OneDrive\OneDrive.exe"" -w -p -v", vbNormalFocus)
End Sub
but I get Run-time error '53': File not found.
The error still occurs if I change to
RWRR = shell("C:/Windows/System32/RunWithRestrictedRights.exe ""C:\Users\ssttr\AppData\Local\Microsoft\OneDrive\OneDrive.exe"" -w -p -v", vbNormalFocus)
or to
Call shell("RunWithRestrictedRights ""C:\Users\ssttr\AppData\Local\Microsoft\OneDrive\OneDrive.exe""", vbNormalFocus)
I have the required security policy set per https://www.coretechnologies.com/products/RunWithRestrictedRights/ :
which states:
Does RunWithRestrictedRights.exe work on Windows XP and Windows Server
2003, where there is no UAC?
Yes, it works well on Windows XP and Windows Server 2003. The Windows
Integrity Level can't be set (that feature is only available in
Windows Vista and later) but the application is run without admin
rights as intended.
One note though: If you receive an error stating that "a required
privilege is not held by the client", please ensure that your account
has these two rights: Adjust memory quotas for a process; Replace a
process level token.
If I run directly from a non-elevated command line
RunWithRestrictedRights.exe "C:\Users\ssttr\AppData\Local\Microsoft\OneDrive\OneDrive.exe" -w -p -v
or
C:/Windows/System32/RunWithRestrictedRights.exe "C:\Users\ssttr\AppData\Local\Microsoft\OneDrive\OneDrive.exe"```` or ````RunWithRestrictedRights "C:\Users\ssttr\AppData\Local\Microsoft\OneDrive\OneDrive.exe" -w -p -v
it works, resulting in:
I have tried all these syntax commands inside the shell, with what I think are the appropriate syntax changes, e.g. as shown the above VBA above, but still get the run time error 53.
FWIW here's the help for RunWithRestrictedRights.exe:
which says:
RunWithRestrictedRights
Synopsis: Runs a given application in a "restricted" mode - at Medium
(or Low) Integrity and without rights granted by being a member
of the Administrators group.
Usage: RunWithRestrictedRights.exe [-w] [-l] [-p]
[-v]
[-d ]
Options:
The full path to the application to be started. Please be
sure to enclose the path in quotes if it contains at least
one space.
-w Instead of returning immediately after launching the
application, wait until the application ends. Optional.
-l Instead of running the application with Medium Integrity,
start it with Low Integrity. Optional.
-p Also strip away rights granted from being a member of the
"Power Users" group. Optional.
-d Also deny rights to the given SID.
-v Produce verbose output. Optional.
Exit code: The non-zero process identifier (PID) if the
application
was successfully started.
-1 if there was an error starting the application.
Version: 3.0.1.16 (Feb 18 2020)
Example: > RunWithRestrictedRights.exe "C:\MyApp\MyApp.exe"
- Starts MyApp.exe with retricted rights.
This free utility is Copyright 2020, Core Technologies Consulting,
LLC. Find out about this and our other products at our web site:
https://www.CoreTechnologies.com/

Why isn't my script able to locate my excel file when given correct filepath?

I have a .vbs script that opens two excel files and copies the contents of a sheet from the first file into the second file. It's supposed to run daily via task scheduler.
The script ran normally until the excel files in question were recently modified and slightly renamed - I went through the script and edited the filenames accordingly after the changes were made, triple checking that the names and filepaths matched up.
Everything ran fine for a few weeks after the changes but now the script fails immediately after starting, giving me an error claiming that the file can't be located even though the file is located at the given path. The error code is 800A03EC.
This is the first chunk of code in the script, including line 7 which seems to be throwing the error:
Dim objApp ' as excel object
Dim x, y ' as workbook
Set objApp = CreateObject("Excel.Application")
objApp.DisplayAlerts = False
objApp.Visible = False
Set x = objApp.Workbooks.Open("S:\Work (Public)\PORT MGMT & TRADING\PORT MGMT FORMS\ORION_FPFOCUS.xlsm")
Set y = objApp.Workbooks.Open("S:\Work (Public)\PORT MGMT & TRADING\PORT MGMT FORMS\FPFocusPasteSpecialValues.xlsb")
Dim WSx, WSy ' as excel worksheet
Set WSx = x.Worksheets("FPSUP")
Set WSy = y.Worksheets("FPFOCUS-COPY")
WSy.Range("B1").value = FormatDateTime(Now)
objApp.Application.Run "ORION_FPFOCUS.xlsm!Auto_Open"
The excel files in question are both located in the same directory:
S:\Work (Public)\PORT MGMT & TRADING\PORT MGMT FORMS\ORION_FPFOCUS.xlsm
S:\Work (Public)\PORT MGMT & TRADING\PORT MGMT FORMS\FPFocusPasteSpecialValues.xlsb
And the script is located here:
C:\Users\bserv\Documents\CopyFPFocus.vbs
The S drive isn't a physical drive, it's a virtual drive hosted by a service called Workplace. I can navigate through it and open the excel files manually just fine.
I initially thought it was a user privilege issue with task scheduler, but I've selected the 'run with highest privileges' option and the script is still failing. I also went through the privacy/trust settings in Excel to make sure the script wasn't being denied access, but I don't see any settings that would disable the script from working, and I also know that all these settings haven't changed since the script was working, so I don't see how they could be potential causes.
When I try running the code manually via cscript in the command line, it returns this error:
C:\Users\bserv\Documents\CopyFPFocus.vbs(25, 4) (null): The remote procedure call failed.
This is line 25 of the script for reference:
objApp.Run "RefreshAllStaticData"
When I try again by running command prompt as an admin, I get the same error I got initially. Sorry, is it possible the file was moved renamed or deleted.
The part that really confuses me is that the script ran fine for some time after the changes - so I'm really unsure about what actually changed to cause this issue to randomly pop up.
One other thing I've noticed is that upon opening the excel files I get a popup saying they're in use and locked for editing by me. I can't remember if this popup was showing up before the issue started. The other users on the network have been accessing these files regularly long before the script started failing, so I don't see how that could be the issue. The error code/message also doesn't seem to correspond with this being the problem.
I'd appreciate any help or insight into this issue. Thank you!

Importing Excel files into Access with Excel 2016

We currently have Office 2010 and are moving to Office 2016. I have an Excel macro that I am try to testing. I use the following shell command to open access and run a macro to import some excel files into a database. This has worked great and never has any issues.
Shell "C:\PROGRA~1\MICROS~1\Office14\MSACCESS.EXE \\Vs300\rental_public\SHARED~1\SSDATA~2.MDB /X Upload_Manheim", vbMaximizedFocus
When I look for the Access application on my machine the path is as follows:
C:Program Files\Microsoft Office\Office14
When I search for the Access application on the test machine, the path is as follows:
C:Program Files (x86)\Microsoft Office\root\Office16
I've tried modifying the shell command as follows:
Shell "C:\PROGRA~1\MICROS~1\root\Office16\MSACCESS.EXE \\Vs300\rental_public\OFFICE~1\SHARED~1\SSDATA~1.MDB /X Upload_Manheim", vbMaximizedFocus
When I try to run my macro, I'm getting a file not found error message. I believe the 2nd half of the shell command is fine, so I believe it is the issue is in the 1st half of the shell command.
The database being opened is an Access 2000 database. I'm not sure what is wrong.
Instead of going thru the command line you could stay inside your Excel Macro and do the same without making reference to the location of the Access application. Instead you can create a new instance of MS Access from within vba, open the Access database the contains the macro, and then run the macro.
Something like:
Dim accApp As Access.Application
Dim db As Object
Set accApp = CreateObject("Access.Application")
accApp.OpenCurrentDatabase "Your database location\dbName", True
Set db = accApp.CurrentDb
With db
DoCmd.RunMacro "MacroNameHere"
End With
Set accApp = Nothing
Set db = Nothing
Good luck!

Excel2016VBA (Mac) MkDir returns error 75

I've been working on a simple code (with guidance from the internet) that makes a directory based on what's in cell R1C1.
Sub mkdirtest()
Dim f_string As String
Sheets("Sheet1").Select
f_string = Cells(1, 1)
MkDir (f_string)
End Sub
In R1C1 I have for example "/Users/cwu/Desktop/Tefdshsdfh" and running the macro, I get a dialog to grant file access (for which I choose desktop and then select grant access) and then
Run-time error '75':
Path/File access error
However everything works when I have "/Users/cwu/Library/Group Containers/UBF8T346G9.Office/EXCELtest/Tefdshsdfh" in R1C1 which is a folder in a location that "bypasses" the Apple sandbox/security measures (from this site http://www.rondebruin.nl/mac/mac034.htm forgive me for any wrong lingo, I'm new to coding.).
Is there a solution to this? I've read that Excel for Mac 2016 has issues and is being worked on by Microsoft. The code also works fine in 2011, which I've tested the code in.
On Mac or Windows, that error will be generated if there is a legitimate error, either the path length is too long, the folder you are trying to create has illegal characters, or there are security restrictions preventing you from creating a folder at that location.
However, it will also return that error if the directory already exists, I don't want to sound patronising, but could this be your issue?

Resources