Macro broke after re-boot - Excel unable to locate external text files - vba

As part of a larger macro Excel retrieves .dat files from a folder. After a crash and rebooting, the macro no longer works and seizes up upon trying to refresh.
There was also changes in security upon reboot where I had to enable all macros to be able to step though this current one.
I have double checked to make sure the path is correct and the files are still there.
Updated code and ended up crashing for unrelated memory issue. Fixed the memory problem and now won't run and is giving the same error code and message as before even with updated code. Current code which will run through the first loop but fails on the second.

If I am not mistaken, Dir just returns the filename found within that directory and not the full path to that file. What likely happened is your directory was initially set to F: so the macro used this as the default path when searching for the file. The best way to do this would be to store your directory in a constant string, and then append the two together. Something like this:
Const fPath as String = "F:YourPathHere\"
strFile = fPath & Dir(fPath & "*.dat")
Debug.Print strFile ' Just to make sure it is setting properly.

Related

What is the difference between Program and Argument directories when calling .exe using Shell in VBA?

My latest attempt to solve my problems when calling a .exe with an input argument from Excel-VBA uses this script:
Sub RunProgram()
Dim wsh As Object
Set wsh = VBA.CreateObject("WScript.Shell")
ChDir "\\path\folder1\folder2\"
StartExeWithArgument
......
End Sub
Public Sub StartExeWithArgument()
Dim strProgramName As String
Dim strArgument As String
strProgramName = "program.exe "
strArgument = "datafile.gdp"
Call Shell("""" & strProgramName & """ """ & strArgument & """", vbNormalFocus)
End Sub
The path I set as the working directory is the working directory of the .exe program, and the location of the input file datafile.gdp. However, this current script calls the .exe without loading the argument file and the calculations the .exe is supposed to run do not occur. Instead the .exe launches to its main page as though I clicked a desktop shortcut to start a new project. When loaded correctly, the .gdp file should cause the calculation to initiate and run in the background without ever appearing to the user.
If I change the path of the input file to:
strArgument = "\\path\folder1\folder2\datafile.gdp"
But keep everything else the same, the .exe launches and calculates automatically, but wants to write files in the following duplicated directory, (all prefixed with the name of the input file):
\\path\folder1\folder2\PATH\FOLDER1\FOLDER2\
If I create the file path for it to operate in everything operates as it should, BUT the path is actually 6 folders deep in reality and this is all being duplicated, meaning the files are too deep to be backed up on our system. So I need to launch the program and have it operating without this duplication of the directory. It works fine when not launched from this VBA script, and worked fine before the .exe was updated by an external company.
Why can the Call Shell command find the .exe without a path, but I
need to provide a path for the argument?
strArgument = ... requires a path to find the argument file, despite the file being in the current directory, providing the path seems to pass a duplicated path to the .exe causing it to crash if I don't create the folders representing the duplicated directory so it can operate within them. Is there something very basic I am missing regarding directories?
My previous up-voted but unanswered question here provides more context.

Setting Directories and the If Len(Dir(... statement in VBA

I have a file exists under this path:
//path/folder1/folder2/datafile.gdp
It is an input to an external program being called from vba in this manner:
Sub RunProgram()
Dim wsh As Object
SetCurrentDirectory "\\path\"
ChDir "\\path\folder1\folder2\" 'Set Directory
Set wsh = VBA.CreateObject("WScript.Shell")
check = CurDir
Statusnum = wsh.Run(Command:="program.exe ""\\path\folder1\folder2\datafile.gdp""", WindowStyle:=1, waitonreturn:=True)
But on the final line, including \path\folder1\folder2\ before the input file name appears to cause the external program to want to write some files into a duplicated directory that doesn't exist, causing an error. It used to work in this format before the .exe was updated by an external company. It now wants to write some files here, all prefixed with the name of my input file:
\\path\folder1\folder2\PATH\FOLDER1\FOLDER2\
Hoping to fix this, I changed the final line of the code to this, following some comments on a previous post here on SO:
Statusnum = wsh.Run(Command:="program.exe ""datafile.gdp""", WindowStyle:=1, waitonreturn:=True)
Since the directory is set correctly prior to calling the .exe, I thought removing the path for the input file would solve the issue.
The program now launches, but doesn't appear to load the input file with it and no longer runs calculations automatically in the background as it should. Instead, it launches and the main .exe window pops up to the user as if it had just been launched for setting up a new project, calculations don't occur automatically.
To check which directory the VBA code was try to pull my datafile.gdp from, I created these loops directly before calling the .exe:
If Len(Dir("\\path\folder1\folder2\datafile.gdp")) = 0 Then
FileIsMissing1 = True 'I use Excel-VBA watches to break if true
End If
If Len(Dir("datafile.gdp")) = 0 Then
FileIsMissing2 = True
End If
Bizarrely, neither of these loops causes a break. The file only exists in
\\path\folder1\folder2\datafile.gdp
Not in the duplicated directory... so why are both of these statements satisfied? Does entering the directory make no difference even when the current directory has been set? The current directory seems to be impacting the line:
Statusnum = wsh.Run(Command:="program.exe ""\\path\folder1\folder2\datafile.gdp""", WindowStyle:=1, waitonreturn:=True)
But not these if loops, and I'm not sure why.

DateCreated glitch? How to identify if overwriting

As part of an auto-update macro, I have a copy of an Access FrontEnd on the local drive which when opened, checks to see if the file on the server has a newer CreatedDate. If it is newer, my code currently uses fileSystemObject to CopyFile and overwrites the local drive version (filename remains the same).
The problem I am having however is that when this is done, the 'date created' does not change to that of the newer file and so continually loops as the old file is closed and the new one opened - which checks for updates based on date created... I even tried using kill on the local file and waiting 10 seconds before doing the Copyfile command but even then it appears with the deleted file's creation date.
When I get back to the office I'm going to try copying the file from the server to the local drive without renaming it, deleting the original local drive file, then copying the newly created file so I can rename it back to the original name (the name should not be changed so that any shortcuts will still work).
Has anyone come across this before and found a solution? Am I missing something obvious that would 'refresh' the created date of the file?
EDIT
I think this is pretty close to what I had.
Dim strSource As String, strDest As String, strOrigDB As String, strSvrDB As String
Dim varOldDB As Variant, varNewDB As Variant, fso As Object
Set fso = CreateObject("scripting.filesystemobject")
strSource = "\\192.168.1.2\Data\svrDatabase"
strSvrDB = "AnyOldName.mde"
strDest = "C:\myFolder\myDatabase"
strOrigDB = "KeepMyName.mde"
varOldDB = (strDest & "\" & strOrigDB)
varNewDB = (strSource & "\" & strSvrDB)
If fso.getfile(varOldDB).DateCreated < fso.getfile(varNewDB).DateCreated Then
Kill strDest & "\" & strOrigDB
Excel.Application.Wait Now() + TimeValue("00:00:05")
fso.copyfile (strSource & "\" & strSvrDB), (strDest & "\" & strOrigDB), True
'open new database version
ShellExecute 0, "Open", (strDest & "\" & strOrigDB), "", "", 1
DoCmd.Quit
End If
I was originally using date modified, but noticed that as soon as the Front end opened, this would get renewed and would therefore always be a newer date value than the server file.
EDIT
After thinking about this, and hoping my logic hasn't completely broken down, it would be best if I had a shortcut for the user to click on, but instead of opening the Frontend, it opens a script file that checks for an update. If there is an update, then it deletes the local Frontend and copies the server one (which should be named differently to the original) to the local folder - then opens the new frontend.
This would mean that the datecreated being checked is always going to be updated on copy to the local folder and the kill will work because the file has not been opened. I am still a little wary of using lastdatemodified incase a user has the database open when an update is created - the Frontend contains tables used in searches which I believe will alter the modified date of the Frontend. In this scenario the local date modified would still be greater than a new frontend on the server.
You should be using Date Modified. That's when the file was last changed.
This is what helps says about times.
Timestamps are updated at various times and for various reasons. The only guarantee about a file timestamp is that the file time is correctly reflected when the handle that makes the change is closed.
So try closing all files before comparing times.
Also From https://support.microsoft.com/en-us/kb/172190
When a name is removed from a directory (rename or delete), its short/long name pair and creation time are saved in a cache, keyed by the name that was removed. When a name is added to a directory (rename or create), the cache is searched to see if there is information to restore. The cache is effective per instance of a directory. If a directory is deleted, the cache for it is removed.
Also coping from an untrusted source will change last modified for sure.
Also there are rules for copy versus move.
Also files need to be wholey within Windows eco system for windows rules to apply for sure.

VBA fails to find a file

I have a VBA script used to process Word documents. The first thing the program does is to create an index of the documents in a defined set of folders. It then goes through the list processing each of the indexed documents.
The problem I am having is that it will sometimes decide that a particular document cannot be found, even though it previously indexed the document and a quick spot check shows the document to be in the correct place.
Can anyone shed some light on why VBA should display this behaviour?
The script is using the Dir$ function to index the files, and the Documents.Open function to open each word document for processing.
Sample code:
ChangeFileOpenDirectory (folderName)
inputFileName = Dir$(folderName & "*.doc")
Do While inputFileName <> ""
... call various functions here ...
inputFileName = Dir$
Loop
One of the functions called in the block has the following line:
Set currentDoc = Documents.Open(fileName:=docFileName, AddToRecentFiles:=False, Visible:=False)
This is the point at which the code is failing.
One of the most annoying things I have found is that recent files links are returned as the files themselves with Dir. You can use the FileSystemObject to check the file type.
I copy/paste your code and it works correctly.
However, it leaves all the files open (and hidden), and when you run it in another directory, additional files are opened and added to the open projects (take a look in the VBA editor).
My only guess is that after a while you're hitting the maximum allowable number of open files.
Try adding
currentdoc.Close
just before
inputFileName = Dir$
A few reasons, some duplicated from other answers:
If the path+ filename is long enough ... (you already answered in a comment)
If you are writing new files to same directory, Dir$ may get corrupted (happened to me)
If you have filenames with non-std chars (ex. "#")
Files locked by other processes
Files deleted while the macro is running
You may also try this code ...
Set fso = CreateObject("Scripting.FileSystemObject")
If Not fso.FileExists(file) Then ....
First enable the Microsoft Scripting reference in the VBE

How to use Process.Start

I'm using process.Start to run Convert.exe. This program's purpose is to convert all files which are in the exe's folder. So when I normally use it, I copy paste a file into the same folder as Convert.exe and then run Convert.exe. Convert.exe will create a new "converted" file in the same folder.
I'm trying to automate this tedious process. A User selects a file which needs to be converted from FolderA, I copy it to the same folder where Convert.exe is and I'm using process.start(Convert.exe) to run it.
Just to be clear, this "Convert.exe" accepts NO arguments.
The problem: "Convert.exe" is not converting the files in its folder. Instead it's converting all the files in FolderA for some weird reason. I don't know why it picked that folder, I never even try to send it as an argument or nothing.
Here's the code I have:
Dim techInfo As New System.IO.FileInfo(itm.strFilePath)
techInfo.CopyTo(ConverterPath & techInfo.Name)
Dim procInfoConvert As New ProcessStartInfo
procInfoConvert.CreateNoWindow = False
procInfoConvert.Arguments = ""
procInfoConvert.FileName = ConverterPath & "Convert.exe"
Dim procConvert As Process = Process.Start(procInfoConvert)
I did a test where I copy pasted a file into the "Convert.exe" folder and then just run this code:
process.start(ConverterPath & "Convert.exe")
The exe returns nothing, same as if there was no files in the folder.
The only thing I can think of is that when process.Start is run, it copies the file to another location and runs it from there.
Any ideas anyone?
Try this:
procInfoConvert.WorkingDirectory = ConverterPath
That'll set the process up to start in the directory it's contained in, instead of the current directory.