Reading a document from bottom - c#

I have created a add-in for MS word. I have two buttons. Click on first move me forward by highlighting a range of words. On every second button click I want to go to the previous highlighted word. Can anybody help me in second button functionality. On button click one I have this code working fine.Now how to go the previously highlighted word range on every button2 click??
private void adxRibbonButton1_OnClick(object sender, IRibbonControl control, bool pressed)
{
object missing = System.Type.Missing;
Word.Document document = WordApp.ActiveDocument;
foreach(Word.Range docRange in document.Words)
{
if(docRange.HighlightColorIndex.Equals(Microsoft.Office.Interop.Word.WdColorIndex.wdRed))
{
docRange.HighlightColorIndex = Microsoft.Office.Interop.Word.WdColorIndex.wdBlue;
docRange.Font.ColorIndex = Microsoft.Office.Interop.Word.WdColorIndex.wdWhite;
break;
}
}
}

There's more than one way to approach this:
Use Word's built-in Find to search backwards in the document for the first instance of the changed highlighting.
Set two bookmarks, one for the current position of the code in the question and one for the previous position. The code sample below is for this variation.
string CurrentBkm = "_bkmCurrent";
string LastBkm= "_bkmLast";
if(docRange.HighlightColorIndex.Equals(Microsoft.Office.Interop.Word.WdColorIndex.wdRed))
{
docRange.HighlightColorIndex = Microsoft.Office.Interop.Word.WdColorIndex.wdBlue;
docRange.Font.ColorIndex = Microsoft.Office.Interop.Word.WdColorIndex.wdWhite;
if (document.Bookmarks.Exists(CurrentBkm))
{
document.Bookmarks.Add(LastBkm, document.Bookmarks[CurrentBkm].Range.Duplicate);
}
document.Bookmarks.Add(CurrentBkm, docRange);
break;
The code for button2 simply goes to the bookmark "_bkmLast":
string LastBkm= "_bkmLast";
document.Bookmarks[LastBkm].Range.Select();
Note that the bookmark name starts with an underscore _. This hides the bookmark in the Word UI so that it won't irritate the user in case the application settings show bookmark non-printing characters.
Note, also, that the code in the question could also work with Word's built-in Find functionality to search the formatting. This would almost certainly be more efficient than "walking" each word in the document and testing its highlight formatting. If you were to change your code to use Find the solution I provide with the bookmarks would still work.

Related

Office word editor control for WinForms Applications

I know that this question may be very old and classic but, I am trying to find a free and good word editor control to be embedded into my application for educational purpose, so I googled and tried a lot of editors and methods like using RichTextBox control and fill the RTF value with my word document data and it was displayed into the RichTextBox but without any editing capabilities that exist in the real Word application.
I just need some of the editing capabilities that are exist in the word not all of them, so I decided to build my own word editor but actually I can't find a good way to start that and I don't have that experience, Any Ideas?
What I did until now is very basic and I need to know for example how to add a new method to attach word document to my editor so I need to do something like
wordEditor1.Word = {Path of word document}
and this step should show the document inside my editor with all styles and formats just like opening any word document inside word application.
Also I need to add capability of applying paragraph style or character style on the selected paragraph, so I think that I need to add methods for characters or paragraphs like
selectedParagraph.Style = {name of style in word or name of selected style form styles pane}
Finally I need to allow user to run macros on the opened document and I know that this may be the hardest step, so I just need some ideas to redirect me to the best way of how to do that.
What I did till now is something like
using System.Windows.Forms;
namespace AutoStyle
{
public partial class WordEditor : RichTextBox
{
public WordEditor()
{
InitializeComponent();
}
public object Word
{
get;
set;
}
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
}
}
}
I believe that this question may help others like me who is newbie and has a lack of experience, so I appreciate you comments and efforts.

C# Winforms Help Text Change font

