How to get location of comments from word file in c# - c#

I have tried Microsoft.Office.Interop.Word. In that, I have tried Range property. But not getting a result.
Application application = new Application();
Document document = application.Documents.Open("D:\\Files\\Meeting Agenda.doc");
var commentRange = document.Comments[1].Range;

I misunderstood exactly what you wanted.
It is the "Scope" property of the "Comment" object that you need - it is a range & you can obtain the location of the comment from that (Start/End are 0 based offset from start of document). So use :
var commentRange = document.Comments[1].Scope;
The "Range" property is the comment itself (Start/End properties appear to be offsets in a list of comments).
The documentation states the "Reference" property indicates the location of the comment but the Start and End properties are always 1 apart & seem to be the end of the comment & the Text property is always null.

Related

c# Interop: How to restart Selection.Find to beginning of doc?

Simple question that I'm not finding an answer to. My code below is in a loop and finds the first text matching "{{foo}}" in a Word doc. I then want to reset the Find so that it begins its next search at the beginning of the doc again. Currently, it picks up where after the "foo".
Selection sel = application.Selection;
sel.Find.ClearFormatting();
sel.Find.MatchWildcards = true;
sel.Find.Text = #"\{\{?#\}\}";
sel.Find.Forward = true;
sel.Find.Execute();
How do I reset the starting location of Find?
It's always "better" to use Range rather than Selection in Word, whenever possible. You can have only one selection, but code can work with multiple ranges. In addition, the screen is quieter and execution tends to be faster. There are situations where Selection is necessary, but this is not one of them.
To get the Range of the entire document
Word.Range rngDoc = document.Content;
To "find" using the range:
rngDoc.Find.ClearFormatting();
rngDoc.Find.MatchWildcards = true;
rngDoc.Find.Text = #"\{\{?#\}\}";
rngDoc.Find.Forward = true;
rngDoc.Find.Wrap = Word.WdFindWrap.wdFindStop //ensure Word won't entire an infinite loop
rngDoc.Find.Execute();
When "find" is successful, the Range (or Selection) contains only what was found. To "reset" to start again from the beginning of the document (including the whole document):
rngDoc = document.Content;
And (what people ask more frequently) to continue searching from just beyond the "found" term to the end of the document:
object oCollapseEnd = Word.WdCollapseDirection.wdCollapseEnd;
rngDoc.Collapse(ref oCollapseEnd); //go just beyond what was found
rngDoc.End = document.Content.End;
In VBA we'd use:
Selection.HomeKey Word.WdUnits.wdStory
So, in your C# code would that convert to?
Sel.HomeKey(Word.wdUnits.wdStory);
.Find.Execute always resets the range to the found range. Accordingly, you need to either re-set it to the entire document (as per Olivier's comment) or use the C# equivalent of .Wrap = wdFindContinue (VBA) to instruct Word to continue searching from the top after getting to the end of the document.

Why Comment's Reference Text Return null in Interop.Word

I use Microsoft.Office.Interop.Word (in C#) to work with word (word 2013)
I Addes some comments to my doc, and now i want to read comment's reference text (Range.Comments[0].Reference.Text) but it is always null.
Also i look to range start & range end position and it seems range position is at end of the reference and it is always on step position (like 271 to 272)
How can get the correct range of comment reference?
Example of code:
var comments = Doc.Comments;
foreach (var comment in comments)
{
//this variable is always null :(
var commentRefText = comment.Reference.Text;
}
Solved:
with using of comment.Scope.Text the referenced text returned.

Insert Text to Word Range

I use interop.Word to create a Word document programmatically.
In the document I have a particular range which I would like to insert text to.
When I google it I see that the way to do this is :
range.Text=" Whatever...";
but I have no "Text" property for the range object.
Any ideas?
For the orignal question - this is just an intellisense bug, there is such property in the Range class.
For the problem from comments that
Range range=wordApp.ActiveDocument.TablesOfFigures[i].Range;
range.Text=" Whatever...";
replaces the ToF instead of prepending it with text. If you just want to set a header of the table, you can use Caption:
wordApp.ActiveDocument.TablesOfFigures[i].Caption = "Header text";
If however you need some text preceeding the ToF - check out this thread which is discussing similar case, but for the list instead of Table of Figures.
Another way to set caption is to select range you need and call InsertCaption:
wordApp.ActiveDocument.TablesOfFigures[i].Range.Select();
wordApp.Selection.InsertCaption("Whatever");
Note that InsertCaption accepts various args of various types, make sure to try different.
If you want to insert text at a range position, you can use Range.InsertBefore.
Range range=wordApp.ActiveDocument.TablesOfFigures[i].Range;
range.InsertBefore("My Text here. ");

Footer still active after reading it (rtf formular file)

An rtf document is generated by a data base application, with information from this data base. I have created a software (C#, net framework 4.5), to pick up data, then to record it into Excel file.
I have to read the footer of the rtf file, thing I can do.
But, when software access to footer, the document view is the same when footer/header are active (the same effect when you double click on header/footer to access it when you are under Word. This action action adds a carriage return on header (Word add this to enter something), and this \r causes to have additional page.
Here the code :
Sections oSection = cGlobalVar.varWordApp.ActiveDocument.Sections;
HeaderFooter oFooter = oSection[1].Footers[WdHeaderFooterIndex.wdHeaderFooterFirstPage];
Range oRange = oFooter.Range.Tables[1].Range;//<= at this point, footer is accessible, the empty header of original document has a\r character, causing 2nd page to document that I don't want
strBuffer = oRange.Text;//<= information I need
oRange = oSection[1].Range.Tables[1].Range;//<= try to affect something else to oRange
oFooter = null;//<= try to null the object
oSection = null;//<= same as above
//cGlobalVar.varWordDoc.ActiveWindow.View.Type = WdViewType.wdPrintView;//<= try to use this to return to a normal state
I have tried to manipulate Word to find something to get back to my original document (one page), but without any success.
Nulling the object won't clear its content. If you want to clear it, change the text of the range object
oFooter.Range.Text = "";
oSection.Range.Text = "";
Note: These objects have a reference type. This means that the variable points to the actual object, which is somewhere else. If you set the variable to null, you are just loosing the link to the object, but you are not changing the object. See my answer to the SO question Setting a type reference type to null doesn't affect copied type?
UPDATE
I made an experiment in Word, using a VBA macro that reads the table range of the footer as you did above. It does not change the view type of word.
Sub Macro1()
Dim oSection As Sections
Dim oFooter As HeaderFooter
Dim oRange As Range
Dim strBuffer As String
Set oSection = Application.ActiveDocument.Sections
Set oFooter = oSection(1).Footers(WdHeaderFooterIndex.wdHeaderFooterPrimary)
Set oRange = oFooter.Range.Tables(1).Range
strBuffer = oRange.Text
Debug.Print strBuffer
End Sub

Editing the Text of Word Document Range removes paragraph formatting

I'm using Office Interop with MS Word (Microsoft.Office.Interop.Word) and Microsoft.Office.Tools.Word to modify a word document in a Word Add-in. I have a Range which contains specific text I want to edit.
When I update the Text object, the paragraph formatting of the Range is reset, specifically the Alignment and the LeftIndent. I can save the Alignment and LeftIndent in temp variables and reset them, but this is not ideal. Is there a way to stop the ParagraphFormat from being reset and if not, are there any other properties that I may be forgetting that I need to save (I just realized the before and after paragraph spacing also gets reset...).
Microsoft.Office.Interop.Word.Range range = myObject.range;
var oldAlignment = range.ParagraphFormat.Alignment;
var oldLeftIndent = range.ParagraphFormat.LeftIndent;
range.Text = "new text";
range.ParagraphFormat.Alignment = oldAlignment;
range.ParagraphFormat.LeftIndent = oldLeftIndent;
Edit: I just tried saving the ParagraphFormat as a temp variable and then resetting the formatting with that, but the temp variable loses its formatting as well.
oldParagraphFormat = range.ParagraphFormat;
range.Text = "new text";
range.ParagraphFormat = oldParagraphFormat; // oldParagraphFormat's objects are reset
Try creating a duplicate of the Range.ParagraphFormat object prior to changing the text. You can do this via the ParagraphFormat.Duplicate object. This will retain the old ParagraphFormat value. After you change a range's text and its ParagraphFormat resets, you can restore the value from the duplicate.
// Get current value of ParagraphFormat.
Microsoft.Office.Interop.Word.Range range = myObject.range;
var oldParagraphFormat = myObject.range.ParagraphFormat.Duplicate;
// Change the range's text. This will reset ParagraphFormat, so reapply the previous value.
range.Text = "new text";
range.ParagraphFormat = oldParagraphFormat;
Some background as to what's going on: Changing Range.Text essentially resets the Range object because a Range is text + formatting. So changing the text without including any formatting information will cause all previous formatting to be lost. (Much like how changing an HTML tag's innerText property causes that tag to lose all child tags.)
If duplicating the ParagraphFormat doesn't help then you may want to look into setting the Range.FormattedText property instead of Range.Text.

Categories