different format into one single line Interop.word - c#

I've been trying to figure out how to insert 2 different formats into the same paragraph using interop.word in c# like this:
hello planet earth here's what I want to do

Assuming you have your document defined as oDoc, the following code should get you the desired result:
Word.Paragraph oPara = oDoc.Content.Paragraphs.Add(ref oMissing);
oPara.Range.Text = "hello planet earth here's what I want to do";
object oStart = oPara.Range.Start + 13;
object oEnd = oPara.Range.Start + 18;
Word.Range rBold = oDoc.Range(ref oStart, ref oEnd);
rBold.Bold = 1;

I had to modify Dennis' answer a little to get it to work for me.
What I'm doing it totally automated, so I have to only work with variables.
private void InsertMultiFormatParagraph(string text, int size, int spaceAfter = 10) {
var para = docWord.Content.Paragraphs.Add(ref objMissing);
para.Range.Text = text;
// Explicitly set this to "not bold"
para.Range.Font.Bold = 0;
para.Range.Font.Size = size;
para.Format.SpaceAfter = spaceAfter;
var start = para.Range.Start;
var end = para.Range.Start + text.IndexOf(":");
var rngBold = docWord.Range(ref objStart, ref objEnd);
rngBold.Bold = 1;
para.Range.InsertParagraphAfter();
}
The main difference that made me want to make this post was that the Paragraph should be inserted AFTER the font is changed. My initial thought was to insert it after setting the SpaceAfter property, but then the objStart and objEnd values were tossing "OutOfRange" Exceptions. It was a little counter-intuitive, so I wanted to make sure everyone knew.

The following code seemed to work the best for me when formatting a particular selection within a paragraph. Using Word's built in "find" function to make a selection, then formatting only the selected text. This approach would only work well if the text to select is a unique string within the selection. But for most situations I have run across, this seems to work.
oWord.Selection.Find.Text = Variable_Containing_Text_to_Select; // sets the variable for find and select
oWord.Selection.Find.Execute(); // Executes find and select
oWord.Selection.Font.Bold = 1; // Modifies selection
oWord.Selection.Collapse(); // Clears selection
Hope this helps someone!

I know this post is old, but it came out in almost all my searches. The answer below is in case someone, like me, wants to do this for more than one word in a sentence. In this case, I loop through a string array of variables that contain strings and change that text to bold--modifing #joshman1019
string[] makeBold = new string[4] {a, b, c, d};
foreach (string s in makeBold)
{
wApp.Selection.Find.Text = s; //changes with each iteration
wApp.Selection.Find.Execute();
wApp.Selection.Font.Bold = 1;
wApp.Selection.Collapse(); //used to 'clear' the selection
wApp.Selection.Find.ClearFormatting();
}
So, each string represented by the variable will be bold. So if a = "hello world", then Hello World is made bold in the Word doc. Hope it saves someone some time.

I know this is an old thread, but I thought I'd post here anyway for those that come across it via Google (like I did). I got most of the way to a solution with krillgar's approach, but I had trouble because some of my text contains newlines. Accordingly, this modification worked best for me:
private void WriteText(string text)
{
var para = doc.Content.Paragraphs.Add();
var start = para.Range.Start;
var end = para.Range.Start + text.IndexOf(":");
para.Range.Text = text;
para.Range.Font.Bold = 0;
para.Range.InsertParagraphAfter();
if(text.Contains(":")){
var rngBold = doc.Range(start, end);
rngBold.Bold = 1;
}
}
The key difference is that I calculate start and end earlier in the function. I can't quite put my finger on it, but I think if your new text has newlines in it, the later calculation of start/end messes something up.
And obviously my solution is intended for text with the format:
Label: Data
where Label is to be bolded.

Consider usage of Range.Collapse eventually with Microsoft.Office.Interop.Word.WdCollapseDirection.wdCollapseEnd as parameter.
That would allow next text to have formatting different than previous text (and next text formatting will not affect formatting of previous one).

Related

Add more than one hyperlink in a MS-Word table cell

