How to define a specific application to open a pdf from excel - excel

I would like to automate the opening of a pdf which is defined using a dynamic hyperlink, but using the DEFAULT pdf editor of the user, but cannot fathom how to do this beyond the code below which opens the file in
I have other code to save the pdf which automatically saves it and opens a file in the default program for each user. But I don't know how to do the reverse and have a file which is searched for and found via the dynamic hyperlink - which will then allow them to update.
This is to shortcut sometone opening various folders, manually seatching, then opening up a file. ideally Id want to automate.
Here is the code I have so far which works but will only open in Adobe and not the default program - is this perhaps a setting thing on my PC or is it code which is missing?
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("TNR Report")
Dim r As Range: Set r = ws.Range("A82") ' this defines the actual path and filename to be searched for
Dim strHyperlink As String
On Error GoTo CannotFindFile
strHyperlink = r.Value
ThisWorkbook.FollowHyperlink strHyperlink
File needs to open with nuance to enable the user to edit and update the "record", but opens only in reader which is no use and kind of defeats the purpose of the code.

2 possibilities:
Make Nuance your default application in Windows to open PDF files.
Use a shell command to start nuance with a filename as parameter
Shell """C:\Path To Nuance\Nuance.exe"" ""C:\Path To PDF\pdffile.pdf"""

Related

How to work around Excel 2016 halting without message when trying to assign variable to VBProject?

System Details.
Windows 10
Excel 365 64-bit V16.0 (Apps for Enterprise)
Issue.
I have a macro that opens a file, checks if the user has allowed programmatic access to the VBA Project in the trust center and raises an alert if they have not. This works fine on windows 7 machines with both 32bit and 64bit Excel from 2013 onwards.
The specific problem I am having on the Windows 10 machine is that when workbooks.open(path) is executed the file opens but in the VBA Project explorer window the VBAProject object for that file does not appear. I also get a popup saying that code cannot be run in break mode when I try this while stepping through the code. When run on Win 7 with this version of Excel and others both 32 and 64-bit the VBAProject object appears and no popup is generated.
This lack of the VBA Project causes an issue later when I run set vbproj = ActiveWorkbook.VBProject. At this point when stepping through the code execution halts with no messages at all. The Project pops up in the Project explorer window and it takes me to a module in the opened workbook. This gets opened with Design Mode turned on and when you click to turn it off I get an error message saying 'Macros have been disabled'
Notes
set vbproj = ActiveWorkbook.VBProject works fine if the file is open and the VBAProject is visible in the Project explorer window.
If the file being opened does not contain a macro then it works correctly.
I have made sure that the files are in a Trusted Location.
I have set Enable all macros in the Macro Settings of the Trust Center.
When opening the files manually I do not get any alerts that macros have been disabled by an administrator and I do not get any message asking if I want to enable macros.
I have looked at W10 group policies to see if there is one that would block VBAProjects / Macros from files opened via VBA and there does not appear to be one as far as I can see.
The Trust Center setting for programmatic access to the VBA Project does not matter to this test case. It will return True if it is allowed and False if it is not allowed.
This has been tested on another Windows 10 laptop with the same version of Excel 64-bit and it has the same result so is not an issue with a specific users laptop.
I removed the folder from the Trusted Location on the Windows 7 machine and the code still executes correctly and returns True/False.
In the actual macro this check is done for each opened file in a loop and the variant vbproj is used to remove data from the modules within that project. I have considered working around the issue by using Application.onTime and that may be a solution but have not spent much time on that and with how it halts it may not be viable.
Attempted Solutions
I have tried set wb = workbooks.open(path) to open the workbook and then using set vbproj = wb.VBProject but it has the same behavior as above.
I have tried doing ActiveWorkbook.Activate and similar actions to see if that will make the VBA project appear, it does not.
I have tried setting Application.FileValidation = msoFileValidationSkip before opening the file, this does not change the behavior.
I have tried setting Application.EnableEvents=False before opening the file, this does not change the behavior.
I have tried making vbproj a variant, an object and a VBProject, this does not change the behavior.
Steps to Recreate
Create a new workbook.
Put the below code into Module 1.
Function projectAccess()
Dim vbproj As Variant
On Error GoTo noaccess
Set vbproj = ActiveWorkbook.VBProject 'If access is denied an error is raised.
projectAccess = True
Exit Function
noaccess:
projectAccess = False
End Function
Sub openfile()
Dim filepath As String
filepath = Application.ThisWorkbook.Path
Workbooks.Open (filepath & "\openfile.xlsm")
Debug.Print projectAccess
End Sub
Save the workbook
Create a 2nd workbook, in my case it was called openfile.xlsm and put some code into Module 1.
put both workbooks in the same location and make sure it is a Trusted Location in Excel.
run openfile().
If successful the immediate window will display True / False depending on the Trust Center setting.
I am out of ideas. Any suggestions for some setting that I may have overlooked to make the Win 10 machines behave the same as the Win 7 machines or suggestions for a possible work around?
Even if it is a group policy setting that would be something I can raise with IT as long as I know what to ask for.
Many Thanks
Andrew
EDIT: Thanks to Rory in the comments the issue was making sure that the automation security was set like so Application.AutomationSecurity = msoAutomationSecurityLow as the way the new Win 10 + Office 64 systems have been set up by my IT dept is to have it default to msoAutomationForceDisable

