How to remove lines one by one in Richtextbox C# - c#

I use this code to delete lines one by one in richtextbox, but still leaving an empty line (whitespace).
var text = "";//Holds the text of current line being looped.
var startindex = 0;//The position where selection starts.
var endindex = 0;//The length of selection.
for (int i = 0; i < richtextbox1.Lines.Length; i++)//Loops through each line of text in RichTextBox
{
text = richtextbox1.Lines[i]; //Stores current line of text.
startindex = richtextbox1.GetFirstCharIndexFromLine(i);
endindex = text.Length;
richtextbox1.Select(startindex, endindex);
MessageBox.Show(richtextbox1.SelectedText);
richtextbox1.SelectedText = "";
}
How do I delete lines one by one without empty lines (whitespace)?

// Gets the number of newline characters in your rich text box
var numberOfNewLines = richTextBox1.Text.Count(r => r == '\n');
for (var i = 0; i < numberOfNewLines; i++)
{
// Finds the first occurance of the newline character
var newlineCharacterIndex = richTextBox1.Text.IndexOf('\n') + 1;
// Replaces the rich textbox text with everything but the above line
richTextBox1.Text = richTextBox1.Text.Substring(newlineCharacterIndex);
MessageBox.Show("OK!");
}
// Removes the final line.
richTextBox1.Text = string.Empty;
I think you were on the right track, but the way you were doing it was just removing the contents of the line and not the line itself.

Related

Wrap string without cutting words for thermal printer

