richTextBox proper tab setting - c#

I have a list in my richTextBox and I want it to look better. I add the attributes one-by-one, of course from variables, but this is the concept:
richTextBox1.AppendText("attr1 - ");
richTextBox1.AppendText("some text\r\n");
richTextBox1.AppendText("attr2 - ");
richTextBox1.AppendText("some even longer text\r\n");
//etc...
This is how it looks like now:
atrr1 - some text
attr2 - some even longer
text
attr3 - some text
This is what I need:
atrr1 - some text
attr2 - some even longer
text
attr3 - some text
The wrapping should be automatic, I don't want horizontal scroll-bar in my tool. I wish I could share some code but unfortunately I couldn't find any way to solve this.

you can use stringbuilder to achieve your goal and write code formatted like a html table:
StringBuilder tableRtf = new StringBuilder();
tableRtf.Append(#"\trowd \trgraph \cellx1000 Content text of cell \cell\row\pard\par");
richTextBox1.Rtf = tableRtf.ToString();
so you can use it in a for loop
for (int i = 0; i < ROWS_NUMBER; i++)
{
//add cell with columns
}
\trowd --> start table
\trgraph --> start paragraph
\cellx1000 --> cell with width of 1000
refer this likn for documentation

Related

how to get all sentences which contain revision or track changes in Chinese\Japanese\Korean Word document with C#

I am trying to read a Chinese\Japanese\Korean Word document sentence by sentence to find which sentence has track change or revision, and put these sentences which have track changes or revisions to another Word document's table.
For example, if one sentence has track change, then I will copy this sentence with format to that table's column 3 and column 4 in same row.
Then I will reject the track change in column 3 and accept track change in column 4.
The problem is I cannot get these Chinese\Japanese\Korean sentences' content but only "\r\a". So after I assign the sentence's formatted content to that table, only new line added in that table's cell, no other content.
The sample text: 노출의 안전성 이후(가 검토된 후) .
For example, here is a sentence: 노출의 안전성 이후(가 검토된 후) . In this sentence only 출 was marked with track change, I can get 출 with above code, but cannot get 노출의 안전성 이후(가 검토된 후). I want to get 노출의 안전성 이후(가 검토된 후), because in this sentence, one character 출 is in track change, not just 출.
You can add or delete the part of sample text with track change open and try it with below code:
int sentenceCount = doc1.Sentences.Count;
int i = 0;
for (int s = 1; s <= sentenceCount; ++s)
{
i++;
if (doc1.Sentences[s].FormattedText.Revisions.Count > 0)
{
if (i <= tableRowCount)
{
doc2.Activate();
table.Cell(i, 3).Range.FormattedText = doc1.Sentences[s].FormattedText;
table.Cell(i, 4).Range.FormattedText = doc1.Sentences[s].FormattedText;
table.Cell(i, 3).Range.Revisions.RejectAll();
table.Cell(i, 4).Range.Revisions.AcceptAll();
//string sss = doc2.Sentences[s].Text;
}
}
}
doc2.Save();
Could you please take a look and tell me why or any other solution if have? Thanks in advance.

richTextBox - add text and table

i want to add formatted text and table to a richTextBox.
For this I use these codes:
Text:
richTextBox1.SelectionFont = new Font("Maiandra GD", 30, FontStyle.Bold);
richTextBox1.SelectionColor = Color.Red;
richTextBox1.SelectionIndent = 0;
richTextBox1.AppendText("text text text");
And the table:
StringBuilder tableRtf = new StringBuilder();
tableRtf.Append(#"{\rtf1\fbidis\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fnil\fcharset0 Microsoft Sans Serif;}}");
for (int j = 0; j <5; j++)
{
tableRtf.Append(#"\trowd");
tableRtf.Append(#"\cellx2500" + " ghhghgjghjghjhggjh");
tableRtf.Append(#"\intbl\cell");
tableRtf.Append(#"\cellx10000\intbl\cel");
tableRtf.Append(" " + "sdfsdfs" + #"\intbl\clmrg\cell\row");
}
tableRtf.Append(#"\pard");
tableRtf.Append(#"}");
richTextBox1.Rtf=tableRtf.ToString();
But the
richTextBox1.Rtf=tableRtf.ToString();
kills the previous contents.
How can I make compatible them?
It is not a duplicate because I want two thing:
1) add formatted text to richTextBox this way:
richTextBox1.SelectionFont = new Font("Maiandra GD", 30, FontStyle.Bold);
richTextBox1.SelectionColor = Color.Red;
richTextBox1.AppendText("text text text");
It is well readable and I can modify easily.
2) And I want to add tables.
So the structure:
text text text text text
text text text text text
|TABLE|
text text text text text
text text text text text
text text text text text
|TABLE|
etc.
But I don't know how can I apply tables without losing previous contents?
What you need to do is to dissect the rtf codes into the headers and the bodies.
The table body starts with the loop and keeping the \par is surely a good idea.
But you must neither replace the old text nor simply append the body to the end.
Instead you need to insert it before the last curly! This is because that last curly marks the end of the whole rtf code and anything after it will be ignored!
This was simple.
For a full solution you also will want to combine the headers.
This is a lot more work and writing it all out would go beyond an SO answer.
But the basic principle is simple:
You need to understand the things your table header adds to the things already in the primal header.
The most common things are afont table and a color table.
So if you want to use one or more different fonts in the appended table you need to do this:
add them to the font table with a new font index, e.g. as \f1\fnil Consolas; after the previous semicolon.
use it by changing the loop to include the new font right after the first \intbl table-paragraph-formatting control word: \intbl\f2\fs24 ghhghgjghjghjhggjh.
repeat as needed if you want to use different fonts in the table.
add a cfNfont color selector, if you want to.
The same idea will also work for the color table. It doesn't have a explicit indexing, so order matters; all colors are appended, each with a semicolon at the end:
{\colortbl ;\red255\green0\blue0;\red25\green0\blue220;}
..adds a blue color to the red from the formatted text.
You see, this is work and takes some effort and preparations.
You can find the full rtf specs here.
Here is a screenshot of playing a little with the rtf..:
Note that the parts of table header was created by the control; you may want to use a dummy control for this or maybe you can figure out which parts you need and which are not necessary..
Update: Here is a 'appending rtf for dummies' version:
tableRtf.Append(#"{\fonttbl{\f0\fnil\fcharset0 Courier;}}");
for (int j = 0; j <5; j++)
{
tableRtf.Append(#"\trowd");
tableRtf.Append(#"\cellx2500" + " ghhghgjghjghjhggjh");
tableRtf.Append(#"\intbl\cell");
tableRtf.Append(#"\cellx10000\intbl\cel");
tableRtf.Append(" " + "sdfsdfs" + #"\intbl\clmrg\cell\row");
}
tableRtf.Append(#"\pard");
tableRtf.Append(#"}");
string rtf1 = richTextBox1.Rtf.Trim().TrimEnd('}');
string rtf2 = tableRtf.ToString();
richTextBox1.Rtf = rtf1 + rtf2;
Note that the font table inserted before the table body does work! But make sure not to add the rtf-start tag!!

Retain highlighted color of text after editing

Cannot keep the highlighted effect I set in my RichTextBox on my text after removing content of a line in front of him.
No matter how much text I remove from the control it always removes the custom SelectionColor and SelectionBackColor I set to a text already contained in it.
Code of my Removal method:
private void btnRemove_Click(object sender, EventArgs e)
{
//Remove selected line from RichTextBox
richTextBox1.Text = richTextBox1.Text.Remove(richTextBox1.Text.Length - 1, 1);
//Remove all blank lines remaining after deletion
richTextBox1.Text = Regex.Replace(richTextBox1.Text, #"^\s*$(\n|\r|\r\n)", "", RegexOptions.Multiline);
}
The number of letters I want to remove here is 1 as the word "AND" is a simple image inserted by means of Clipboard Paste method.
You must never (read my lips: Never, never, never) change to Text or the Lines property of a RichtTextBox or else you will lose/mess up all previous formatting.
So you need to change this:
richTextBox1.Text = richTextBox1.Text.Remove(richTextBox1.Text.Length - 1, 1);
To this sequence:
First Select the part of the Text you want to change in some way:
richTextBox1.SelectionStart = richTextBox1.Text.Length - 1;
richTextBox1.SelectionLength = 1;
Now you can change it. To delete either use:
richTextBox1.SelectedText = "";
or
richTextBox1.Cut();
The latter version also will place the text in the clipboard; doing it it will keep the formatting of that portion and you could Paste it to some other place..
The same rules apply when you want to add or change any type of formatting:
First Select Then Modify
And, yes, this means that the second command will grow quite a bit, i.e. you will have to replace the RegEx.Replace by a loop :-(

Cannot change hyperlink style with Word interop without changing the style of the next paragraph

I have a document with a format similar to
Section Heading 1
Paragraph 1
...
Paragraph N
Sub Heading 1
Paragraph 1
...
Paragraph N
What I am trying to do is add a hyperlink from a heading to a reference document. I can add the hyperlink and apply a style to the link but the style gets applied to the section's Paragraph 1 as well as the hyperlink.
Note: WordApp is a singleton wrapper around Microsoft.Office.Interop.Word.Application. The HyperlinkDestionation class just holds the bookmark name and the path for the file that contains the bookmark.
private void LinkHeadings(string file)
{
Document doc = WordApp.Open(file);
for (int i = 1; i <= proposal.Paragraphs.Count; i++)
{
HyperlinkDestination dest = null;
Paragraph paragraph = proposal.Paragraphs[i];
paragraph.Range.Select();
Style style = (Style)paragraph.get_Style();
string styleString = ((Style)paragraph.get_Style()).NameLocal;
string headingText = paragraph.Range.Text.Split(' ')[0];
if (styleString.Contains("Heading"))
{
dest = _hyperlinkDestinations.Find(x => x.HyperlinkText == headingText);
}
if (dest != null)
{
Hyperlink link = WordApp.ActiveWindow.Document.Hyperlinks.Add(WordApp.Selection.Range, Address: dest.FilePath, SubAddress: dest.bookmarkName, TextToDisplay: WordApp.Selection.Text);
link.Range.set_Style(style);
}
}
WordApp.Close(true);
}
My guess is that it has something to do with with the hyperlink anchor. I've also tried deleting the heading first then inserting the hyperlink but it also has the same result.
The basic problem is that you are including the paragraph mark in the Hyperlink field that Word inserts. That pargraph mark will then be hidden when the hyperlink field result is displayed, i.e. the Section Heading 1 para. will actually become part of Paragraph 1. When you apply the style to the selection, the entire paragraph will be affected.
I'm not going to attempt to provide C# here, but here are some suggestions
a. as a rule it is better to work with Range objects in Word than the Selection where possible, and you should be able to do so here.
b. If you apply the Hyperlink to the paragraph without the paragraph marker, the paragraph style will be unchanged, so you should not need to re-apply it
c. So instead of the code starting with "paragraph.Range.Select();" you should be able to use something like this (I leave you to get the C# syntax right - perhaps you can edit this message)
Range r = Paragraph.Range();
string headingText = r.Text.Split(' ')[0];
if (styleString.Contains("Heading"))
// you shoul probably also tst for an empty paragraph here before inserting anything (I leave it to you)
{
dest = _hyperlinkDestinations.Find(x => x.HyperlinkText == headingText);
}
if (dest != null)
{
// Move the end of the range one character towards the beginning
r.MoveEnd(Word.WdUnits.WdCharacter,-1)
Hyperlink link = WordApp.ActiveWindow.Document.Hyperlinks.Add(r, Address: dest.FilePath, SubAddress: dest.bookmarkName, TextToDisplay: r.Text);
}
If your code needs to run internationally and you only need to check paragraphs with the built-in style types Heading 1..Heading 9, then it would also be better to compare the Style.Type to see if it is one of those 9 style types. If you have other style types called "Heading something" that need to be included, then you probably need to check both the Style.Type and the name.

How can I insert hard newlines into text where the text wraps in a window?

This question started out with someone wanting to import every apparent 'line of text' in a Word document into a row in an Excel sheet, but I'm sure this is not possible without some development.
I would like to insert a newline (whatever that may be configured as) at every point that a string is wrapped to a new line when displayed in a window. How can I do that? I figure I would need to query the window and get an array of its text lines, then count characters in each line, and in the original string, insert a newline after the number of characters that are displayed for that line.
I do of course realise that changing the window size will invalidate all the work of this code I'm asking how to write, but that is not a relevant issue here.
USEFUL INFO:
I have found a solution to the original, Word to Excel export, problem. When you save a Word document as a text file, after you click Save on the Save dialogue, you are given another dialogue with an option for inserting line breaks.
What you can do is something like this:
int width = txtBox.width;
Graphics g = CreateGraphics();
SizeF size = g.MeasureString(myText, txtBox.Font);
if (size.Width > width)
{
int i = 0;
List<string> lines = new List<String>();
string str = "";
while (i<myText.Length)
{
str = str + myText.SubString(i,1);
int w = (int)(g.MeasureString(str, txtBox.Font).Width);
while (w<width && i<myText.Length)
{
i++;
str = str + myText.SubString(i,1);
}
str = str + '\n';
}
// str now contains your newline formatted string
return str;
}
return myText;
What you can do is get the width of the display control and the font it is using, then use GetTextMetrics to get a TEXTMETRIC struct that can be used to find out the width of each character. This is very involved as it takes into account all the different character profiles.
An easier way is to use GetTextExtentPoint32 which, given a string and the font properties, will return its width in pixels. So you can make a rough estimate as to where the line break would be, call this function on that substring, and insert a line break when the result of GetTextExtentPoint32 is just less than the width of the text control.
Cheers.

Categories

Resources