Do the DSOFile functions only apply to the non-binary Excel Document types?

Using Windows 10 (Build 1903 if that's relevant?) and 64bit Office 365 (probably relevant?) I've implemented a system that allows me to version control Excel VBA code.
I'm using the Workbook_BeforeSave method to check whether the current file is saved or not, and if it is saved, where it is saved to.
This works fine and will prompt the user as to whether they want to update the code contained within. I then thought that maybe I should in fact check if the code "needs" to be updated prior to prompting the user.
First off, I found the following question/solution: Using VBA to read the metadata or file properties of files in a SharePoint doc library
which I couldn't use without DSOFile.dll that I was able to install from here:
https://www.microsoft.com/en-us/download/details.aspx?id=8422
Here follows the code I have which doesn't work:
Private Function CheckTemplateIsNewerThanCurrentFile(ByVal templatePath As String) As Boolean
Dim templateName As String
Dim fso As New FileSystemObject
templateName = ActiveWorkbook.CustomDocumentProperties("TemplateName").Value
If fso.FileExists(templatePath & "\" & LocalTemplateName) Then
Dim objDSO As New DSOFile.OleDocumentProperties
objDSO.Open templatePath & "\" & LocalTemplateName, True, dsoOptionDefault
If Not objDSO.CustomProperties("LastCommitDate") = ActiveDocument.CustomDocumentProperties("LastCommitDate").Value Then
CheckTemplateIsNewerThanCurrentFile = False
Else
CheckTemplateIsNewerThanCurrentFile = True
TemplateLastCommitDate = objDSO.CustomProperties.Item("LastCommitDate")
End If
End If
End Function
And here (highlighted) is the error I receive trying to run the method above on an .xlsb file:
(FWIW: the reason for use of the .xlsb format is because we're working with 500K+ rows of data in the process we're carrying out. Yes, I know Excel is ABSOLUTELY NOT the tool for this but we're lumbered with it now)
I know I could have already tried changing the file format to .xlsm but because this file is version controlled that is a pain to do if the method is still likely to fail.
Thanks in advance,
Alex.

How to open Locked for Editing file as Read Only?

I have a macro that opens multiple files. If it comes to a file "Locked for Editing" it will give me an error saying
FileName is currently in use. Try again later.
How can I make it open said file as read only? I tried:
Workbooks.Open FileName:=Selected_EOS_Report_File, ReadOnly:=True
and
Workbooks.Open FileName:=Selected_EOS_Report_File, ReadOnly:=True, IgnoreReadOnlyRecommended:=True
Update: The first method does work. My code runs on multiple files that pass through the "Selected_EOS_Report_File" variable. At some point a file passed through that was an Excel temp file (begins the filename with "~$"). I created an if/then statement to skip over any such files.
As far as I know, you need Notify:= True
MSDN link
Notify
If the file cannot be opened in read/write mode, this argument is True
to add the file to the file notification list. Microsoft Excel will
open the file as read-only, poll the file notification list, and then
notify the user when the file becomes available. If this argument is
False or omitted, no notification is requested, and any attempts to
open an unavailable file will fail.
The code below worked for a similar Problem I had. This will set the ReadOnly and IgnoreReadOnlyRecommended parameters.
I tested this for Excel 365.
ReadOnly: True to open the workbook in read-only mode.
IgnoreReadOnlyRecommended: True to have Microsoft Excel not display the read-only recommended message (if the workbook was saved with the Read-Only Recommended option).
dim wbReadOnly as Workbook
Set wbReadOnly = Workbooks.Open(strXLSFileName, , True, , , , True)
link to VBA Documentation
Try this?
Dim wb As Workbook
Set wb = GetObject(Selected_EOS_Report_File)
wb.Open 'ReadOnly:=True (removed the readonly part)
Derived from this post: Opening .xlsx with VBA, File in Use error. Read-only not working
edit
A post here indicates a similar issue for older versions, and that if you undate to xlsx then it goes away:
https://social.technet.microsoft.com/Forums/en-US/5c9f7444-a2c7-4598-beca-21a6d5575d94/excel-file-currently-in-use

VBA - How to get the last modified file or folder in a directory in Excel 2010

What I want to do is more complex than selecting a file from a list of files. I will start in a directory, then I want to change to the most recently modified directory. I then want to repeat that process in a sub-directory, and then, inside of that, I want to select the most recently modified excel file and open it.
What is the best approach to do this?
What objects / methods should I be looking into?
The simplest function is
FileDateTime(pathname)
where pathname can be a directory for folder.
Alternatively, you can use the FileSystemObject object, DateLastModified property:
Dim fileModDate As String
Set fs = CreateObject("Scripting.FileSystemObject")
Set f = fs.GetFile(<filenamestringhere>)
fileModDate = f.DateLastModified
All of the above can be explored in VBA help.

Change .xla File with MSBuild

I'm trying to create a build script for my current project, which includes an Excel Add-in. The Add-in contains a VBProject with a file modGlobal with a variable version_Number. This number needs to be changed for every build. The exact steps:
Open XLA document with Excel.
Switch to VBEditor mode. (Alt+F11)
Open VBProject, entering a password.
Open modGlobal file.
Change variable's default value to the current date.
Close & save the project.
I'm at a loss for how to automate the process. The best I can come up with is an excel macro or Auto-IT script. I could also write a custom MSBuild task, but that might get... tricky. Does anyone else have any other suggestions?
An alternative way of handling versioning of an XLA file is to use a custom property in Document Properties. You can access and manipulate using COM as described here: http://support.microsoft.com/?kbid=224351.
Advantages of this are:
You can examine the version number without opening the XLA file
You don't need Excel on your build machine - only the DsoFile.dll component
Another alternative would be to store the version number (possibly other configuration data too) on a worksheet in the XLA file. The worksheet would not be visible to users of the XLA. One technique I have used in the past is to store the add-in as an XLS file in source control, then as part of the build process (e.g. in a Post-Build event) run the script below to convert it to an XLA in the output directory. This script could be easily extended to update a version number in a worksheet before saving. In my case I did this because my Excel Add-in used VSTO, and Visual Studio doesn't support XLA files directly.
'
' ConvertToXla.vbs
'
' VBScript to convert an Excel spreadsheet (.xls) into an Excel Add-In (.xla)
'
' The script takes two arguments:
'
' - the name of the input XLS file.
'
' - the name of the output XLA file.
'
Option Explicit
Dim nResult
On Error Resume Next
nResult = DoAction
If Err.Number <> 0 Then
Wscript.Echo Err.Description
Wscript.Quit 1
End If
Wscript.Quit nResult
Private Function DoAction()
Dim sInputFile, sOutputFile
Dim argNum, argCount: argCount = Wscript.Arguments.Count
If argCount < 2 Then
Err.Raise 1, "ConvertToXla.vbs", "Missing argument"
End If
sInputFile = WScript.Arguments(0)
sOutputFile = WScript.Arguments(1)
Dim xlApplication
Set xlApplication = WScript.CreateObject("Excel.Application")
On Error Resume Next
ConvertFileToXla xlApplication, sInputFile, sOutputFile
If Err.Number <> 0 Then
Dim nErrNumber
Dim sErrSource
Dim sErrDescription
nErrNumber = Err.Number
sErrSource = Err.Source
sErrDescription = Err.Description
xlApplication.Quit
Err.Raise nErrNumber, sErrSource, sErrDescription
Else
xlApplication.Quit
End If
End Function
Public Sub ConvertFileToXla(xlApplication, sInputFile, sOutputFile)
Dim xlAddIn
xlAddIn = 18 ' XlFileFormat.xlAddIn
Dim w
Set w = xlApplication.Workbooks.Open(sInputFile,,,,,,,,,True)
w.IsAddIn = True
w.SaveAs sOutputFile, xlAddIn
w.Close False
End Sub
I'm not 100% sure how to do exactly what you have requested. But guessing the goal you have in mind there are a few possibilities.
1) Make part (or all) of your Globals a separate text file that is distributed with the .XLA I would use this for external references such as the version of the rest of your app. Write this at build time and distribute, and read on the load of the XLA.
2) I'm guessing your writing the version of the main component (ie: the non XLA part) of your application. If this is tru why store this in your XLA? Why not have the main part of the app allow certain version of the XLA to work. Version 1.1 of the main app could accept calls from Version 7.1 - 8.9 of the XLA.
3) If you are just looking to update the XLA so it gets included in your version control system or similar (i'm guessing here) maybe just touch the file so it looks like it changed.
If it's the version of the rest of the app that you are controlling i'd just stick it in a text file and distribute that along with the XLA.
You can modify the code in the xla programmatically from within Excel. You will need a reference to the 'Microsoft Visual Basic for Applications Extensibility..' component.
The examples on Chip Pearson's excellent site should get you started.

Resources