Powerpoint VBA Presentations File names - vba

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

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?

Can a Variable be stored in an Excel File that can not be accessed through Excel

I just discovered that in MS Word it is possible to store a Variable in a MS Word File that can not be accessed through the regular interface when running Microsoft Word.
Sub SetMyVariable()
Dim VARNAME As String
VARNAME = "HiddenVar"
ActiveDocument.Variables.Add VARNAME, "My special info"
End Sub
This gets saved in the XML Schema under word\settings.xml
I have tried using the ThisWorkbook Object in Excel, but it doesn't seem to have a Variable object that can be added like in word.
I want to know if there is something similar in Excel to store information/varialbes that get saved with the file.
PS: the closest thing I can think of (and use in codig) is a hidden named range.
You can try with the CustomXMLParts property of the Workbook which from the link seems a generic feature of Office products and available in Excel. Given you noted that a user would have to manually inspect the XML within the unzipped xlsx files then this seems to map to the Word Variables feature. The code sample just substitutes ThisWorkbook for ActiveDocument:
Option Explicit
Sub TextXMLPart()
Dim objXMLPart As CustomXMLPart
'add
Set objXMLPart = ThisWorkbook.CustomXMLParts.Add("<foo>bar</foo>")
'inspect
For Each objXMLPart In ThisWorkbook.CustomXMLParts
Debug.Print objXMLPart.XML
Next objXMLPart
End Sub
The accepted answer to this question (which focuses on Excel and vsto) states that:
Custom XML parts For an application-level add in, this is my preferred method of storing any application data that needs to be persisted in a saved xls file without ever being visible to the user.

Splitting MS Publisher 2010 document into multiple files

I want to split a multi-page MS Publisher 2010 document into a set of separate documents, one per page.
The starting document is from a mail-merge, and I am trying to produce a set of numbered and named tickets as PDFs to send to people for an event (this is for a charity). The mail-merge seems to work fine and I can save the merged document and it looks OK with e.g. a list of fifty people giving me a 50-page document.
Ideally the result would be a set of PDFs.
I have tried to create some simple VBA code to do this, but it is not working consistently. If I try this very simple macro below , I get the correct number of documents, but only perhaps 1 or 2 documents with the correct contents out of every five. Most of the documents are completely empty.
Sub splitter()
Dim i As Integer
Dim Source As Document
Dim Target As Document
Set Source = ActiveDocument
For i = 1 To Source.Pages.Count
Set Target = Documents.Add
Source.Pages(i).Shapes.Range.Copy
Target.Pages(1).Shapes.Paste
Target.SaveAs Filename:="C:\Temp\Ticket_" & i
Target.Close
Set Target = Nothing
Next i
End Sub
I did sometimes get an error that the clipboard is busy, but not always.
Another approach might be to start with the master document and do this looping over the separate documents and fill in the personal details for each person's ticket and directly produce the PDFs. But that seems more complex, and I am not a VB programmer (but been doing C++ etc for 20+ years, so I can program :-) )
A final annoyance is that it seems to keep opening a new Publisher window for each document. It takes a while to then close 50+ copies of publisher, and the laptop starts to crawl...
Please advise how best to get round these issues. I am probably missing something trivial, being a relative VB(A) newbie.
Thanks in advance for any suggestions
Try coding something like this:
Open Publisher application (CreateObject()?)
Open Publisher document (doc.Open(filename))
Store the total amount of pages in a global variable (doc.Pages.Count)
Close document (doc.Close())
Loop the following for each page
Copy the pub file and rename it to name & "page" & X
Open the new pub file
Remove all Pages except page X from the pub file
doc.Save()
doc.Close()
Copying files with VBA is easy, but copying pages in Publisher VBA is quite a hassle, so this should be easier to achieve

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.

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