I'm new to the Word programming with C# and I'm trying to insert 3 hyperlinks in a word document using C#, but for some reason, the hyperlink get overwrite and only the last hyperlinks remains in the cell.
After some research, it seems to be a common problem. Using this exemple, it should work... https://social.msdn.microsoft.com/Forums/office/en-US/c35d9598-e933-4a90-ba6e-088c2bdb6484/adding-multiple-links-to-a-table-cell?forum=worddev
Here's my function
private static void RemplirSommaireChangement(Word.Document doc, Word.Table t, string noChangement, string responsable, DateTime dateMEP, List<string> backlogItems)
{
int nbRows = t.Rows.Count;
Word.Range r;
object oAdress;
Word.Hyperlinks hl;
t.Rows[1].Cells[2].Range.Text = noChangement;
t.Rows[2].Cells[2].Range.Text = responsable;
t.Rows[3].Cells[2].Range.Text = dateMEP.ToShortDateString();
t.Rows[5].Cells[2].Range.Text = "";
hl = t.Rows[5].Cells[2].Range.Hyperlinks;
foreach (string s in backlogItems)
{
r = t.Rows[5].Cells[2].Range;
oAdress = "http://www.test-" + s + ".com";
r = r.Hyperlinks.Add(r, oAdress, TextToDisplay: (object)(s + "\r\n")).Range;
r.Collapse(Word.WdCollapseDirection.wdCollapseEnd);
r.InsertAfter("\r\n");
r.Collapse(Word.WdCollapseDirection.wdCollapseEnd);
}
}
and how it is call :
List<string> stories = new List<string>();
stories.Add("test1");
stories.Add("test2");
stories.Add("test3");
RemplirSommaireChangement(doc, t, "No changement", "responsable", DateTime.Now, stories);
Any idea what's wrong with this function?
Thanks!
The main problem is I think that you have
r = t.Rows[5].Cells[2].Range;
inside your foreach loop, which means that you are resetting the range r To be the range of the cell for each string in backlogItems. So you will end up with a hyperlink constructed from the last of those strings, followed by a couple of paragraph returns.
Moving that line so it comes before the loop is where I’d start. Without testing I can’t tell whether you would need to adjust other parts of the code as well.

Trackbar Percent to richtextbox Text

