Tobias Mayr
Tobias Mayr

Reputation: 186

Splitting string after certain number of characters and newlines. In C#

Background: I'm taking large Strings (500-5000 characters) and put them in a PPTX file. My slides only have enough space for around 1000 characters each slide. I would like to split the text after the slide is full and continue on the next slide. As far as I know there is no way (pretty sure) to check the slide if the text is already outside of the slide/textbox (I'm using "OpenXML SDK in combination with "Open-XML PowerTools").

Process so far: I managed to write a method that splits the string after exactly 1000 characters without triggering an error when the maxLength is smaller than 1000 characers (as it happend with Substring(startIndex, maxLength)). This is my Truncate Method:

public static string Truncate(string text, int startIndex, int maxLength)
        {

            if (string.IsNullOrEmpty(text)) return text;
            if (text.Length > startIndex + maxLength)
            {
                return text.Substring(startIndex, maxLength) + "-";
            }
            return text.Substring(startIndex);
        }

Problematic: The problem now is that some strings have a lot of newlines and others have few or none. This results into some strings that take a lot of height and being to large to fit into the slide.

Possible idea: I thought about estimating the string height counting the newlines and adding 30 characters to the number of characters for each newline. This gives a more exact approximation. (A line full of characters contains usually about 50 characters but sometimes the newline is in the middle of the line so I thought +30 characters would be a good guess). This is my method so far:

public int CountCharacters(string text)
{
    var numLines = text.Length;
    numLines += (text.Split('\n').Length) * 30;
    return numLines;
}

Resulting question: How do I now combine these approaches to split the string after I reach a 1000 taking the newlines into account? Or is this the wrong approach after all?

Upvotes: 2

Views: 3820

Answers (3)

Ben Keeping
Ben Keeping

Reputation: 11

I think you're better just to manually count the newlines in your truncate function. Those Split calls are not cheap, and all you are using them for is to count newlines. Here's my attempt (CHARS_PER_NEWLINE is a global constant corresponding to the 30 you suggested):

public static string Truncate(string text, int startIndex, int maxLength)
    {

        if (string.IsNullOrEmpty(text)) return text;
        int remaining = maxLength;
        int index = startIndex;
        while (remaining > 0 && index<text.Length)
        {
            if (text[index] == '\n')
            {
                remaining -= CHARS_PER_NEWLINE;
            }
            else
            {
                remaining--;
            }
            index++;
        }
        return text.Substring(startIndex, index - startIndex) + '-';
    }

Upvotes: 1

Innat3
Innat3

Reputation: 3576

How about something like this:

        string test; //your input string
        int j;  //variable that holds the slide content length
        int max_lines = 10;  //desired maximum amount of lines per slide
        int max_characters = 1000; //desired maximum amount of characters
        char[] input = test.ToCharArray();  //convert input string into an array of characters
        string slide_content;    //variable that will hold the output of each single slide

        while (input.Length > 0)
        {
            //reset slide content and length
            slide_content = string.Empty;
            j = 0;

            //loop through the input string and get a 'j' amount of characters
            while ((slide_content.Split('\n').Length < max_lines) && (j < max_characters))
            {
                j = j + 1;
                slide_content = new string(input.Take(j).ToArray());
            }

            //Output slide content
            Console.WriteLine(slide_content);
            Console.WriteLine("=================== END OF THE SLIDE =====================");          

            //Remove the previous slide content from the input string
            input = input.Skip(j).ToArray();       
        }

        Console.Read();

Upvotes: 1

user117499
user117499

Reputation:

You can measure a string, and determine needed space. Keep in mind the font is a factor so if you use multiple fonts you will need to do multiple calculations.

https://msdn.microsoft.com/en-us/library/6xe5hazb(v=vs.110).aspx

Upvotes: 1

Related Questions