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.
Related
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.
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.
Is there a way to take a value from a field on a form and use it as a reference to a different field in the same form, and not just literally? I want to be able to manually enter something like [txtFlavor] in one field and have it show the actual flavor, the value of the field named "txtFlavor" in another field, and not just the string "[txtFlavor]". I'm basically trying to store some vba references (terminology?) in a table so I can bring up a string of text with references to values on the form.
I have been asked to create a system that will store letter templates in Access 2010 and allow users to choose a record with personal information and insert that info into a template letter, preferably displaying it on a form immediately in plain text. I already proposed using reports to do this but that was unacceptable to the end users. They really just want a form that combines
a) contact records, one at a time
with
b) letter templates, one at a time
I've been trying to store the template info with it's form references in a table, but I have yet to be able to make references pull data from another text field on the form.
Is it possible and/or sensible to try to store something like the following in a table, or to enter it into a field on a form?
[txtFlavor] & " is dull but popular."
and then have it show up elsewhere in the form as
Vanilla is dull but popular.
I sure feel dumb and am sure I've missed something obvious. Everything I do is just repeated literally and not interpreted as a reference.
You could get your users to create their templates using 'tags' as placeholders for the database information, in a similar way to how you would design a merge document in Word. So in your example above, the template document would look like:
{Flavor} is dull but popular.
When it comes time to create the merged result you would need to use the Replace function to change these tags to actual data values. So if you had a read-only text box on your form, the control source could be:
=Replace([txtTemplate], "{Flavor}", [Flavor])
I assume you would have lots of potential tags, so using this approach you would need to nest the Replace functions. I have split my nesting across multiple lines to make it a bit more readable:
=Replace(
Replace(
Replace([txtTemplate], "{EmpName}", [EmpName]),
"{EmpAddress}", [EmpAddress]),
"{EmpPhone}", [EmpPhone])
If you had many more database fields/tags this would start to become very unwieldy so I would recommend using some VBA to make life easier, maybe something along the lines of:
Dim rsSource As Recordset
Dim strMerge As String
Dim intField As Integer
'Assuming your form has a field called EmpNo (numeric data) that you can use to pull data...
Set rsSource = CurrentDb.OpenRecordset ("Select EmpName, EmpAddress, EmpPhone From Employees Where EmpNo = " & Me.EmpNo)
strMerge = txtTemplate
For intField = 0 to rsSource.Fields.Count - 1
strMerge = Replace(strMerge, "{" & rsSource(intField).Name & "}", rsSource(intField))
Next intField
txtMerge = strMerge
rsSource.Close
Set rsSource = Nothing
You could put this code in the AfterUpdate event of your txtTemplate text box and it would update the contents of the txtMerge text box. You either need your tag names to match your database columns, or else you could alias the columns in the Select statement so they match the tag names.
I've used worksheet URL actions in tableau before and they are Great! But I have a case where to construct a valid link- I need the field twice.
something like....
"http://wwwin-esstools-prd.cisco.com/pmt/emailfilters/EmailFilter.json/?&id=FIELD&queryObj={"conjunction":"and","expressions":[{"op":"equals","attr":"id","value":FIELD}],"preFilterQuery":"","name":"Advanced Filter"}"
where FIELD is the field name I would like to use to properly construct the url. I have tried using both the select and menu options-
both seem to be ignored by tableau.
FIELD needs to be surrounded by angle brackets. You can use the Insert menu on the URL action dialog panel to insert field names into your URL if you prefer, and thus avoid spelling errors. Or simply type the field name and brackets where you want them.
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.