I need help creating a PowerShell script that will find all open Excel documents, then first if the document is read only close the document without saving and suppress prompts if changes were made, or second if the document is not read only then save and close them. This script will be run from a scheduled task.
The reason why I want to do this is because I need an automated way of saving and closing documents on our shared production area computers. We have about 80 computers on our manufacturing shop floor area and these computers are setup like kiosks for our production workers to access programs and documents needed to do their work. These computers are locked down tight with group policy and only have access to specific applications. One of these applications has Excel documents linked within it for the production workers to open and edit (they don't ever create documents). But the problem is all too often these documents are left open far too long and many times they are also not saved. So my solution is to create a scheduled task (that runs in between our production shifts) to save and close all open Excel documents that are left open.
I have used this PowerShell script below to close other applications and it does work for Excel too if no changes were made... but obviously you'll get a prompt to save if there are changes so I need a way to save the Excel documents first before this runs (or if read only suppress the prompt and just close).
Get-Process EXCEL | Foreach-Object { $_.CloseMainWindow() | Out-Null }
If this can't be done with PowerShell I'm open to doing this with a VBScript instead.
VBScript, JScript, PS, VBA can all do it. Above is VBScript (and thus also VBA). The technology is COM not a language.
EDIT
As said using the app object doesn't work in excel.
A excel file opened.
Running GetObject using Excel.Application
NOTE
This is in addition to other faulty behaviour by excel where it won't exit memory when references are released.
@bgalea had the right idea, but the answer is very incomplete. For one thing, re-attaching to COM objects only works in the context of the user who created the object, so you'd have to create either a scheduled task that runs as that particular user or a logoff script (automatically runs in a user's context at logoff).
Since you apparently want to run this periodically, a logoff script probably isn't an option, so you may want to use a logon script to create a respective scheduled task for each user, e.g. like this:
The VBScript run by these tasks might look somewhat like this:
If you want a PowerShell script instead of VBScript you need to use the
GetActiveObject()
method to attach to a running Excel instance.According to Microsoft's documentation the
GetObject()
method is supposed to work as well:but when I tried it I ended up with an additional (hidden) Excel instance instead of attaching to the already running one.
Note: If for some reason a user has started multiple Excel instances you will need to run the code once for each instance.