Word - list unavailable fonts

Hi, all,

I’m working on a script to batch-process exporting PDFs out of a bunch of Word documents. Word for Mac v. 16.67.

One issue we have is that the user who’s creating the PDFs may not have the same fonts installed and Word doesn’t give any warning that fonts are being substituted. This can cause reflow and in some instances may cause elements not to display in the final PDF.

I haven’t been able to find much about this in scripting terms. It seems like this:


tell application "Microsoft Word"
set myUnFonts to unavailable fonts of active document
end tell

… should work to get a list of fonts. At least the Word dictionary says that’s what it does. But all I get is “missing value” when testing against a document I know has fonts substituted.

I also found a reference in the dictionary to “get dialog dialog font substitution”, and I can run that and get a reference to the dialog … but then what do I do with that reference to return any useful information? I couldn’t find anything other than getting it to display using “show”.

Anybody out there have any experience or ideas about this?

Thanks in advance for any advice!

Mary

As for the ‘unavailable fonts’ property, try accessing it this way:

tell application "Microsoft Word"
	set myUnFonts to (get unavailable fonts of active document)
	--> {"Times New Roman"}
end tell

Alternatively, you can just get the properties of the document. It will return a mountain of them and one should be ‘unavailable fonts’.

[format]properties of document 1
→ unavailable fonts:{“Times New Roman”}
[/format]

You can also do this but I’d try the first approach above:
[format]set docProps to properties of active document
set myUnFonts to unavailable fonts of docProps[/format]

I’m not sure what exactly is the cause of this particular issue but I occasionally find that applescript returns ‘missing value’ whenever you surprise it by asking for a specific property. Sticking it inside brackets prefaced with a get will often encourage it to respond. Also, once it gets it, it seems to remember and not require the workaround.

That said, the property may hold an inaccurate list of fonts. It does for me.

As to the dialog commands, there is an ‘execute dialog’ which you can run against the particular dialog.

set myd to get dialog dialog font substitution
execute dialog myd

It doesn’t seem to work for me (in Word 2011) but it might with a newer version.

What the dialogue does is allow you to substitute fonts within a particular document from among those on the computer in question. It will typically suggest a likely substitute, e.g. Times for Times New Roman or Arial for Helvetica. Sometimes the substitute is not well-chosen… A document using Impact had it replaced with Geneva (without ever coming up in the font check). I only saw it when I checked the resulting PDF. If the execute command doesn’t work, you could theoretically cycle through every document getting it to accept the substitution offered.

Ultimately, you may find it easier to run your script from a computer that has the required fonts, and if this operation may need to be done again in the future, set word to (save and) embed the fonts in each document and then it shouldn’t matter whether that font is installed on the user’s machine.

Thanks, Mockman, I very much appreciate your detailed reply.

Unfortunately, none of them seem to be working for me. “Execute” runs, but doesn’t seem to do anything. Using “get” was a good idea, but it’s returning “missing value”. Getting the properties does the same; I had tried that before I came to the forum.

Ultimately, I don’t want to substitute fonts, I just want to identify what fonts were used in preparing the document so that we can activate them if we have them. If we can’t get the font, we’ll cross that bridge when we come to it. We don’t control how these documents are being prepared; it’s not being done within our company. But we need to make PDFs of them and need to make sure that the text is displaying correctly when we do so we don’t lose important elements in the PDF.

I may wind up establishing a short list of fonts that are used in the sample documents I have – Calibri, Arial and TNR – cycle through all the paragraphs and check against the “approved” list, report any documents that use anything apart from those fonts for further (likely manual) investigation.

Thanks again for your suggestions.

Mary

My pleasure. Given your situation, I think that’s the best you can do. It’s kind of weird that an application that’s as old as Word doesn’t have a simple method to list a document’s fonts. A lot of the stuff related to formatting, styles and fonts doesn’t seem to have really changed since Word 5 which is one of the reasons I avoid using it for anything personal anymore. They add features but once they set, they are neglected and remain unimproved.

FWIW, there is a stack overflow page on the subject:
https://stackoverflow.com/questions/5261108/list-fonts-used-by-a-word-document-faster-method
Perhaps you can find something useful there. I think it also has a link to an external site (tips.net) that also has a visual basic solution (two actually, depending upon the version of word).

Another oddball approach you might look at… assuming the documents are docx, you can unzip the file and look at some of its components. There is a ‘fontTable.xml’ in its guts but it includes unrelated fonts, which I guess is typical. However, the ‘document.xml’ file seems to include only intended fonts. You can then search for ‘rFonts’ which seems to be the relevant tag for the beginning of each font usage. If you’re comfortable with the shell, you could probably automate the process.

<w:rFonts w:ascii="Courier Prime" w:eastAsia="Times" w:hAnsi="Courier Prime" w:cs="Courier Prime"/>

Additionally, there is a size tag, which looks like this below. The value is 2x the actual font size, e.g. 14 points in this case — nothing is clear and easy with Word.

<w:sz w:val="28"/>

As an aside, when I use ‘active document’, the ‘unavailable fonts’ property fails. However, when I use ‘document 1’, it works — no idea why though.