i have a Trackbar and want it to add the Current Value to a richtextbox Text without replacing the whole Text Line
richTextBox1.Rtf = richTextBox1.Rtf.Replace("aimbot_aimtime=85.000000", "aimbot_aimtime=" + trackbarpercent.Text + ".000000");
(i get the Value from my Label)
Thats what im using right now but it only Replaces it if the Text is "aimbot_aimtime=85.000000"
i want it to add the new Value after "aimbot_aimtime=NEWVALUE" but i cant get it to work atm
#Marc Lyon
I think a better way for me is to Replace the Line itself cause its always Line 7
Got it working, thanks to all who helped :)
void changeLine(RichTextBox RTB, int line, string text)
{
int s1 = RTB.GetFirstCharIndexFromLine(line);
int s2 = line < RTB.Lines.Count() - 1 ?
RTB.GetFirstCharIndexFromLine(line + 1) - 1 :
RTB.Text.Length;
RTB.Select(s1, s2 - s1);
RTB.SelectedText = text;
}
private void trackbarpercent_Click(object sender, EventArgs e)
{
changeLine(richTextBox1, 7, "aimbot_aimtime=" + aimtimetrackbar.Value + ".000000");
}
You have to know what the value is in order to replace it, which is why it only works when the value is your default value of 85.
In order to replace the text with the new text, you will have to track the previous value somewhere to use in your replacement. This means a field in your form, a property in some class. Let's say you create an int field on your form (myForm) called oldAimbot_aimtime. Every time the slider changes, put old value into this field. now your code becomes:
var prompt = "aimbot_aimtime=";
var oldvalue = string.Format("{0}{1}", prompt, myForm.oldAimbot_aimtime);
var newvalue = string.Format("{0}{1}", prompt, {NEWVALUE}.Format("#.######");
richTextBox1.Rtf = richTextBox1.Rtf.Replace(oldvalue, newvalue);
This code is off the top of my head and may not work exact, but it should replace the value. What is the value of using a richtextbox on a config screen? Can you post a screenshot?
OK, I see the screenshot. Ethics aside (not sure there is such a thing as a legit aimbot). You are using the richtextbox presumably because it was the easiest control for you to style...
Where you use the richtextbox is probably better suited to a GridView, ListBox, maybe even a treeview where you have finer control over each element.
If you want to use the richtext, write code which emits each option, then you can obtain exact values to use in rtf.Replace()commands
Hope this helps.

C# WinForms - Adding text to each line in a textbox

I am very new to C#. I learn best by experimentation, but of course, I will get completely stumped sometimes. I will try to explain my problem the best I can with what knowledge of the programming language I currently have.
I have been trying to create a simple tool to edit/add lines of text into a text file. I have done much researching, especially on this site, and all the information has been extremely helpful. My problem though, is adding text to both sides to a single line of text within a multi-line textbox.
So lets say I have a textbox with 2 existing lines; I want to add some text next to both sides of to one of one lines, and do the same to the next one. Here is an example of what the text would look like before and after a button is hit:
Before
is not the same as is different than
After
A is not the same as B A is different than B
The two lines in "Before" would be in textBox1 (multiline), and would be inserted to richTextBox1 as "After".
Hopefully I have explained it clearly enough, I do not know where to begin with this.
Thank you.
If you know which index you have to update the text, then you should be able to inset the value directly using insert function exposed by string class
Example:
//Get the text box value
var formatedTextboxString = this.textbox1.Text;
formatedTextboxString = formatedTextboxString.Insert(0, "A ");
formatedTextboxString = formatedTextboxString.Insert(21, "B");
//Place the formated text back to the richTextBox
this.richTextBox1.Text = formatedTextboxString;
Try
"{0} is not the same as {1} {2} is different than {3}"
In textbox1. Then use:
textbox2.Text = String.Format(textbox1.Text, A, B, A, B);
In case if you have multiline textbox:
var list = new List<string>(textBox1.Lines);
for (int i = 0; i < list.Count; ++i)
{
list[i] = "A" + list[i] + "B";
}
textBox1.Lines = list.ToArray();
string[] arr = textBox1.Text.Split(Environment.Newline);
//then loop over each line and add whatever you want :-
foreach (string s in arr)
{
//add here
}
I guess this is good enough hint to start with :)

How to highlight text using string indexes in WPF RichTextBox?

I'm working on a custom RichTextBox which highlights certain words typed in it.
(more like highlight certain strings, because I intent to highlight strings that are not separated by spaces)
I search for strings by loading the text to memory, and looking for a list of strings one by one, then applying formatting to them.
Issue is that, index I get from the plain text representation, doesn't necessarily point to the same position in the RichTextBox's content, when formatting is applied.
(First formatting is perfect. Any subsequent formatting starts to slip to the left. I assume this is because formatting adds certain elements to the documents which makes my indexes incorrect.)
Sample pseudo code for this is as follows.
// get the current text
var text = new TextRange(Document.ContentStart, Document.ContentEnd).Text;
// loop through and highlight
foreach (string entry in WhatToHighlightCollection)
{
var currentText = text;
var nextOccurance = currentText.IndexOf(suggestion); //This index is Unreliable !!!
while (nextOccurance != -1)
{
// Get the offset from start. (There appears to be 2 characters in the
// beginning. I assume this is document and paragraph start tags ??
// So add 2 to it.)
int offsetFromStart = (text.Length) - (currentText.Length) + 2;
var startPointer = Document.ContentStart.
GetPositionAtOffset(offsetFromStart + nextOccurance, LogicalDirection.Forward);
var endPointer = startPointer.GetPositionAtOffset(suggestion.Length, LogicalDirection.Forward);
var textRange = new TextRange(startPointer, endPointer);
textRange.ApplyPropertyValue(TextElement.BackgroundProperty, new SolidColorBrush(Colors.Yellow));
textRange.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold);
textRange.ApplyPropertyValue(TextElement.FontFamilyProperty, new FontFamily("Segoe UI"));
// Go to the next occurance.
currentText = currentText.Substring(nextOccurance + suggestion.Length);
nextOccurance = currentText.IndexOf(suggestion);
}
}
How do I map string indexes to rich text box content ?
NOTE: I'm not worried about the performance of this at the moment, although any suggestions are always welcome, as currently I run this on every TextChanged event to highlight 'as the user type' and it's getting a bit sluggish.

