How to test the existence of a Word Custom Document Property (CDP) in a field code? - ms-word

The following fieldcode in Word displays the contents of the custom document property "myproperty" when it exists; otherwise it does nothing
{IF {DOCPROPERTY "myproperty"} <> "Error! Unknown document property name." {DOCPROPERTY "myproperty"}}
The test for existence is based upon the error message that Word returns if the property does not exist. Trouble is: this error message can be localized (e.g. in French etc).
Do you know how to test for existence of a custom document property in a locale independent manner? This would be equivalent to something like:
{IF {EXIST-DOCPROPERTY "myproperty"}{DOCPROPERTY "myproperty"}}

IMHO you've stumbled over the few issues in Word which are language-content-related and for which no correct solution exists.
Another example is the {STYLEREF} field, which needs a reference to the style you want to refer to. While you have in VAB/VSTO the possibility to refer to the built-in styles through a constant, e.g. wdStyleHeading1, to be language-independent, with the field you must add the style name as "Heading 1" in an English Word. Open the document in a German Word, and you'll get a "style name not defined" error, and vice versa opening a German "STYLEREF "Überschrift 1"} in an English Word.
You haven't said anything about the whole situation in which you want to address your issue. In my document template sets, I'm normally in control of the documents, e.g. there's a global add-in running through which I can control documents. Additionally, templates issued by me do have the custom document properties already defined, so that errors of your kind can not happen. However, even if they're not defined, you may create them while opening a document.

Related

DOCVARIABLE in ms word Field has disappeared, and yet still appears to be functioning. How can I get it back?

First off, sorry if this is really basic, but I've been working with fields in a word document for the past few days and I'm finding them quite counterintuitive. I have a document with over 100 images, and I am sourceing those images using the INCLUDEPICTURE field. Inside that field there is a DOCVARIABLEwhich contains the path to the image. I set this up to display all 1000 images. I then copied this word file and made a new one because I had a second set of images to display. SoI copied and pasted a section of the image name in the field codes and replaced it with a new name, e.g. all "image_a" instances were replaced with "image_b" so instead of seeing "image_a_1.png" and "image_a_2-png", the field codes now show "image_b_1.png" and "image_b_2.png" etc. and this has successfully retrieved the correct images so the document looks good.
However after doing this I have noticed that the codes in the fields has now changed. beforehand at the start the appeared like this:
{ INCLUDEPICTURE "{ DOCVARIABLE "var_doc_path" }folderwithpics\\image_a_1.pgn" \d }
now however after the copy and paste this is what appears:
{ INCLUDEPICTURE "folderwithpics\\image_b_1.pgn" \* MERGEFORMAT \d }
The doc variable is no longer displayed. What's weird that is that the correct image is still sourced and displayed in the word document, so it seems that the docvarible which is essential for the field to reference the correct path, is still active.
There is a problem though, which is that in a new word document, I need to use INCLUDEIMAGE to source all of the 1000 images again into this new document, and they aren't getting displayed. I need to go back and manually enter in the full path for each of the images in order for the new word document to access those image.
I think this must have something to do with the fact that the correct path is no longer displayed. Can anyone help me? I think I need to get the document to display { DOCVARIABLE "var_doc_path" } in the INCLUDEPICTURE field again.
As a side note if anyone has a good guide they can reccommend on working with fields I think that would be a great help. Thanks!
Unless you copied the document via Windows or via SaveAs, rather than simply copying & pasting content from one document to another, the new document will not contain the Document Variable. By using the \d switch, Word is referencing a copy of the image stored in the document metadata rather than the one in the filepath it can no longer access via the DOCVARIABLE field.
FWIW, the \* MERGEFORMAT switch does nothing useful in an INCLUDEPICTURE field.

Reaching the referenced text from a Word interop field object

