VSTO Word Add-in - insert Content Control around selected text - c#

I'm trying to add a rich text content control around the user's selected text in a Word document.
I'm new to VSTO and Content Controls so i'm using the MSDN examples as a baseline. The example shows this, which adds the Content Control at the chosen position:
private void AddRichTextControlAtSelection()
{
word.Document currentDocument = Globals.ThisAddIn.Application.ActiveDocument;
currentDocument.Paragraphs[1].Range.InsertParagraphBefore();
currentDocument.Paragraphs[1].Range.Select();
Document extendedDocument = Globals.Factory.GetVstoObject(currentDocument);
richTextControl1 = extendedDocument.Controls.AddRichTextContentControl("richTextControl1");
richTextControl1.PlaceholderText = "Enter your first name";
}
However i want the Content Control to wrap around the user's selected text. Any help, please?

What you found is one possibility. More efficient and "cleaner" (IMO) would be to use the constructor that accepts a RANGE object and pass the Range. If you want the user's selection then
richTextControl1 = extendedDocument.Controls.AddRichTextContentControl(extendedDocument.Parent.Selection.Range, "richTextControl1");
//the Parent of a Document is the Word.Application
//Selection is a dependent of the Word.Application
Otherwise, building on your code sample:
richTextControl1 = extendedDocument.Controls.AddRichTextContentControl(currentDocument.Paragraphs[1].Range, "richTextControl1");
Note that if you don't need to work with VSTO's extensions of the Content Controls you don't need to go through the GlobalFactory steps, you can simply insert the "interop" versions of the Content Controls.

Simple fix in the end: currentDocument.ActiveWindow.Selection.Range.Select();

Related

Retrieve hidden text blocks and replace all content between two of them

I want to use OpenXML to automate Word document creation by taking a given document as a template. This template contains text blocks with a special syntax (namely e.g. «tagname[»...«]tagname») in the form of hidden text (in the font dialog box, the 'Hidden' checkbox in the effects section is activated) so that they don't show up when the document is printed.
Depending on the tagname I want to replace any content which might be already there in the template file between the opening and closing tag with some other content (e.g. in «today[»01/01/2000«]today» the content 01/01/2000 would be substituted with 07/06/2018) preferably preserving the format (e.g. bold, italic or text color).
How can I retrieve the hidden text parts and is there an easy way to replace anything between corresponding tags using C#?
I am not sure what exactly are the text blocks in your template. Instead you can use Content Control from Developer options at the required place, then you can name them from the properties of content control.
today will be name of the Content Control
Once you have all the content control at your template, you can look for specific content control with name and add the new value you want to.
Here is the Snippet to give you an idea.
// Title is name of content control(today), value is what you want to add(1/01/2000)
private static void UpdateControl(WordprocessingDocument document, string title, string value)
{
MainDocumentPart mainPart = document.MainDocumentPart;
var sdtRuns = mainPart.Document.Descendants<SdtRun>()
.Where(run => run.SdtProperties.GetFirstChild<Tag>().Val.Value == title);
foreach (SdtRun sdtRun in sdtRuns)
{
sdtRun.Descendants<Text>().First().Text = value;
}
document.MainDocumentPart.Document.Save();
}

How to Append Clickable Hyperlink to Comment in Word

I have implemented a hyperlink interface; when the user selects text in the document and then clicks a button from my Word Add-in, there is a comment box that is pre-filled with text added to this selection.
However, I want to include a hyperlink that is clickable to bring the user to a Google Doc and this link should be at the end of the comment box. This is what I have tried so far:
Hyperlink link = new Link();
link.Address = (String) oAddress;
link.SubAddress = (String) oSubAddress;
link.TextToDisplay = "more";
selection.Comments.Add(rng2, comment + link)
It looks like you need to create a collection of Hyperlinks from your current document, then add your hyperlink to it.
Below code should highlight everything inside your comment.
// Select the element you want to apply the hyperlink to - you will have to use the Find method
Microsoft.Office.Interop.Word.Range currentRange = myDoc.Comments[0].Range
if (currentRange != null)
{
Microsoft.Office.Interop.Word.Hyperlink hp = (Microsoft.Office.Interop.Word.Hyperlink)
// This line is what you are missing
currentRange.Hyperlinks.Add(currentRange, "http://www.microsoft.com");
}
Credit to https://stackoverflow.com/a/8665770/5209435.
You can use the above as a base before using the Find method to narrow to find the text that you want to hyperlink and just apply it to the selected text. See this question.

Get whole .docx text with office automation, including font and properties (as bold, italic...)