Adding Control based on info in txt file

Following code, credit: Guffa.
Hello All,
I'm trying to add controls to a Form at runtime based on the information found in a Plain Text File. The structure? of the text file is always the same, and will not change. Example:
File.txt:
Label
"This is a label"
320, 240
Explanation:
Control
Text
Location
The following code, provided to me by Guffa, doesn't cause any errors or anything, but at the same time, nothing happens at all. And I'm not sure why... Can somebody please explain why the label doesn't get created and added to the form with the right info attached to it?
MatchCollection lines = Regex.Matches(File.ReadAllText(fileName), #"(.+?)\r\n""([^""]+)""\r\n(\d+), (\d+)\r\n");
foreach (Match match in lines) {
string control = match.Groups[1].Value;
string text = match.Groups[2].Value;
int x = Int32.Parse(match.Groups[3].Value);
int y = Int32.Parse(match.Groups[4].Value);
Console.WriteLine("{0}, \"{1}\", {2}, {3}", control, text, x, y);
if(control == "Label")
{
Label label = new Label();
label.Text = text;
canvas.Controls.Add(label); // canvas is a Panel Control.
label.Location = new Point(x, y);
}
}
I hope that I have clearly explained my situation. Any help at all would be greatly appreciated.
Thanks for taking the time to read.
jase
My guess is that your file doesn't have quite the right format. If you step into the code, does it match anything?
If so, what gets printed to the console?
Have you tried it with the exact sample shown in the question? While I haven't tried it in a form, I've tried the rest of the code above with the sample file, and it works fine.
Personally I don't think I'd use a regex to match all of the lines like this - it makes it harder to diagnose issues - but it should work okay if the file is correct. You say you don't understand the regex provided - that's another good reason not to use it, to be honest. Even if it's entirely correct, it's not a good idea to use code that you don't understand - you won't be able to maintain it.
I would personally just read the lines three at a time and then deal with them that way. Something like this:
private static readonly Regex LocationPattern = new Regex(#"^(\d+), (\d+)$");
...
using (TextReader reader = File.OpenText(filename))
{
while (true)
{
string control = reader.ReadLine();
string text = reader.ReadLine();
string location = reader.ReadLine();
if (control == null)
{
break;
}
if (text == null || location == null)
{
// Or however you want to handle this...
throw new InvalidConfigurationFileException
("Incorrect number of lines");
}
if (text.Length < 2 || !text.StartsWith("\"") || !text.EndsWith("\""))
{
// Or however you want to handle this...
throw new InvalidConfigurationFileException
("Text is not in quotes");
}
text = text.Substring(1, text.Length - 2);
Match locationMatch = LocationPattern.Match(location);
if (!locationMatch.Success)
{
// Or however you want to handle this...
throw new InvalidConfigurationFileException
("Invalid location: " + location);
}
// You could use int.TryParse if you want to handle this differently
Point parsedLocation = new Point(int.Parse(match.Groups[1].Value),
int.Parse(match.Groups[2].Value));
// Now the rest of the code before
}
}
As you can tell, it's a lot more code - but each part of it is relatively simple. Regular expressions are powerful if you're happy to handle them, but unless something is complicated to express "longhand" I often find it easier to maintain the longer way. Just a personal preference though.
Blind guess: I see the last \r\n in the regex is not optional. Possible that your input file is missing a return character after the last line?
Additional note about sucking at regular expressions: there are some tools that will help you experiment with regular expressions, which might be useful, for example, to understand what's going on in this particular case. I always use Expresso, which among other things analyzes the structure of the regular expression you provide and explains what it does.
Another possibility is that you forgot to add canvas (Panel control) to another control so the chain of controls inside canvas is not displayed and you would maybe not see that the canvas itself doesn't display. Which guess is the best? :-)

Categories