I am using Word interop to build a Word plugin. In this plugin I have a case where I want to examine all
Field objects in the document and when that field is a cross-reference to another place in the same document I need to be able to capture the text in the paragraph that the field is referring to.
I was able to get the name of the field object but there were no bookmarks defined in the Document although in Word I could click on the field to get to the other location.
Example field
Example field as code
referenced text I need to get
No Bookmark objects are defined
I tried to simulate the user clicking on the field by invoking DoClick() on it and then I accessed V_V_Scalar_Document_Generic.Application.Selection.Range.Text
but it gave nothing. I also tried the GoTo approach below but still didn't reach the referenced text.
System.Collections.Generic.List<string> L_V_List_String_Fields = new System.Collections.Generic.List<string>();
foreach (Field L_V_Scalar_Field_Item in V_V_Scalar_Document_Generic.Range.Fields)
{
try
{
if (L_V_Scalar_Field_Item.Type == WdFieldType.wdFieldRef)
// L_V_Scalar_Field_Item.Data --> gives COM exception
// L_V_Scalar_Field_Item.Code.ID --> blanks
// L_V_Scalar_Field_Item.DoClick() 'will not help because fields are not always hyperlinks
// L_V_Scalar_Field_Item.Result.Text --> gives the text of the field itself
// all variations I tried for the target parameter in the line below (last param) are not working
// V_V_Scalar_Document_Generic.[GoTo](Microsoft.Office.Interop.Word.WdGoToItem.wdGoToField, System.Type.Missing, System.Type.Missing, "_Ref28680085")
// Dim L_V_Scalar_String_Source as string = V_V_Scalar_Document_Generic.Application.Selection.Range.Text
L_V_List_String_Fields.Add($"CodeText:{L_V_Scalar_Field_Item.Code.Text} |FieldType:{L_V_Scalar_Field_Item.Type} |FieldKind:{L_V_Scalar_Field_Item.Kind} |SourceText:{"source text ??"}");
}
catch (Exception L_V_Scalar_Exception_Generic)
{
}
}
The bookmarks are not listed because Word has a convention that bookmarks with names starting with an underscore ("_") are "hidden". In the Insert->Links->Bookmark dialog box, you can see them if you check the "Hidden Bookmarks" box, but in the Find and Replace box, you have to enter the name manually.
Even when Bookmarks are hidden, you can reference them. So for example you should be able to do something like this (this is VBA syntax):
Dim TargetText As String
TargetText = ActiveDocument.Bookmarks("_Ref28680085").Range.Text
to get the text "covered" by the bookmark. In theory, you could use Goto, by using wdGotoBookmark instead of wdGotoField, except that I think it will only have a chance of working with the Selection object, not a Range object.
Depending on what type of cross-reference the user inserts, Word "covers" different parts of the referenced material. So you may need to construct the Range you really need, e.g. using the Bookmark's Range.Start to tell you which paragraph the reference is pointing at.

How to hyperlink a document property field in word 2016?

Document properties are fields that can be used throughout microsoft word: https://support.office.com/en-us/article/view-or-change-the-properties-for-an-office-file-21d604c2-481e-4379-8e54-1dd4622c6b75
Typically I use these fields throughout my document so changing the document property will change all instances of that field throughout my document. This is great, however, when one of the fields is "Company Email" I not only want the text to change to employee#company.com but I would like to have that field hyperlinked to employee#company.com so that the user can click it in order to send an email.
Edit: (Info from comments)
I have tried to insert a hyperlink, hit alt-f and embed a docproperty via the instructions from a similar thread: stackoverflow.com/questions/17428891/…. But could not get that to work properly.
The following works for me, in a quick test (you'll need to substitute the name of the Document Property you're using):
{ HYPERLINK "mailto:{ DocProperty Email }" }
When I Ctrl+Click this it creates a new Email to the address.
For readers unfamiliar with inserting field codes: The wavy bracket pairs must be inserted using Ctrl+F9. Alt+F9 after to switch from field code to field display.

manipulating Microsoft Word DOCX files that have links and track changes using Python

I have been using the excellent python-docx package to read, modify, and write Microsoft Word files. The package supports extracting the text from each paragraph. It also allows accessing a paragraph a "run" at a time, where the run is a set of characters that have the same font information. Unfortunately, when you access a paragraph by runs, you lose the links, because the package does not support links. The package also does not support accessing change tracking information.
My problem is that I need to access change tracking information. Or, more specifically, I need to copy paragraphs that have change tracking indicated from one document to another.
I've tried doing this at the XML level. For example, this code snippet appends the contents of file1.docx to file2.docx:
from docx import Document
doc1 = Document("file1.docx")
doc2 = Document("file2.docx")
doc2.element.body.append(doc1.element.body)
doc2.save("file2-appended.docx")
When I try to open the file on my Mac for complicated files, I get this error:
But if I click OK, the contents are there. The manipulation also works without problem for very simple files.
What am I missing?
The .element attribute is really an "internal" interface and should be named ._element. In most other places I have named it that. What you're getting there is the root element of the document part. You can see what it is by calling:
print(doc2.element.xml)
That element has one and only one w:body element below it, which is what you get when with doc2.element.body (.xml will work on that too, btw, if you want to inspect that element).
What your code is doing is appending one body element at the end of another w:body element and thereby forming invalid XML. The WordprocessingML vocabulary is quite strict about what element can follow another and how many and so forth. The only surprise for me is that it actually sometimes works for you, I take it :)
If you want to manipulate the XML directly, which is what the ._element attribute is there for, you need to do it carefully, in view of the (complex) WordprocessingML XML Schema.
Unlike when you stick to the published API, there's no safety net once ._element (or .element) appears in your code.
Inside the body XML can be relationships to external document parts, like images and hyperlinks. These will only be valid within the document in which they appear. This might explain why some files can be repaired.

