How I can change this feature so I select the range of characters in a word document between the characters "E" and "F", if I have; xasdasdEcdscasdcFvfvsdfv is underlined to me the range -> cdscasdc
private void Rango()
{
Word.Range rng;
Word.Document document = this.Application.ActiveDocument;
object startLocation = "E";
object endLocation = "F";
// Supply a Start and End value for the Range.
rng = document.Range(ref startLocation, ref endLocation);
// Select the Range.
rng.Select();
}
This function will not let me pass by reference two objects of string type.......
Thanks
You need to pass the position in the document you want the range to cover, see:
How to: Define and Select Ranges in Documents
I have added some example code below:
var word = new Microsoft.Office.Interop.Word.Application();
string document = null;
using (OpenFileDialog dia = new OpenFileDialog())
{
dia.Filter = "MS Word (*.docx)|*.docx";
if (dia.ShowDialog() == DialogResult.OK)
{
document = dia.FileName;
}
}
if (document != null)
{
Document doc = word.Documents.Open(document, ReadOnly: false, Visible: true);
doc.Activate();
string text = doc.Content.Text;
int start = text.IndexOf('E') + 1;
int end = text.IndexOf('F');
if (start >= 0 && end >= 0 && end > start)
{
Range range = doc.Range(Start: start, End: end);
range.Select();
}
}
Do not forget to close the document and Word etc.
Related
I have a code in C# ,for deleting Blank Pages (even those pages that may have spaces on it) And it works correctly for those cases,,, but ,My weird problem is that if the page has an image it deletes it,While if the page has a combination of image and text ,it do not delete it.
Can someone explain me ,where might be my problem?
Below is my code
String wordPath = #Path;
Microsoft.Office.Interop.Word.Application wordapp = null;
Microsoft.Office.Interop.Word.Document doc = null;
Microsoft.Office.Interop.Word.Paragraphs paragraphs = null;
try
{
// Start Word APllication and set it be invisible
wordapp = new Microsoft.Office.Interop.Word.Application();
wordapp.Visible = false;
doc = wordapp.Documents.Open(wordPath);
paragraphs = doc.Paragraphs;
object miss = System.Reflection.Missing.Value;
WdStatistic stat1 = WdStatistic.wdStatisticPages;
int numberOfPages = doc.ComputeStatistics(stat1, ref miss);
var document1 = wordapp.ActiveDocument;
for (int i = 1; i < numberOfPages; i++)
{
Console.WriteLine(i);
document1.ActiveWindow.Selection.GoTo(WdGoToItem.wdGoToPage, WdGoToDirection.wdGoToAbsolute, i, miss);
Console.WriteLine("-> TEXT : " + document1.ActiveWindow.Selection.GoTo(WdGoToItem.wdGoToBookmark, miss, miss, "\\page").Text);
Console.WriteLine("-> longitud : " + document1.ActiveWindow.Selection.Text.Trim().Length);
if (document1.ActiveWindow.Selection.Text.Trim().Length <= 1)
{
document1.ActiveWindow.Selection.Delete();
}
if (document1.ActiveWindow.Selection.Text.Trim().Length <= 1 || document1.ActiveWindow.Selection.Text.Trim() == "\f")
{
foreach (Paragraph paragraph in document1.ActiveWindow.Selection.Paragraphs)
{
Console.WriteLine(" PARAGRAPH!" + paragraph.Range.Text + "!");
if (paragraph.Range.Text.Trim() == string.Empty || document1.ActiveWindow.Selection.Text.Trim() == "\f")
{
paragraph.Range.Select();
wordapp.Selection.Delete();
}
}
}
}
// Save the document and close document
doc.Save();
((Microsoft.Office.Interop.Word._Document)doc).Close();
// Quit the word application
((Microsoft.Office.Interop.Word._Application)wordapp).Quit();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
// Clean up the unmanaged Word COM resources by explicitly
// call Marshal.FinalReleaseComObject on all accessor objects
if (paragraphs != null)
{
Marshal.FinalReleaseComObject(paragraphs);
paragraphs = null;
}
if (doc != null)
{
Marshal.FinalReleaseComObject(doc);
doc = null;
}
if (wordapp != null)
{
Marshal.FinalReleaseComObject(wordapp);
wordapp = null;
}
}
// end
You're just looking for Text:
document1.ActiveWindow.Selection.Text.Trim().Length <= 1
I think you also need to look for 'InlineShapes' which would include things like images and drawings:
document1.ActiveWindow.Selection.InlineShapes.Count == 0
So probably something like
if (document1.ActiveWindow.Selection.Text.Trim().Length <= 1
&& document1.ActiveWindow.Selection.InlineShapes.Count == 0)
{
document1.ActiveWindow.Selection.Delete();
}
... although I don't really understand what your second 'if' block is for, you probably need something similar there too
The answer is quite simple.
If you have 1 picture without text and the picture is an inlineShape (picture that moves with text), then text.lenght = 1 so the <= 1 check will succeeed and the picture is deleted
If you don't want it to be deleted then simply check on (VB.NET):
Selection.Text.trim.length = 0 AndAlso Selection.range.shaperange.count = 0
Notes:
shaperange holds the pictures that do not move with text
note that selection.shaperange.count returns 0 even if a shape is selected
selection.range.shaperange.count does return a non-0 when a shape is selected
to detect empty tables extra logic needs to be added
The debugger is your friend whenever the results are weird. Inspect the Selection object diligently.
I am reading a word document in c#,where after reading it, I need to enter a comment for selected paragraphs.
So I need to find the index of paragraph through c#, is it possible??
foreach (Microsoft.Office.Interop.Word.Paragraph aPar in oDoc.Paragraphs) // looping through all the paragh in document
{
Microsoft.Office.Interop.Word.Range parRng = aPar.Range;
string sText = parRng.Text;
if (sText == para[1].ToString()) // found the paragraph and i need the index of this paragraph
{
oDoc.Comments.Add(oDoc.Paragraphs[0].Range, ref comments); // to add the comment in document
}
}
If I found the index of that paragraph, Can I insert the comment on that paragraph? Is it possible?
Or is there any other way to do this?
Try this
foreach (Microsoft.Office.Interop.Word.Paragraph aPar in oDoc.Paragraphs) // loads all words in document
{
Microsoft.Office.Interop.Word.Range parRng = aPar.Range;
string sText = parRng.Text.Replace("\r","");
if (sText == txtBoxParagraph.Text ) // found the paragraph and i need the index of this paragraph
{
oDoc.Comments.Add(parRng, txtBoxComments.Text); // to add the comment in document
}
}
It works for me.
int i = 1;
foreach (Word.Paragraph aPar in oDoc.Paragraphs)
{
string sText = aPar.Range.Text;
if (sText != "\r")
{
if (sText == para[1].ToString() + "\r")
{
Word.Range range = oDoc.Paragraphs[i + 1].Range;
if (!range.Text.Contains("GUID:"))
{
int pEnd = aPar.Range.End;
string guid = "GUID:" + para[0].Replace("{", "").Replace("}", "");
int length = guid.Length;
aPar.Range.InsertAfter(guid);
Word.Range parRng = oDoc.Range(pEnd, pEnd + length);
parRng.Font.Hidden = 1;
parRng.InsertParagraphAfter();
}
}
}
i++;
}
I have two methods which search through a text document in my WPF app. When search for a word in the first search it works fine, but when I add a word to it, it will crash and come up with a null exception. Can someone please help?
Crashes on:
TextRange result = new TextRange(start, start.GetPositionAtOffset(searchText.Length));
Stacktrace:
{"Value cannot be null.\r\nParameter name: position2"}
Example:
if the text said this.
And I search for "if the", then I search for "if the text said" it would crash.
private void btnSearch_Click(object sender, RoutedEventArgs e)
{
string searchText = searchBox.Text.Trim();
searchText = searchText.ToLower();
if (String.IsNullOrWhiteSpace(searchText))
{
MessageBox.Show("Please enter a search term!");
searchBox.Clear();
searchBox.Focus();
newSearch = true;
return;
}
if (!String.IsNullOrEmpty(lastSearch))
{
if (lastSearch != searchText)
newSearch = true;
}
TextRange searchRange;
RichTextBox _body = ((DockPanel)((TabItem)tabControl.Items[tabControl.SelectedIndex]).Content).Children[1] as RichTextBox;
_body.Focus();
if (newSearch)
{
searchRange = new TextRange(_body.Document.ContentStart, _body.Document.ContentEnd);
lastSearch = searchText;
TextPointer position2 = _body.Document.ContentEnd;
}
else
{
backupSearchRange = new TextRange(_body.CaretPosition.GetLineStartPosition(1) == null ?
_body.CaretPosition.GetLineStartPosition(0) : _body.CaretPosition.GetLineStartPosition(1), _body.Document.ContentEnd);
TextPointer position1 = _body.Selection.Start.GetPositionAtOffset(1);
TextPointer position2 = _body.Document.ContentEnd;
searchRange = new TextRange(position1, position2);
}
TextRange foundRange = newSearchFunction(searchRange, searchText);
if (foundRange == null)
{
if (newSearch)
{
MessageBox.Show("\'" + searchBox.Text.Trim() + "\' not found!");
newSearch = true;
lastOffset = -1;
}
else
{
MessageBox.Show("No more results!");
newSearch = true;
lastOffset = -1;
}
}
else
{
_body.Selection.Select(foundRange.Start, foundRange.End);
_body.SelectionBrush = selectionHighlighter;
newSearch = false;
}
}
private TextRange newSearchFunction(TextRange searchRange, string searchText)
{
int offset = searchRange.Text.ToLower().IndexOf(searchText);
offset = searchRange.Text.ToLower().IndexOf(searchText);
if (offset < 0)
return null;
if (lastOffset == offset)
{
//searchRange = backupSearchRange;
offset = searchRange.Text.ToLower().IndexOf(searchText);
if (offset < 0)
return null;
for (TextPointer start = searchRange.Start.GetPositionAtOffset(offset); start != searchRange.End; start = start.GetPositionAtOffset(1))
{
TextRange result = new TextRange(start, start.GetPositionAtOffset(searchText.Length));
if (result.Text.ToLower() == searchText)
{
lastOffset = offset;
return result;
}
}
}
for (TextPointer start = searchRange.Start.GetPositionAtOffset(offset); start != searchRange.End; start = start.GetPositionAtOffset(1))
{
TextRange result = new TextRange(start, start.GetPositionAtOffset(searchText.Length));
if (result.Text.ToLower() == searchText)
{
lastOffset = offset;
return result;
}
}
return null;
}
Method GetPositionAtOffset can return null if it cannot find this position. See TextPointer.GetPositionAtOffset. In your case you see it because you do the search until you don't reach end of your search range, but in the case when for example your search range contains 100 symbols and your search text has 10 symbols after you reach pointer at index 91 - you will call GetPositionAtOffset with offset 10 - and this will be 101 symbol, which gives you null in this case.
You can do simple check in your for loops, something like:
for (
TextPointer start = searchRange.Start.GetPositionAtOffset(offset);
start != searchRange.End;
start = start.GetPositionAtOffset(1))
{
var end = start.GetPositionAtOffset(searchText.Length);
if (end == null)
{
break;
}
TextRange result = new TextRange(start, end);
if (result.Text.ToLower() == searchText)
{
lastOffset = offset;
return result;
}
}
You have one more similar for loop, just add this special check in it too.
It looks like you are doing search, so just want to give you two recommendations:
Use string.Compare method instead ToLower. See String.Compare Method (String, String, Boolean, CultureInfo). In your case it should be string.Compare(text1, text2, ignoreCase: true, culture: CultureInfo.CurrentCulture). In this case your application will support all languages.
If you really want to use ToLower and do search in this way - consider to change it to ToUpper, because some languages can be tricky when you do ToLower. Check this article What's Wrong With Turkey?. When you do ToLower(I) with Turkish locale you will get dotless i, which is different from i. Wikipedia about: Dotted and dotless I.
I am working on Word AddIns and using Interop library of Word and i want to assign a name(string) to Shape but word.shape.name throwing Exception:
"System.UnauthorizedAccessException: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))".
My code is:
bool blnRetVal = false;
string strModel = ndModel.Name;
int lngModel = 0;
int lngNextModel = 0;
int lngStart;
int lngEnd;
Alias.Document objTemp;
Microsoft.Office.Interop.Word.Range objRange;
Shape objShape;
Object[] astr;
int n;
bool bLastModel;
/*'--------------------------------------------------------------------------------------------------
' 1. Find model's model marker and the next marker (if any)
'--------------------------------------------------------------------------------------------------*/
astr = dicMarkers.Keys();
for (n = astr.GetLowerBound(0); n <= astr.GetUpperBound(0); n++)
{
if (string.Compare(astr[n].ToString(), strModel, true) == 0)
{
lngModel = (int)dicMarkers.get_Item(astr[n]); //PNDC //dicMarkers.Item(astr(n))
if (n < astr.GetUpperBound(0))
{
if (string.Compare(astr[n + 1].ToString(), "#end", true) == 0)
{
lngNextModel = 0;
bLastModel = true;
}
else
{
lngNextModel = (int)dicMarkers.get_Item(astr[n + 1]);
bLastModel = false;
}
}
else
{
lngNextModel = 0;
}
break;
}
}
/*'--------------------------------------------------------------------------------------------------
' 2. Copy model from original document to new document
'--------------------------------------------------------------------------------------------------*/
if (lngModel > 0)
{
lngStart = objSourceDocument.Sections[lngModel].Range.Start;
if (lngNextModel == 0)
{
var key = "#end";
var value = dicMarkers.get_Item(key);
lngEnd = value;
}
else
lngEnd = objSourceDocument.Sections[lngNextModel].Range.Start; //objSourceDocument.Sections.Last.Index;
//--------------------------------------------------------------------------------------------------
//copy original
objSourceDocument.ActiveWindow.Selection.SetRange(lngStart, lngEnd);
objSourceDocument.ActiveWindow.Selection.Copy();
bool bInsertSection = false;
//paste (append) copied model to the document
if (objTargetDocument.Sections.First.Index == objTargetDocument.Sections.Last.Index)
{
//Target document only has 1 (default) section
bInsertSection = true;
}
else
{
if (objTargetDocument.Sections.Last.PageSetup.SectionStart == WdSectionStart.wdSectionNewPage)
{
//Last section is a nextpage section
if ((objTargetDocument.Sections.Last.Range.End - (objTargetDocument.Sections.Last.Range.Start) <= 1))
//Empty section
bInsertSection = false;
else
bInsertSection = true;
}
else
{
//Last section isn't a nextpage
bInsertSection = true;
}
}
objTargetDocument.ActiveWindow.Selection.Start = objTargetDocument.Range().End;
if (bInsertSection)
{
objTargetDocument.ActiveWindow.Selection.InsertBreak(WdBreakType.wdSectionBreakNextPage);
objTargetDocument.ActiveWindow.Selection.Start = objTargetDocument.Range().End;
}
objTargetDocument.ActiveWindow.Selection.Collapse();
objRange = objTargetDocument.ActiveWindow.Selection.Range.Duplicate; //remember range for model marker anchor
objTargetDocument.ActiveWindow.Selection.Paste();
//place model marker (so that we can find our model again)
objShape = objTargetDocument.Shapes.AddTextbox(Microsoft.Office.Core.MsoTextOrientation.msoTextOrientationUpward, 0, 0, 0, 0, objRange);
objShape.Name = m_strModelMarker + strModel;
objShape.Visible = Microsoft.Office.Core.MsoTriState.msoFalse;
UpdateFields(ref objTargetDocument, ref ndModel);
blnRetVal = true;
}
else
new Modules.Globals().MsgBoxEx("Kan het bestaande model '" + strModel + "' niet kopieren.", MessageBoxButtons.OK);
return blnRetVal;
}
I am unable to duplicate your error, however I am able to get your code to run with a few changes. Let me know if I've misinterpreted.
Note the Missing variable used instead of objRange. I've also removed variables that were not applicable.
using Word = Microsoft.Office.Interop.Word;
using Alias = Microsoft.Office.Interop.Word;
public Test()
{
var doc = new Alias.Document();
var doc2 = new Alias.Document();
var t = this.CloneModel(ref doc, ref doc2);
}
private bool CloneModel(ref Alias.Document objTargetDocument, ref Alias.Document objSourceDocument)
{
var missing = Type.Missing;
Word.Shape objShape;
objShape = objTargetDocument.Shapes.AddTextbox(
Microsoft.Office.Core.MsoTextOrientation.msoTextOrientationUpward, 0, 0, 0, 0, ref missing); <== note the missing here instead of objRange
objShape.Name = "Carma DocSys~Brief"; // no longer throwing exceptions (hard coded string)
objShape.Visible = Microsoft.Office.Core.MsoTriState.msoFalse;
return true;
}
If this is NOT the problem, then I would suggest that you are having trouble with permissions to the file as the error message suggests.
I am searching XML files to see if there are contents which match the words inserted in these textboxes txtComKeyword1, txtComKeyword2, txtComKeyword3 and/or txtComKeyword4. The function below is working, but may I know how can I highlight the keywords that user entered in the four textboxes that match that appear in my richComResults richtextbox?
For example, my user will fill in those four textboxes ie. txtComKeyword1, txtComKeyword2, txtComKeyword3 and txtComKeyword4. Then, my code will parse the XML file to see if the nodes contain these four keywords, if yes, the nodes' data will be output on my richComResults, I wanna highlight those four keywords (eg txtComKeyword1=hello, txtComKeyword2=bye, txtComKeyword3=morning, txtComKeyword4=night). These 4 words, if found and appear in richComResults, will be highlighted with color.
I have no clue after searching for a while, my case is much different from other questions. I am a newbie in programming, your help would be much appreciated. Thank you!
My Code:
private void searchComByKeywords()
{
// Process the list of files found in the directory.
string[] fileEntries = Directory.GetFiles(sourceDir);
foreach (string fileName in fileEntries)
{
XmlDocument xmlDoc = new XmlDocument(); //* create an xml document object.
string docPath = fileName;
xmlDoc.Load(docPath); //* load the XML document from the specified file.
XmlNodeList nodeList = xmlDoc.GetElementsByTagName("item");
foreach (XmlNode node in nodeList)
{
XmlElement itemElement = (XmlElement) node;
string itemDescription = itemElement.GetElementsByTagName("description")[0].InnerText;
if (txtComKeyword1.Text != (String.Empty) && itemDescription.ToLower().Contains(txtComKeyword1.Text.ToLower()) ||
txtComKeyword2.Text != (String.Empty) && itemDescription.ToLower().Contains(txtComKeyword2.Text.ToString()) ||
txtComKeyword3.Text != (String.Empty) && itemDescription.ToLower().Contains(txtComKeyword3.Text.ToString()) ||
txtComKeyword4.Text != (String.Empty) && itemDescription.ToLower().Contains(txtComKeyword4.Text.ToString()))
{
string itemTitle = itemElement.GetElementsByTagName("title")[0].InnerText;
string itemDate = itemElement.GetElementsByTagName("pubDate")[0].InnerText;
string itemAuthor = itemElement.GetElementsByTagName("author")[0].InnerText;
richComResults.AppendText("Author: " + itemAuthor + "\nDate: " + itemDate + "\nTitle: " + itemTitle + "\nDescription: " + itemDescription + "\n\n--------\n\n");
}
}
}
}
Try this:
int pointer = 0;
int index = 0;
string keyword = "txtComKeyword1";
while (true)
{
index = richComResults.Text.IndexOf(keyword, pointer);
//if keyword not found
if (index == -1)
{
break;
}
richComResults.Select(index, keyword.Length);
richComResults.SelectionFont = new System.Drawing.Font(richComResults.Font, FontStyle.Bold);
pointer = index + keyword.Length;
}
This searches for the keyword and highlights it. Then it continues the search after the found keyword. The pointer is used to keep track of the search position in your text. The index marks the position of the found keyword.
Jan's answer contains great content, but I shuddered mildly at the while(true) and break aspect! Here's my tweaked (case-insensitive) version...
int nextHigh = RTF.Text.IndexOf(txSearch, 0, StringComparison.OrdinalIgnoreCase);
while (nextHigh >= 0)
{
RTF.Select(nextHigh, txSearch.Length);
RTF.SelectionColor = Color.Red; // Or whatever
RTF.SelectionFont = new Font("Arial", 12, FontStyle.Bold); // you like
nextHigh = RTF.Text.IndexOf(txSearch, nextHigh + txSearch.Length, StringComparison.OrdinalIgnoreCase);
}
try this code :
void ParseLine(string line)
{
Regex r = new Regex("([ \\t{}():;])");
String[] tokens = r.Split(line);
foreach (string token in tokens)
{
// Set the tokens default color and font.
richTextBox1.SelectionColor = Color.Black;
richTextBox1.SelectionFont = new Font("Courier New", 10, FontStyle.Regular);
// Check whether the token is a keyword.
String[] keywords = { "Author", "Date", "Title", "Description", };
for (int i = 0; i < keywords.Length; i++)
{
if (keywords[i] == token)
{
// Apply alternative color and font to highlight keyword.
richTextBox1.SelectionColor = Color.Blue;
richTextBox1.SelectionFont = new Font("Courier New", 10, FontStyle.Bold);
break;
}
}
richTextBox1.SelectedText = token;
}
richTextBox1.SelectedText = "\n";
}
and after fill your string str with your method call my method :
string strRich =
"Author : Habib\nDate : 2012-08-10 \nTitle : mytitle \nDescription : desc\n";
Regex r = new Regex("\\n");
String[] lines = r.Split(strRich);
foreach (string l in lines)
{
ParseLine(l);
}
enjoy.