5

i have a label control in windows form. i want to display full text in the label . condition is like this:

  • if text length exceeds more that 32 character than it will come in the new line.
  • if possible split by full word, without hyphen(-).

    So far i have reach till below code:

       private void Form1_Load(object sender, EventArgs e)
        {
            string strtext = "This is a very long text. this will come in one line.This is a very long text. this will come in one line.";
            if (strtext.Length > 32)
            {              
                IEnumerable<string> strEnum = Split(strtext, 32);
                label1.Text =string.Join("-\n", strEnum);
            }         
        }
        static IEnumerable<string> Split(string str, int chunkSize)
        {
            return Enumerable.Range(0, str.Length / chunkSize)
                .Select(i => str.Substring(i * chunkSize, chunkSize));
        }
    

but issue is that the last line is not displaying entirely because its splitting by 32 character.

Is there another way to achieve this?

Rudi Visser
  • 21,350
  • 5
  • 71
  • 97
Mohammad Arshad Alam
  • 9,694
  • 6
  • 38
  • 61
  • 1
    I see your problem - the last bit of text doesn't show up. I suggest you read the comments below where you took the Split method from, the answer is there. http://stackoverflow.com/questions/1450774/splitting-a-string-into-chunks-of-a-certain-size – Chris Gessler Jan 21 '13 at 10:12
  • is there any way to break by word with full text, without hyphen(-)? – Mohammad Arshad Alam Jan 21 '13 at 10:37
  • Yes, you need to implement a Word-Wrap method. Looks like Steve provided one and I'll post the one I use in a few minutes. – Chris Gessler Jan 21 '13 at 11:19

5 Answers5

2

I don't know if you will accept an answer that doesn't use linq, but this is simple:

string SplitOnWholeWord(string toSplit, int maxLineLength)
{
    StringBuilder sb = new StringBuilder();
    string[] parts = toSplit.Split();
    string line = string.Empty;
    foreach(string s in parts)
    {
        if(s.Length > 32)
        {
            string p = s;
            while(p.Length > 32)
            {
                int addedChars = 32 - line.Length;
                line = string.Join(" ", line, p.Substring(0, addedChars));
                sb.AppendLine(line);
                p = p.Substring(addedChars);
                line = string.Empty;
            }
            line = p;
        }
        else
        {
            if(line.Length + s.Length > maxLineLength)
            {
                sb.AppendLine(line);
                line = string.Empty;
            }
            line = (line.Length > 0 ? string.Join(" ", line, s) : s);
        }
    }
    sb.Append(line.Trim());
    return sb.ToString();
}

Call with

string result = SplitOnWholeWord(strtext, 32);

It is possible to transform this in an extension method easily:

Put the code above in a separate file and create a static class

public static class StringExtensions
{
     public static string SplitOnWholeWord(this string toSplit, int maxLineLength)
     {
          // same code as above.....
     }

}

and call it in this way:

string result = strtext.SplitOnWholeWord(32);
Steve
  • 213,761
  • 22
  • 232
  • 286
  • Thanks to you, however, beware that this is not a complete solution. If it happens that a `word` contains more that 32 characters you will have problems with the code above – Steve Jan 21 '13 at 11:37
  • Well, this proved to be a bit more complicated than I thought, but now it seems to split correctly also for substring with length > 32 – Steve Jan 21 '13 at 12:14
1

Try this..

string strtext = "This is a very long text. this will come in one line.This is a very long text. this will come in one line.";
if (strtext.Length > 32)
{
   IEnumerable<string> strEnum = Split(strtext, 32);
   string a = string.Join("-\n", strEnum);
   if ((strtext.Length % 32)>0)
   {
      string lastpart = strtext.Substring(((strtext.Length / 32) * 32));
      a = a + "-\n" + lastpart;
   }
   label1.Text=a;
 }

Hope it helps :)

Avishek
  • 1,896
  • 14
  • 33
0

You have to take the Ceiling of result in the following calculation

str.Length / chunkSize

Right now it will return integer part of the result and ignore if any reminder is there , thus if you have 120 characters in the str , and your chunk size is 50 , the above calculation will give result = 2 which you are using as number of chunks and that is wrong you need 3 here.

To make sure that your division works fine , you can add additional length to the str.length

Use the following code:

static IEnumerable<string> Split(string str, int chunkSize)
{
    return Enumerable.Range(0, (str.Length+chunkSize-1) / chunkSize)
        .Select(i => str.Substring(i * chunkSize, (str.length-(i*chunkSize))>=chunkSize? chunkSize:str.length-(i*chunkSize)));
}
Imran Rizvi
  • 7,331
  • 11
  • 57
  • 101
0

You could try

static IEnumerable<string> Split(string str, int chunkSize)
    {
        var count = str.Length / chunkSize;
        var result=Enumerable.Range(0, count)
            .Select(i => str.Substring(i * chunkSize, chunkSize));
        var end = count * chunkSize;
        if (end < str.Length) {
            result = result.Concat(str.Substring(end, str.Length - end));
        }
        return result;
    }

or

static IEnumerable<string> Split(string str, int chunkSize)
    {
       for (var i=0; i<str.Length; i+=chunkSize) {
           yield return str.Substring(i, Math.Min(str.Length-i, chunkSize));
       }
    }      

EDIT: Justified split, after comment

static IEnumerable<string> split(string str,int chunkSize) {
    var words=str.Split(' ');
    var line=new StringBuilder(chunkSize);
    for (var i=0; i<words.Length;i++) {
        var word=words[i];
        if (line.Length + word.Length + 1 > chunkSize) {
            if (line.Length == 0) {
                for(var x=0;x<word.Length/chunkSize;x++) {
                    yield return word.Substring(x*chunkSize,chunkSize);
                }
                var remainder = word.Length % chunkSize;
                if (remainder>0) {
                    line.Append(word.Substring(word.Length-remainder, remainder));
                }
            } else {
                yield return line.ToString();
                line.Clear();
                i--; // Force reprocessing this word
            }
        }  else {
            if (line.Length>0) {
                line.Append(" ");
            }
            line.Append(word);
        }
    }
}

don't forget to change your string.Join("-\n") to be string.Join("\n")

Bob Vale
  • 18,094
  • 1
  • 42
  • 49
0

Throwing my answer into the mix. This works:

static IEnumerable<string> Split(string str, int chunkSize) {
    int difference = (str.Length % chunkSize);
    int count = str.Length / chunkSize;
    return Enumerable.Range(0, count + 1)
        .Select(i => str.Substring(i * chunkSize, i == count ? difference : chunkSize));
}
Simon Whitehead
  • 63,300
  • 9
  • 114
  • 138