VBA fails to find a file - vba

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

Related

Word VBA macro errors opening files when run on some computers but not others?

This has been a thorn in my side for months. It happens off and on for a small (but growing) number of users at my company, but not others running the same exact Word VBA Macro. The users get "5097:Word encountered an issue" or "4605: Command failed" runtime errors on lines of the code that open word or txt files. All are running the same build of windows and have the same permissions (according to the tech team.) The files are on a shared network drive.
Public Function readData(datafile As String) As String
'datafile = "\\network\unc\path\folder\folder\data.txt"
'I have confirmed this passes to the function correctly.
Dim db As Document
'Before it is suggested, I've tried early-binding, late-binding, and
'diming as Variant, Object, etc. to no effect
'Errors on this line
Set db = Documents.OpenNoRepairDialog(fileName:=datafile, ConfirmConversions:=False, _
ReadOnly:=True, Visible:=False)
'I have tried Documents.Open to no avail, in addition to toggling all of the parameters to
'or removing parameters see if I would get a different result.
'I have tried declaring the Word.Application and Application objects and prepending that
'to the function. Nadda. I also tried just the function, without setting as an object. No dice.
'---rest of code---'
End Function
I've used Debug.Print to check the file path was passed to the function correctly--it is. Also this issue does not have to do with the file being a txt file. If I comment out this function in the main sub, I get the same error on the next function that attempts to open a word doc.
Again, this exact macro runs flawlessly on some workstations.
Here's the real kicker:
The users are all able to navigate to the file paths the macro is trying to open in File Explorer without problem. When I run the "Documents.Open(datafile)" or "Dir(datafile)" functions in the immediate window they work perfectly, no issue. What gives?

Powerpoint VBA Presentations File names

Consider VBA for PowerPoint -
Is this a valid Presentations function call?
Presentations(".\directory\ppname.ppt")
Note that this will be called from within a PowerPoint presentation VBA, to open another one in a sub-directory.
The Microsoft Presentations examples (and most others) are not specific about the filename forms accepted, e.g. those using the ".", "..", "\" directives recognized in DOS scripts.
This seems to work with Powerpoint 2007.
As described in the comment, it takes a block of text (the TextRange), the starting position and length of file reference, also a LinkAddr. LinkAddr is essentially a DOS-style file reference, like "..\folder\ppfile.ppt".
The intention here is to launch another PowerPoint tool by invoking its show.ppt or show.ppsm file name. The file name can refer to some other directory using MSDOS file name stuff. I don't know whether it can span different machine platforms, but it seems to work within one Windows 10 system.
My difficulty in getting this to work was some full-path links to images, e.g. something like C:\blah\blah\image.jpg, in the Visual Basic code. PowerPoint didn't like these, instead asked about enabling macros, and just hung up when one of my file links were to be executed. By getting rid of the "macro" complaints, this suddenly started working.
Or maybe some bugs have been fixed in recent repairs to my 2007 PowerPoint tools??
Go figure...
Sub InsertLink(ByRef Trange As TextRange, fpos As Long, msglen As Long, LinkAddr As String)
' Insert an HTML link into the selected TextFrame.
' get the character range
Dim Hrange As TextRange
Set Hrange = Trange.Characters(Start:=fpos, length:=msglen)
' make it an HTML link
With Hrange.ActionSettings(ppMouseClick)
.Action = ppActionHyperlink
.Hyperlink.Address = LinkAddr
End With
End Sub

VBA code (if needed) to save new Word document in same directory as other Word doc

Many users, myself included, begin editing a Word document, create a new Word doc, and wish to save the second doc in the same directory as the first doc. This is the default behavior in an editor such as emacs. Word 2013, alas, makes me pick the directory ("Folder") where I wish to save the new file, forcing me to select among various network folders and then select multiple subdirectories before I reach the one containing my first document. I used to have a simple VBA script that would find the directory of the first file and then save the new file in that directory, or at least it would set the directory of the first file as the default directory for saving files. Does anyone have code to do what I'm looking for? Thanks!
This will the working directory to the directory of the first file you were working on:
ChDir(Application.Documents(Application.Documents.Count).Path)
If you want to save the most recent opened document to the same location as the first file you were working on, then try the following
Sub SaveWithFirstFile()
NewFileName = "filename1.docx
Application.Documents(1).SaveAs2 FileName:=Application.Documents(Application.Documents.Count).Path & "\\" & NewFileName
End Sub
Change "filename1.docx" to what you want it to

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

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.

Batch add a macro to word documents?

I have several hundred .doc word documents to which I need to add a macro which runs when the .doc file is opened and creates a header for said document based on the file name. Is there a way to do this as a batch? I have been individually opening each document and going into visual basic --> Project --> This Document then inserting a .txt file which contains the code. Is there a fast way to do this for multiple documents?
As a learning exercise, put this into the "ThisDocument" part of Normal (the Normal.dot template) in the VBE
Open a word document and watch what happens.
I don't think you need to put your code in every single file, I think you should be OK with using the Document_Open event in Normal.dot.
Just make sure it shows up as a reference in your word documents that you open but I don't see why it wouldn't
If you absolutely need it in every file then it can be done but the problem is if you make one small change to the code, you have to go through all this again. The idea with code is to write it once, use it many times.
You can write VBA code that alters the VBA code in other documents, but you need to "Trust access to the VBA project object model" in the Trust Centre options. This could open you up to viral code if you download Word documents with malicious VBA code in them. What you want to do, essentially, is write a VBA virus. There are legitimate reasons for doing this, and also malicious ones, I leave the ethics of the uses of these techniques up to the user. Knowledge itself is not malicious.
Here's the meat, you will need to write your own code to loop through the documents and possibly save them as .docm files.
Sub ReplaceCode()
Set oDoc = ActiveDocument
Set oComponents = oDoc.VBProject.VBComponents
For i = oComponents.Count To 1 Step -1
If oComponents(i).Type = 100 And oComponents(i).Name = "ThisDocument" Then
With oComponents(i).CodeModule
.DeleteLines 1, .CountOfLines
.AddFromFile "C:\ThisDocument.cls"
End With
End If
Next i
End Sub
Also, if you create your code file by exporting from VBA, you will need to remove this from the top of the .cls file:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Personally, I would drive this from Excel, maybe using a worksheet to hold a list of the files or locations to update, and another sheet for the code to populate with a list of files updated.