MS Word 2007 - How to set up placeholder text to mimic text but not formatting

I'm probably biting off more than I can chew with this particular problem, but I'll try to be as specific as possible in case it's within my scope. Disclaimer: I'm not terribly experienced with MS Word, beyond simple data entry/some formatting, and I have absolutely zero experience working with macros or VBasic. Unfortunately, I'm afraid the solution to my problem will come in the form of one of those last two.
THE GOAL:
What I want to do is to have placeholder text throughout my template document that will change content but not formatting when the first instance of it is changed. Basically, I'm writing a template for support manuals for a software suite. Each app has certain similar features like the menu bar, data entry screen, diagnostic log screen, transaction history, etc., so I am pre-writing those sections and using placeholders when I need to insert certain app specific properties.
I started off using the Insert->Quick Parts->Document Property->Subject tool which I used as a placeholder for the app name. I set the Property to [Subject] and then used Insert->Quick Parts->Field->Subject throughout the document, wherever I needed to include the app name. This worked fine in this case because the app name will always be capitalized. I simply change the text in the first [Subject] (which is content controlled) and update the fields throughout the document, and they all match nicely, easy-peasy, work done, go home and drink beer, right?
Not quite.
Our software handles part tracking via scanners and SQL Server, so while the interface and menu in the apps remains largely unchanged, the parts they track change from app to app. Because of this, I need to change the part name when I reference it within the text of the manuals; for example, if I'm working in ToiletPap.app and our TP is tracked by the roll, I need every mention of [Component] to be changed to roll. If I'm working in LightBulbs.app, I need [Component] to say bulb.
My first efforts went toward creating a custom doc property called Component using the Advanced tab under the Document Properties dropmenu. I then created a plaintext content control around my first [Component] titled Component and made my next [Component] a field with modified code: {COMPONENT * MERGEFORMAT}. This comes from copying what I can find when [Subject] works. This didn't work at all; updating the text in the first CC doesn't change the Content doc prop, and my fields return "!Undefined Bookmark, COMPONENT".
I got close to what I need by using the [Comments] doc property, set initially to [Component]. I used it just like [Subject], but (this is when I realized that capitalization was going to be an issue) when I mention my [component] in-text, as often as not, I need to to be lowercase instead of upper.
I've looked on MS's forums and a few others as well as here on SO, and I can't find anyone who's trying to do the same thing, much less an answer to how. Please keep in mind when answering, it would be a great help to me if you would include step-by-step instructions on how to enter/implement the code you provide because, as I mentioned, I have no idea how to go about editing macros/VBasic for MS Word.
To restate and summarize my overall question: How can I use a placeholder that displays the text "[Component]" so that, when I change the first instance of [Component] to something else, say "hopper", every subsequent instance of [Component] is updated to hopper but maintains its current capitalization and formatting scheme?
Apologies for the length of the request, but I wanted to make sure I explained the situation as accurately as possible. Thanks in advance for your consideration and responses.
I managed to solve this one after a couple extra hours of tinkering. I didn't need macros or VBasic, either.
On the first instance of [component] I created a plain-text content control to act as a container (not a necessity, but it makes it look nicer. Will likely cause a problem eventually, but for now, it's working as intended) and bookmarked it. Then, for all other instances of [container] I selected each and used Insert->Quick Parts->Field->Ref with the following field code:
REF Text1 \*Lower
Where "Text1" is my bookmark and "*Lower" indicates all lower case. The *Lower can be replaced with *Upper or *FirstCap to indicate all upper case or capitalize the first letter respectively. Now, each field reflects the text of the first with the capitalization appropriate to each field's location within the document. Just like using the doc prop with [Subject], ^a -> f9 is needed to update all fields within the document.