I am trying to print a string by thermal printer, but the problem is that paper accept only 32 charcters in a line and than break rest text to another line, by this last character always cut into two parts and string is hard to understand.
Example:
string PrintStr = "01-(200),02-(200),03-(200),04-(200),05-(200)";
Current output:
01-(200),02-(200),03-(200),04-(20 # <- 200 is broken into 20 and 0
0),05-(200)
Better output:
01-(200),02-(200),03-(200), # Split on comma, numbers are preserved
04-(200),05-(200)
I also use a Linq mehtod to break line after 32th character but the last character is cutting. I just want after last Comma "," in first 32 characters a new line will be add by that my string will break in readable text. I am sharing my code. Thanks in advance for help..
Input:
var PrintStr = "01-(200),02-(200),03-(200),04-(200),05-(200),06-(200),07-(200),08-(200),09-
(200),10-(200),11-(200),12-(200),13-(200),14-(200),15-
(200),16-(200),17-(200),18-(200),19-(200),20-(200),21-(200),22-(200),23-(200),24-(200),25-(200),26-
(200),27-(200),28-(200),29-(200),30-(200),31-(
200),32-(200),33-(200),34-(200),35-(200),36-(200),37-(200),38-(200),39-(200),40-(200),41-(200),42-
(200),43-(200),44-(200),45-(200),46-(200),47-(200),48-
(200),49-(200),50-(200),51-(200),52-(200),53-(200),54-(200),55-(200),56-(200),57-(200),58-(200),59-
(200),60-(200),61-(200),62-(200),63-(200),64-
(200),65-(200),66-(200),67-(200),A1111-(200)"
Code (my attept):
var AdjustPrintStr = string.Join(Environment.NewLine, PrintStr
.ToLookup(c => k++ / 32)
.Select(e => new String(e.ToArray())));
Output (current, unwanted):
01-(200),02-(200
),03-(200),04-(200),05-(200),06-
(200),07-(200),08-(200),09-(200)
,10-(200),11-(200),12-(200),13-(
200),14-(200),15-(200),16-(200),
17-(200),18-(200),19-(200),20-(2
00),21-(200),22-(200),23-(200),2
4-(200),25-(200),26-(200),27-(20
0),28-(200),29-(200),30-(200),31
-(200),32-(200),33-(200),34-(200
),35-(200),36-(200),37-(200),38-
(200),39-(200),40-(200),41-(200)
,42-(200),43-(200),44-(200),45-(
200),46-(200),47-(200),48-(200),
49-(200),50-(200),51-(200),52-(2
00),53-(200),54-(200),55-(200),5
6-(200),57-(200),58-(200),59-(20
0),60-(200),61-(200),62-(200),63
-(200),64-(200),65-(200),66-(200
Note, that the last "),A1111-(200)" fragment is lost
Well, you have to implement such a routine
(split text at at characters ensuring at most maxWidth characters in each line) manually;
it's not that difficult:
public static IEnumerable<string> MySplit(string text,
int maxWidth, params char[] at) {
if (null == text)
throw new ArgumentNullException(nameof(text));
else if (maxWidth <= 0)
throw new ArgumentOutOfRangeException(nameof(maxWidth));
else if (null == at)
throw new ArgumentNullException(nameof(at));
int startIndex = 0;
int bestIndex = -1;
for (int i = 0; i < text.Length; ++ i) {
if ((i - startIndex) > maxWidth) {
if (bestIndex < 0)
bestIndex = i - 1;
yield return text.Substring(startIndex, bestIndex - startIndex + 1);
startIndex = bestIndex += 1;
bestIndex = -1;
}
if (at.Contains(text[i]))
bestIndex = i;
}
yield return text.Substring(startIndex);
}
Now, let's print out the source string:
string PrintStr = #"01-(200),02-(200),03-(200),04-(200),05-(200),06-(200),07-(200),08-(200),09-
(200),10-(200),11-(200),12-(200),13-(200),14-(200),15-
(200),16-(200),17-(200),18-(200),19-(200),20-(200),21-(200),22-(200),23-(200),24-(200),25-(200),26-
(200),27-(200),28-(200),29-(200),30-(200),31-(
200),32-(200),33-(200),34-(200),35-(200),36-(200),37-(200),38-(200),39-(200),40-(200),41-(200),42-
(200),43-(200),44-(200),45-(200),46-(200),47-(200),48-
(200),49-(200),50-(200),51-(200),52-(200),53-(200),54-(200),55-(200),56-(200),57-(200),58-(200),59-
(200),60-(200),61-(200),62-(200),63-(200),64-
(200),65-(200),66-(200),67-(200),A1111-(200)";
It seems, you should preprocess it in order to remove all new lines, tabulations, spaces etc. and
only then split it:
// Let's remove all white spaces (new lines, tabulations, spaces)
PrintStr = Regex.Replace(PrintStr, #"\s+", "");
// split on comma ',' while ensuring each lines <= 32 characters
var result = string.Join(Environment.NewLine, MySplit(PrintStr, 32, ','));
Console.Write(result);
Outcome:
01-(200),02-(200),03-(200),
04-(200),05-(200),06-(200),
07-(200),08-(200),09-(200),
10-(200),11-(200),12-(200),
13-(200),14-(200),15-(200),
16-(200),17-(200),18-(200),
19-(200),20-(200),21-(200),
22-(200),23-(200),24-(200),
25-(200),26-(200),27-(200),
28-(200),29-(200),30-(200),
31-(200),32-(200),33-(200),
34-(200),35-(200),36-(200),
37-(200),38-(200),39-(200),
40-(200),41-(200),42-(200),
43-(200),44-(200),45-(200),
46-(200),47-(200),48-(200),
49-(200),50-(200),51-(200),
52-(200),53-(200),54-(200),
55-(200),56-(200),57-(200),
58-(200),59-(200),60-(200),
61-(200),62-(200),63-(200),
64-(200),65-(200),66-(200),
67-(200),A1111-(200)
Hope, it's the very picture you want to see after printing

C# Console Word Wrap

I have a string with newline characters and I want to wrap the words. I want to keep the newline characters so that when I display the text it looks like separate paragraphs. Anyone have a good function to do this? Current function and code below.(not my own function). The WordWrap function seems to be stripping out \n characters.
static void Main(string[] args){
StreamReader streamReader = new StreamReader("E:/Adventure Story/Intro.txt");
string intro = "";
string line;
while ((line = streamReader.ReadLine()) != null)
{
intro += line;
if(line == "")
{
intro += "\n\n";
}
}
WordWrap(intro);
public static void WordWrap(string paragraph)
{
paragraph = new Regex(#" {2,}").Replace(paragraph.Trim(), #" ");
var left = Console.CursorLeft; var top = Console.CursorTop; var lines = new List<string>();
for (var i = 0; paragraph.Length > 0; i++)
{
lines.Add(paragraph.Substring(0, Math.Min(Console.WindowWidth, paragraph.Length)));
var length = lines[i].LastIndexOf(" ", StringComparison.Ordinal);
if (length > 0) lines[i] = lines[i].Remove(length);
paragraph = paragraph.Substring(Math.Min(lines[i].Length + 1, paragraph.Length));
Console.SetCursorPosition(left, top + i); Console.WriteLine(lines[i]);
}
}
Here is a word wrap function that works by using regular expressions to find the places that it's ok to break and places where it must break. Then it returns pieces of the original text based on the "break zones". It even allows for breaks at hyphens (and other characters) without removing the hyphens (since the regex uses a zero-width positive lookbehind assertion).
IEnumerable<string> WordWrap(string text, int width)
{
const string forcedBreakZonePattern = #"\n";
const string normalBreakZonePattern = #"\s+|(?<=[-,.;])|$";
var forcedZones = Regex.Matches(text, forcedBreakZonePattern).Cast<Match>().ToList();
var normalZones = Regex.Matches(text, normalBreakZonePattern).Cast<Match>().ToList();
int start = 0;
while (start < text.Length)
{
var zone =
forcedZones.Find(z => z.Index >= start && z.Index <= start + width) ??
normalZones.FindLast(z => z.Index >= start && z.Index <= start + width);
if (zone == null)
{
yield return text.Substring(start, width);
start += width;
}
else
{
yield return text.Substring(start, zone.Index - start);
start = zone.Index + zone.Length;
}
}
}
If you want another newline to make text look-like paragraphs, just use Replace method of your String object.
var str =
"Line 1\n" +
"Line 2\n" +
"Line 3\n";
Console.WriteLine("Before:\n" + str);
str = str.Replace("\n", "\n\n");
Console.WriteLine("After:\n" + str);
Recently I've been working on creating some abstractions that imitate window-like features in a performance- and memory-sensitive console context.
To this end I had to implement word-wrapping functionality without any unnecessary string allocations.
The following is what I managed to simplify it into. This method:
preserves new-lines in the input string,
allows you to specify what characters it should break on (space, hyphen, etc.),
returns the start indices and lengths of the lines via Microsoft.Extensions.Primitives.StringSegment struct instances (but it's very simple to replace this struct with your own, or append directly to a StringBuilder).
public static IEnumerable<StringSegment> WordWrap(string input, int maxLineLength, char[] breakableCharacters)
{
int lastBreakIndex = 0;
while (true)
{
var nextForcedLineBreak = lastBreakIndex + maxLineLength;
// If the remainder is shorter than the allowed line-length, return the remainder. Short-circuits instantly for strings shorter than line-length.
if (nextForcedLineBreak >= input.Length)
{
yield return new StringSegment(input, lastBreakIndex, input.Length - lastBreakIndex);
yield break;
}
// If there are native new lines before the next forced break position, use the last native new line as the starting position of our next line.
int nativeNewlineIndex = input.LastIndexOf(Environment.NewLine, nextForcedLineBreak, maxLineLength);
if (nativeNewlineIndex > -1)
{
nextForcedLineBreak = nativeNewlineIndex + Environment.NewLine.Length + maxLineLength;
}
// Find the last breakable point preceding the next forced break position (and include the breakable character, which might be a hypen).
var nextBreakIndex = input.LastIndexOfAny(breakableCharacters, nextForcedLineBreak, maxLineLength) + 1;
// If there is no breakable point, which means a word is longer than line length, force-break it.
if (nextBreakIndex == 0)
{
nextBreakIndex = nextForcedLineBreak;
}
yield return new StringSegment(input, lastBreakIndex, nextBreakIndex - lastBreakIndex);
lastBreakIndex = nextBreakIndex;
}
}

C# - split a RichTextBox line in two based on the caret position

I've got a RichTextBox, here referred to as box.
string currentline = box.Lines[box.GetLineFromCharIndex(box.SelectionStart)];
That line there fetches the line the caret is in. It works excellently.
However, I have a need to get two strings from this. The first is everything on that line UP to the caret, and the second is everything on that line AFTER it.
For instance, if the line is How is you|r day going?, with | representing the caret, I would get How is you and r day going?, separately.
I wrote this monstrosity, which works:
string allbefore = box.Text.Substring(0, box.SelectionStart);
string allafter = box.Text.Substring(box.SelectionStart, box.Text.Length - box.SelectionStart);
string linebefore = "";
for (int i = 0; i < allbefore.Length; i++)
{
linebefore += allbefore[i];
if (allbefore[i] == '\n')
linebefore = "";
}
string lineafter = "";
for (int i = 0; i < allafter.Length; i++)
{
if (allafter[i] == '\n')
break;
else
lineafter += allafter[i];
}
It gives me the result I want, but involves looping through EVERY character in the entire box, which just hurts. Is there an easy way to do this I'm just missing? Thanks.
This might do the trick for you
string currentline = box.Lines[box.GetLineFromCharIndex(box.SelectionStart)];
var listOfStrings = new List<string>();
string[] splitedBox = currentline.Split('|');
foreach(string sp in splitedBox)
{
string[] lineleft = sp.Split('\n');
listOfStrings.Add(lineleft[lineleft.Count() - 1]);
}
In the first approach we are splitting the line by char | than finding if we have any \n if it exsist we are taking the values accordingly
Another approach could be
string box = "How is \n you|r day \n going?";
bool alllinesremoved = true;
while(alllinesremoved)
{
if(box.Contains('\n'))
{
if(box.IndexOf('\n') > box.IndexOf('|'))
{
box = box.Remove(box.IndexOf('\n'), (box.Length - box.IndexOf('\n')));
}
else
{
box = box.Remove(0, box.IndexOf('\n') + 1);
}
}
else
{
alllinesremoved = false;
}
}
string[] splitedBox = box.Split('|');
in the second approach we are removing the characters before and after the \n and then splitting the string. I think the second one seems more good to me.
Have you tried using line.split? Not sure if this is what you want.
Store the position of \n using indexOf and, if >= 0, that is, the string contains it, use substring and assign the value otherwise.
string allbefore = box.Text.Substring(0, box.SelectionStart);
string allafter = box.Text.Substring(box.SelectionStart, box.Text.Length - box.SelectionStart);
int newLinePos = allBefore.lastIndexOf("\n");
string lineBefore = ((newLinePos >= 0) ? (allBefore.substring(newLinePos + 1)) : (allBefore));
newLinePos = allafter.indexOf("\n");
string lineAfter = ((newLinePost >= 0) ? (allAfter.substring(0, newLinePos)) : (allAfter));

TrimEnd not erase last spaces

I want to copy selected rows from my data grid view to clipboard
And it's work perfect, just one thing: I not success to remove last 3 spaces from the string.
(I also try: clipboard.Remove(clipboard.Length - 3) and clipboard.Trim(), but both not working too)
My function:
private void menuCopyClipboard_wholeRow_Click(object sender, EventArgs e)
{
#region calculate spaces
int[] spaces = new int[8]; // I have 8 columns in the data grid view
for (int i = 0; i < 8; i++)
spaces[i] = 0;
foreach (DataGridViewRow dgvr in datagridview1.SelectedRows)
foreach (DataGridViewColumn dgvc in datagridview1.Columns)
{
int cellLength = datagridview1.Rows[dgvr.Index].Cells[dgvc.Index].FormattedValue.ToString().Length;
if (spaces[dgvc.Index] < cellLength)
spaces[dgvc.Index] = cellLength;
}
#endregion
string clipboard = "";
foreach (DataGridViewRow dgvr in datagridview1.SelectedRows)
{
foreach (DataGridViewColumn dgvc in datagridview1.Columns)
clipboard += String.Format("{0, -" + spaces[dgvc.Index] + "} ", // 3 spaces between columns
datagridview1.Rows[dgvr.Index].Cells[dgvc.Index].FormattedValue.ToString());
if (dgvr.Index != 0 && datagridview1.SelectedRows.Count > 1) clipboard += "\n"; // to not add enter after last line nor copy one line
}
clipboard.TrimEnd(); // <-- doens't erase spaces
Clipboard.SetText(clipboard);
}
The problem: The spaces not erased, as you can see in the picture below:
(The question: what wrong? why the spaces are not erased?)
Strings are immutable.
That beeing said, a string manipulating method like TrimEnd() will always return a new string.
So doing this:
clipboard = clipboard.Trim();
will just fix your problem.
If you also need to remove the \n you can use this:
char[] trimChars = new char[]{' ','\n'};
clipboard = clipboard.TrimEnd(trimChars);
TrimEnd() removes all trailing occurrences of a set of characters specified in an array from the current String object, and returns the resultant string, so you should receive the converted string.
char[] charsToTrim = {' '};
clipboard = clipboard.TrimEnd(charsToTrim);
In this line
if (dgvr.Index != 0 && datagridview1.SelectedRows.Count > 1) clipboard += "\n"; // to not add enter after last line nor copy one line
You're adding a "\n" at the ending of the string, that's prevent the Trim to work try trimming before adding the "\n".
if (dgvr.Index != 0 && datagridview1.SelectedRows.Count > 1) clipboard = clipboard.Trim() + "\n"; // to not add enter after last line nor copy one line
else clipboard = clipboard.Trim();
Use this
clipboard.Trim();
Instead of :
clipboard.TrimEnd();

How do I move items up/down in text file

How do I move items/values up and down a text file. At the moment my program reads a text file, an uses a while to make sure it stop when there is no more lines to read. I used an if statement to check if counter equals the line of the value I want to move. I am stuck not sure how to continue from here.
_upORDown = 1;
using (StreamReader reader = new StreamReader("textfile.txt"))
{
string line = reader.ReadLine();
int Counter = 1;
while (line != null)
{
if (Counter == _upORDown)
{
//Remove item/replace position
}
Counter++;
}
}
You can read the file in memory, move the line to where you need it, and write the file back. You can use ReadAllLines and WriteAllLines.
This code moves the string at position i up by one line:
if (i == 0) return; // Cannot move up line 0
string path = "c:\\temp\\myfile.txt";
// get the lines
string[] lines = File.ReadAllLines(path);
if (lines.Length <= i) return; // You need at least i lines
// Move the line i up by one
string tmp = lines[i];
lines[i] = lines[i-1];
lines[i-1] = tmp;
// Write the file back
File.WriteAllLines(path, lines);
#dasblinkenlight's answer, using LINQ:
string path = "c:\\temp\\myfile.txt";
var lines = File.ReadAllLines(path);
File.WriteAllLines(
path,
lines.Take(i).Concat(
lines.Skip(i+1)
)
);
This deletes the line at position i (zero-based) and moves the other lines up.
Adding to a new line:
string path = "c:\\temp\\myfile.txt";
var lines = File.ReadAllLines(path);
var newline = "New line here";
File.WriteAllLines(
path,
lines.Take(i).Concat(
new [] {newline}
).Concat(
lines.Skip(i+1)
)
);

Categories