(VBA) Can't check if file exists because Dir is case-sensitive - excel

I'm writing a program which writes links into an excel sheet based on various data found in the sheet. My company used SOLIDWORKS PDM to store files, so I'm using the PDM API (the pdmv object) to write the links. Some of the files don't exist due to faulty data, so I need some kind of error checking before referencing the pdmv object and writing the link.
The issue I'm running into is with case-sensitive file locations. GetFolderFromPath and GetFile commands are case-insensitive, so the program writes links without problems if they exist. However, since the Dir command is case-sensitive, I can't properly check if the files exist before running the link-writing commands.
Is there any way to use Dir without worrying about case, or is there a different, case-insensitive method to checking if a file exists that might work here?
Thanks for the help.
EDIT:
evidently, Dir is case-insensitive, so the issue must be arising from the server that my company uses to store files, SOLIDWORKS PDM. Unfortunately, this doesn't fix the issue, so any ideas are welcome.
Sub writeLink(link As String, palRow As Long, asArray, pdmv As Object)
Dim textDisp As String
textDisp = asArray(1) & "-" & asArray(2) & "-1000"
Dim filename As String
filename = textDisp & ".sldasm"
testVar = Dir(link & "\" & filename)
If Not testVar = "" Then
Dim efolder As Object
Dim efile As Object
Set efolder = pdmv.GetFolderFromPath(link)
Set efile = efolder.GetFile(filename)
fileLink = "conisio://myvault/explore?projectid=" & efolder.id & "&documentid=" & efile.id & "&objecttype=1"
calc.Hyperlinks.Add Anchor:=calc.Cells(palRow, 8), _
Address:=fileLink, _
TextToDisplay:=textDisp
Else
calc.Cells(palRow, 2).Interior.Color = 65535
End If
End Sub

Related

ASFolder String for Application.ActiveWorkbook.Path & "\" returning Run-Time '91'

I am building fairly complex accounting suite for an accountant and I don't quite understand why each time file changes folder I encounter this error:
Object variable or With block variable not set.
Code:
Public Function ASFolder() As String
Dim ASwb As Workbook: Set ASwb = ThisWorkbook
If ASwb.Sheets(1).Range("B8").Value = "A" Then 'file path detection
ASFolder = Application.ActiveWorkbook.Path & "\" < < < WHERE ERROR 91 IS INDICATED.
Else
ASFolder = ASwb.Sheets(1).Range("B8").Value & "\"
End If
End Function
There is code that is being launched upon file opening. Could this be related?
Purpose is simple: when file is being open detect certain settings within the document and perform desired actions accordingly - therefore this setting is of significant importance to me.
There is no issues with this until I change folder for the file, as if first file opening does something unusual or something I don't understand.
Greatly appreciated any suggestions.

Is it possible to read files in order of Date Modified?

My macro will need to read through a very large directory of files and parse data from them. This directory is updated periodically so I am trying to optimize my program to only read files that were added since the last time the program was run.
So far using FileSystemObject it seems I can only read files alphabetically, if I'm not mistaken.
The best solution I have so far is to read all the files every time, create an array containing the file information, sort by DateModified, then open only the files I need. I'm curious to see if I can skip this step by reading files in order of DateModified.
Thanks in advance.
Shell does seem to be a good option here - although I haven't compared performance against a FSO. You could, for example, consider the forfiles command which allows you to retrieve files modified after a specified date?
Some sample code for that would be as follows:
Public Sub RunMe()
Dim fileNames As Collection
Dim path As String
Dim dat As Date
Dim file As Variant
'Set the path and 'find after' date.
path = "c:\user\documents"
dat = #1/1/2018#
'Fetch the files, setting mask as required.
'This example is fetching all .txt files.
Set fileNames = GetFilesModifiedAfter(path, dat, "*.txt")
'Process the list of files.
If Not fileNames Is Nothing Then
For Each file In fileNames
' ... do stuff here.
Debug.Print path & "\" & file
Next
End If
End Sub
Private Function GetFilesModifiedAfter( _
path As String, _
after As Date, _
Optional mask As String) As Collection
Dim cmd As String
Dim piped() As String
Dim result As Collection
Dim i As Long
'Build the command string.
'Date must be formatted as MM/DD/YYYY.
cmd = "cmd.exe /s /c forfiles /p " & _
"""" & path & """" & _
" /d +" & Format(after, "mm/dd/yyyy")
'Add the mask if passed-in.
If mask <> vbNullString Then cmd = cmd & " /m " & mask
'Execute the command and split by /r/n.
piped = Split(CreateObject("WScript.Shell").Exec(cmd).StdOut.ReadAll, vbCrLf)
'Leave if nothing is returned.
If UBound(piped) = -1 Then Exit Function
'Poplate the result collection,
'and remove the leading and trailing inverted commas.
Set result = New Collection
For i = 0 To UBound(piped)
If Len(piped(i)) > 2 Then
result.Add Mid(piped(i), 2, Len(piped(i)) - 2)
End If
Next
'Return the result collection.
Set GetFilesModifiedAfter = result
End Function
Update
I've just done some testing and it seems FSO is quicker, certainly on Folders containing fewer than 100 files. It'd be interesting to run this on really large folders (say a thousand files) as instinctively I feel Shell might have a performance advantage. However, for now, here's the FSO version:
Private Function GetFilesModifiedAfter2( _
path As String, _
after As Date, _
mask As String) As Collection
Dim fso As Object, file As Object
Dim result As Collection
'Instance of objects.
Set fso = CreateObject("Scripting.FileSystemObject")
Set result = New Collection
'Iterate the files and test date last modified property.
For Each file In fso.GetFolder(path & "\").Files
If file.Name Like mask And file.DateLastModified > after Then
result.Add file.Name
End If
Next
'Return the result collection.
Set GetFilesModifiedAfter2 = result
End Function

How to open a .PDF file with wild card option via excel macro

Since I am very new to the excel macro I am trying to develop a code which is able to open the PDF file.But There are some PDF files in my system which are generated by another system therefore those files names change day by day and some figures are included too.
As an example,"Process Report 151120183569844" like this.These figures change everyday.I tried it with adding WILDCARD option but it doesn't work.How do I open this PDF with only a part of the file name?
Sub Open_PDF()
Dim pdfPath As String
pdfPath ="D:\Reports\Process Report*" & ".pdf" 'I used wildcard instead "Process Report 151120183569844"'
Call OpenAnyFile(pdfPath)
End Sub
Function openAnyFile(strPath As String)
Set objShell = CreateObject("Shell.Application")
objShell.Open(strPath)
End Function
As pointed out in another answer, the Dir function with a wildcard should do the trick.
Here's an example using the original openAnyFile function.
Sub Open_PDF()
Dim filePath As String, fileName As String
filePath = "D:\Reports\"
fileName = Dir(filePath & "Process Report*.pdf")
If fileName <> "" Then
openAnyFile filePath & fileName
End If
End Sub
Function openAnyFile(strPath As String)
Dim objShell As Object
Set objShell = CreateObject("Shell.Application")
objShell.Open (strPath)
End Function
You cannot open a file using a wildcard - it's just common sense, what if more than one file was matching your criteria - which one would you want to program to open? You have to specify the exact file name to open it.
if there is just one file in the target directory, you can use something like the following code to open it, regardless of its name:
sFound = Dir(ActiveWorkbook.Path & "\Process Report*.xlsm")
If sFound <> "" Then
Workbooks.Open filename:= ActiveWorkbook.Path & "\" & sFound
End If

How do you open a pdf file with VBA code for a relative file path?

I am trying to find the command and correct coding to open a PDF file with a relative file path to the active excel file. The code below works fine as a link directly to the file. However, I just need this code snippet to find the PDF file that is sitting in the same file as the opened excel file and open accordingly.
Sub OpeningPDF()
'ThisWorkbook.FollowHyperlink "C:\Users\Michael\My Documents\totals\copy.pdf"
End Sub
I tried working with ThisWorkbook.path but nothing I tried with that worked or seemed to be outdate. Any help in this matter would be much appreciated.
I have found two solutions to this:
The first one is using the built-in Shell() function. This should automatically resolve the relative path (relative to the applications current working directory):
Public Sub StartExeWithArgument()
Dim strFilename As String
strFilename = "../folder/file.pdf"
Call Shell(strFilename, vbNormalFocus)
End Sub
The second one uses the Shell.Application COM Object and will basically do the same as the first one.
Sub runit()
Dim Shex As Object
Set Shex = CreateObject("Shell.Application")
tgtfile = "../folder/file.pdf"
Shex.Open (tgtfile)
End Sub
If you start with ThisWorkbook.Path and your relative-reference, then trim a layer off for every "..\" in the relative reference, you'll get the path.
Function RelativeToAbsolutePath(ByVal RelativePath As String) AS String
Dim TempStart AS String, TempEnd AS String
TempStart = ThisWorkbook.Path
TempEnd = RelativePath
If Left(TempEnd,1) = "\" Then TempEnd = Mid(TempEnd,1)
RelativeToAbsolutePath = ""
On Error GoTo FuncErr
While Left(TempEnd,3)="..\" AND InStrRev(TempStart,"\")>0
TempStart = Left(TempStart,InStrRev(TempStart,"\")-1) 'Remove 1 layer from Workbook path
TempEnd = Mid(TempEnd,4) 'Remove 1 instance of "..\"
Wend
RelativeToAbsolutePath = TempStart & "\" & TempEnd 'Stitch it all together
FuncErr: 'You may want a DIR(..) check to see if the file actually exists?
End Function
You can then open it with Shell

Define varables in Excel then use in Access VBA at same time

Is it possible to define a string variable in excel and then use that variable inside Access?
I have a program where in Excel a window pops up asking for where a file is located which will feed into an Access database - get processed - then shoot into Excel. The problem is that this is for a lot of different people and so each computer is going to have its own extension address of where the file is located, so it is necessary to have it be easy for users to identify where their file is located instead of hard-coding it into the VBA.
No matter what I try, I can't seem to figure out how to get the string variable to talk to the access database so it knows where to go look for the file.
I can't seem to find a solution for this. Anyone have any ideas?
Here is the code I have so far: This is what is inside the excel file----
'CommandButton1 is a button inside of a form window that pops up for the user to enter the address of the file
Public Sub CommandButton1_Click()
'both of these are public/global variables defined in a global macro
locationaddress = txbBrowse2.Value
LocationOfData = txbBrowse.Value
Dim appAccess As Object
Set appAccess = CreateObject("Access.Application")
'location of data is the location of the access file itself
location address is the string that I'm trying to feed into access
appAccess.OpenCurrentDatabase LocationOfData, exclusive:=False
appAccess.Application.Run "DoExcelImport"
End Sub
'Here is the code inside the access file, the idea is that it will modify the "Import-TEST" saved import. It will change where it pulls the excel sheet that contains a bunch of items that requires access to process.
Sub DoExcelImport()
DoCmd.SetWarnings False
Dim ies As ImportExportSpecification, i As Long, oldXML() As String, newXML As String
Set ies = CurrentProject.ImportExportSpecifications("Import-TEST")
oldXML = Split(ies.XML, vbCrLf, -1, vbBinaryCompare)
newXML = ""
For i = 0 To UBound(oldXML)
If i = 1 Then
' re-write the second line of the existing XML
newXML = newXML & _
"<ImportExportSpecification Path = """ & _
locationaddress & _
""" xmlns=""urn:www.microsoft.com/office/access/imexspec"">" & _
vbCrLf
Else
newXML = newXML & oldXML(i) & vbCrLf
End If
Next
ies.XML = newXML
ies.Execute
Set ies = Nothing
DoCmd.SetWarnings True
End Sub
Probably the easiest way might be using
SaveSettings(AppName As String, Section As String,Key As String, Setting As `String)
to store the string in the registry,
GetSettings((AppName As String, Section As String,Key As String)
to get it in Access, and
DeleteSetting (AppName as String)
to delete it.
Is probably a bit abusing the registry, but an easy way.

Resources