I have a little help pop-up that displays some text when the user presses a "?" label next to a drop-down to explain the different selections.
I did it using the Help.ShowPopup command since that seemed the easiest.
I was hoping there was a way to add different font properties to parts of the text or at least to the whole thing without having to go the direction of a CHM/HTML help-file.
Here is what I am trying to do:
private void helpLbl_Click(object sender, EventArgs e)
{
// for some reason, it ignores the 'parent' parameter
// and lays it out on the screen's coordinates
Point helpLocation = helpLbl.PointToScreen(Point.Empty);
helpLocation.Y += helpLbl.Height; // have it display underneath the control
Help.ShowPopup(this, // hosting form
#"<b>Fixed:</b>
Removes a fixed amount from the sale
<b>Percent Value:</b>
Removes a set percentage of the selected package from the sale
...", helpLocation);
I was hoping since there's the option to use an HTML document to display the help, I could use HTML tags to format what was being displayed, but it doesn't appear so. Any ideas?
Is there a way to do something like displaying a RichTextBox in the help pop-up?
Another possibility is generating a HTML document on-the-fly, but it asks for a "url" if I'm not supplying the text directly and I think that might be a little over-kill for the small amount I'm trying to do here.
You have two options. One is to use a WebBrowser Control. This natively accepts HTML and displays it. The problem with it is its kind of bloated just to use as a simple label.
Your second option is to simply create a RichTextLabel, simply like this:
public class RichTextLabel : RichTextBox
{
public RichTextLabel()
{
BorderStyle = BorderStyle.None;
}
}
Add this to your form and set the Rtf property to your RTF code. You will have to convert your HTML to RTF, which is easy if you got a program such as Microsoft Word, for example.

Restart List Numbering with C# Word Interop

I have a Word 2010 template with some bookmarks and styles that I must use to generate a Word document, after getting the information from some XMLs, and I'm using c# with the Interop (version 8.3). The template was given to me and I can't change it at all, as it follows the documentation rules of the company.
Sometimes, when I use the custom Numbered List style of the template, the numbering screws up, inexplicably starting at 2 instead of 1. Other times, it follows the numbering of the previous list, when I don't always want that to happen.
Fixing those cases would be easy if I could modify the existing styles from the template, or applying custom styles with ContinuePreviousList: false from my program, but the generated Word document must have the styles they force me to use.
If I open the Word document, right click over the list and choose "Restart at 1" option (I don't have Word in English, hope that's the proper translation), it fixes most of the problems that I might have, but I don't know how to use that from Interop. I have recorded macros and then translated to c# to know how Word makes some functions, but the mouse is locked when I start recording macros. Any ideas?
The mouse is locked, but you can use the right click mouse button on the keyboard to get the context menu, and then select Restart at 1 while recording your Macro.
I ended up with this using C# interop:
using System.Runtime.InteropServices;
using MSWord = Microsoft.Office.Interop.Word;
namespace ResetNumberingInWordDoc
{
class Program
{
static void Main()
{
var application = new MSWord.Application();
var document = application.Documents.Open(#"C:\mydocument.docx");
const int listNumber = 1; //The first list on the page is list 1, the second is list 2 etc etc
document.Range().ListFormat.ApplyListTemplateWithLevel(
ListTemplate: document.ListTemplates[listNumber],
ContinuePreviousList: false,
ApplyTo: MSWord.WdListApplyTo.wdListApplyToWholeList,
DefaultListBehavior: MSWord.WdDefaultListBehavior.wdWord10ListBehavior);
document.Save();
document.Close();
application.Quit();
Marshal.ReleaseComObject(application);
}
}
}
I found out the exact way of performing the "Restart at 1" function looking at a recorded macro. Once you have located the paragraph with the numbered list style, you have to select the number that you want to "restart at 1" and apply the "List_Norm" style:
listParagraph.SelectNumber(); //Select numbers from the NumberList paragraph
application.Selection.set_Style(document.Styles["List_Norm"]); //Apply "List_Norm" style
That way, the content of the list will keep the original style(s), but the list will start from 1.
The same code can be applied to restart the Title styles, but applying the "Tit_List" style instead of "List_Norm".

Replacing Content Controls in OpenXML

I need something as a placeholder. I at first looked to Content Control as a solution but I'm having some problems with it.
I then looked into adding CustomXML to the .docx but turned away from that because of the i4i lawsuit.
Then I decided I would just plain change the text of the Content Control through OpenXML SDK 2.0 but even if it's so marked the Content Control doesn't go away. I guess that it doesn't know that the text changed unless it happens inside word.
I could perhaps just remove the CC and place text instead but I'm afraid of problems with format and styles it could bring and also it would kind of defy the purpose of the Content Control.
Then I started wondering if I could define my own placeholders that Word could recognize. Through Building blocks perhaps. It doesn't have to do anything except be easy to find using OpenXML and somehow taggable so I know what to replace it with. I'm not really sure what can be done with Building Blocks but I'm hoping it's do-able.
Not sure what solution would be best for me but what I need is:
a)Something that's easy to place in the template, perhaps predefined Content Control placeholders that you can place where you wan't and style as you like.
b)When the data has been added it removes all placeholders, it won't be modified again. It keeps the style/format defined in the placeholder.
TO RECAP, I need answer to either
How can I edit Content Controls in OpenXML SDK so they will be removed after text is added.
-OR-
Can I define my own custom OpenXML tag for a Word Document that I could then replace?
Perhaps this can help you,
private void DeleteSdtBlockAndKeepContent(MainDocumentPart mainDocumentPart, string sdtBlockTag)
{
List<SdtBlock> sdtList = mainDocumentPart.Document.Descendants<SdtBlock>().ToList();
SdtBlock sdtA = null;
foreach (SdtBlock sdt in sdtList)
{
if (sdt.SdtProperties.GetFirstChild<Tag>().Val.Value == sdtBlockTag)
{
sdtA = sdt;
break;
}
}
OpenXmlElement sdtc = sdtA.GetFirstChild<SdtContentBlock>();
OpenXmlElement parent = sdtA.Parent;
OpenXmlElementList elements = sdtc.ChildElements;
var mySdtc = new SdtContentBlock(sdtc.OuterXml);
foreach (OpenXmlElement elem in elements)
{
string text = parent.FirstChild.InnerText;
parent.Append((OpenXmlElement)elem.Clone());
}
sdtA.Remove();
}
Take a look at using a Field. The mail merge fields are designed for exactly this purpose.
I don't understand from your question if you are only interested in a solution that automatically removes the ContentControl/SDT when you modify it using the OpenXML SDK, or whether you want it to disappear after the content is modifed programmatically or by a user.
If the former, I think you'll have to remove it yourself as Bilel suggested. If the latter, you should look at this property: ContentControl.Temporary ("the ContentControl is automatically deleted when the user types in the control, or when the text in the control is changed programmatically. When the ContentControl is automatically deleted from the document, the text in the control remains in the document.")

How to move caret position to end of current word?

I'm using a webbrowser control. How can I move the insert position for an execCommand to the end of the word, that is currently selected?
Example:
| <- current caret position
Som|eword -> move -> Someword| -> execCommand executes after current word
What I want to do is insert a line without braking the word. What happens now is:
Somew|ord -> line
Somew
ord
What should happen is:
Somew|ord -> line
Someword
This is so hacky that I'm almost embarrassed to post it, but ... you can accomplish "Inserting a line without breaking the word" "using a webbrowser control" by doing something like
webBrowser1.Url =
new Uri("javascript:" +
"var tr=document.selection.createRange();" +
"tr.expand('word');" +
"tr.collapse(false);" +
// "tr.select();" // Necessary to actually move the caret
"tr.pasteHTML('<hr>');");
After the webbrowser has loaded the document that you want to manipulate, and the user has selected the text that they'd like to insert a line after. If you really need the caret moved as well, you'd need a tr.select() after the tr.collapse().
It doesn't use the execCommand though, so it may not be suitable for your purposes. Maybe someone else can figure out a way to make this a little cleaner...

Categories