so I am trying to select text from a word document, that contains text in italic, bold, have specific font family.
So I found this code to select all the text :
//doc is the opened document with office automation, this part works
string text = doc.Content.Text;
int end = text.Length;
Microsoft.Office.Interop.Word.Range range = doc.Range(Start: 0, End: end);
range.Select();
Then i use it, to copy the text into a Outlook message :
Microsoft.Office.Interop.Outlook.Application outlook = new Microsoft.Office.Interop.Outlook.Application();
Microsoft.Office.Interop.Outlook.MailItem oMsg = (Microsoft.Office.Interop.Outlook.MailItem)outlook.CreateItem(Microsoft.Office.Interop.Outlook.OlItemType.olMailItem);
oMsg.BodyFormat = Microsoft.Office.Interop.Outlook.OlBodyFormat.olFormatHTML;
oMsg.Body = range.Text ;
And then, when I watch the message html body, I only ot calibri font, and no bold or italic.
What i want to attempt is the same thing as we got when we do it manually :
open word document
select all text then copy (ctrl + c)
Create a mail in outlook
Paste the text in the mail (ctrl + v).
When it is done this way, It is well reproduced (font family, bold etc are well there), but when it is done in the code, it only take the text.
See the differences in this pic (the one bellow is made programmatically, the one bottom, manually):
How can I fix this(if possible)?
Edit : after the answer from Eugene, I add this :
Microsoft.Office.Interop.Outlook.Inspector insp = oMsg.GetInspector;
Microsoft.Office.Interop.Word.Document wordEditorDoc = insp.WordEditor;
But then, I don't get how I put the doc text, into the word Editor Object I created. I can still made a wordEditorDoc = doc; but the result is not better than before.
The Body property contains a raw text. A possible way is to use HTMLBody or Word editor. I think the most convinient way is to use the Word object model to copy the content between documents (the Word existing document and the message body). As you probably know Outlook uses Word as an email editor in Outlook. So, you can use the Word object model for formatting email messages in Outlook.
The WordEditor property of the Inspector class returns an instance of the Document class (from the Word object model) which represents the message body.
You can read more about possible ways in the Chapter 17: Working with Item Bodies article in MSDN.

OpenXML add custom style to Quick Style Gallery

I'm creating a Word Document using OpenXML. During the creation of the document, I need to create some custom styles.
Now I've one problem left: I want to put my custom styles inside the Quick Style Gallery, but I wasn't able to do that. The way that I'm following is explained in the following code:
var info = new LatentStyleExceptionInfo
{
Name = styleid,
PrimaryStyle = true,
UnhideWhenUsed = false,
SemiHidden = false,
UiPriority = 1
};
styleDefinitionsPart.Styles.OfType<LatentStyles>().First().Append(info);
Because I've found a link that tells that is the "PrimaryStyle" attribute responsible for put a Style inside the Quick Gallery.
Another thing: opening the styles.xml file, I've noticed that all the other styles has "1" or "0" for the OnOffValue, whereas the custom styles created with that piece of code has "true" or "false".
How can I solve it?
Thanks.
The XML tag that influences appearance of the style in the quick gallery is <w:qFormat/>. The API property that corresponds is Style.QuickStyle. The Interop name is also QuickStyle (boolean).
Btw, I don't think adding a latent style is going to help you. You'll want to add a real, actual, fully-fledged style if you want it to appear in the UI and be operative.

How can I get text under mouse pointer WebBrowser control?

I'm currently working on WYSIWYG editor using .net WebBrowser control and I need to implement spell checking.
My question is how can I get text under mouse pointer when I right click on the misspelled word to show all spell suggestions?
Tried to wrap every misspelled word in html label with javascript event, but there seems to be the problem in invoking C# code from javascript.
Ok - here are my 2 cents.
Firstly I imagine you have an editable element more than likely a div and you're using this as your WYSIWYG editor. I also guess you have an Ajax function somewhere that you've setup on a certain keystroke to check the spelling of the entire (maybe even some) of the contents of the DIV, and it can send you back a list of the misspelled words.
My idea is - 1. Create a range on the contents of your editable div, then do a search for the word using the TextRange object - here : http://msdn.microsoft.com/en-us/library/ms535872%28VS.85%29.aspx. Use the findText method which Searches for text in the document (range) and positions the start and end points of the range to encompass the search string.
Once you have this you should copy the text value into a variable, then construct a < Span> possibly even set the bottom-border style of the span to have a red underline, or even use an image so that it looks like that regular misspelled squiggly wave. Set the inner contents of this Span to the value of the original misspelled word. Also don't forget to assign an onclick (or right click) to this SPAN, so you can do another lookup on spelling suggestions later. Great, now you have an offline SPAN but its not yet inserted into the document.
Next step: Use the TextRange pasteHTML method to paste the new SPAN into the document, remember the range should already be defined from the find operation, so you shouldn't have to mess around looking for the text again (or selecting it).
Once the span is in the document using pasteHTML, it should be straight forward, just create another div, absolutely position it just under the SPAN so when the user right clicks it - the "context menu comes up" - populated by Ajax.
After that it should be a very easy case of creating another range, and replacing this time the SPAN with just straightforward text.
ALL of this is theory, but hope it helps!
Also you might want to check out - http://www.aspfree.com/c/a/Code-Examples/Searching-Body-Text-with-textRange-Enter-the-Gecko/ - which will help you make the whole solution work in FireFox (not only IE)
I'll add some more two cents in as I'm currently working on something similar.
Okay, so I'm assuming you are a WebBrowser object? If so, my suggestion would be to use a contextual menu strip every time you every time you right click. From there you can fire the context menu Opening event that will grab that specific HTML element for you.
In short you could use a similar code snippet
Point mouseLocation;
private void ToolStripMenuItem_Click(object sender, EventArgs e)
{
HtmlElement elem = webBrowser.Document.GetElementFromPoint(mouseLocation);
//From here you would do what ever it is you need for your element in the browser
}
private void webContextMenuStrip_Opening(object sender, CancelEventArgs e)
{
//This just gets you the specific mouse position for the given element
mouseLocation = webBrowser.PointToClient(MousePosition);
}
Hope this atleast gets you started and best of luck!

Categories

Resources