-1

First: I know how to split string by length. Task is not about to split text just by length.


I have a text who comes from three database columns, let's call them data fields:

  1. Company name
  2. company registration number aka VAT
  3. Company address

I need to print this data via cash register on recipe. I have some limitations (set by cash register software/driver):

  • I have 4 fields (4 lines), to print customer info
  • each field/line length is 20 symbols
  • company registration number always is one word, example: AB0123456789

To send customer data to cash register, I must specify file in following format:

1,"row 1","row 2","row 3","row 4",0,0.00

Here is description of format:

  • 1 - Customer number/ID, integer, max 16 numbers
  • row 1/2/3/4 - string, max 20 symbols each, can be empty
  • 0 - discount number
  • 0.00 - customer discount (%)

I must place text from database to four fields with some rules:

  • if possible do not split VAT number

I tried various things to split all text to 4 fields, but not so successful.

There can be case when total data length is more than 80 symbols, in this case user can modify each field.

Maybe someone have some (better) suggestions how to split text... Of course this can be achieved with lot of ifs. But that is ugly.

Example data: input: [MyCompany LTD] [AB0123456789] [Not so long address in country] Output:

MyCompany LTD AB0123456789 Not so long address in country

Example 2: [My investment properties LTD] [AB0123456789] [street 24 mycity 2233 country] output:

My investment proper ties LTD AB0123456789 street 24 mycity 2233 count

If split VAT number, then it is possible to fit all information, but it looks ugly:

My investment proper ties LTD AB012345678 9 street 24 mycity 2233 country

If possible, do not split vat number at all.

My variant:

class ChdCustomer
{
    private List<string> outputLines = new List<string>();
    private bool allFit = true;
    private string tmpLine = "";

    public string Line1()
    {
        if (outputLines.Count >= 1) return outputLines[0]; else return "";
    }

    public string Line2()
    {
        if (outputLines.Count >= 2) return outputLines[1]; else return "";
    }

    public string Line3()
    {
        if (outputLines.Count >= 3) return outputLines[2]; else return "";
    }

    public string Line4()
    {
        if (outputLines.Count >= 4) return outputLines[3]; else return "";
    }

    public ChdCustomer()
    {
    }

    public ChdCustomer(string name, string vat, string address)
    {
        AddNameAndVat(name, vat);
        AddAddress(address);
    }

    public bool FitAll()
    {
        return allFit;
    }

    public void AddAddress(string text)
    {
        if (!allFit)
            return;

        int fc = outputLines.Count * 20;


        if (fc == 60)
        {
            fc -= 20 - outputLines[2].Length;
        }
        if (fc < text.Length || fc > 80)
        {
            allFit = false;
            return;
        }


        fc = (80 - fc) / 20; // free lines

        tmpLine = "";
        string[] k = text.Split(' ');


        foreach (string s in k)
        {
            if ((tmpLine + s).Length <= 20)
            {
                tmpLine += s + " ";
            }
            else
            {
                if (fc > 0)
                    outputLines.Add(tmpLine.Trim());
                tmpLine = s + " ";
                fc--;
            }
        }

        if (!outputLines[outputLines.Count - 1].Contains(tmpLine))
        {
            outputLines.Add(tmpLine);
        }


        if (outputLines.Count > 4)
        {
            allFit = false;
        }
    }

    public void AddNameAndVat(string name, string vat)
    {
        if ((name + vat).Length < 20)
        {
            outputLines.Add(name + " " + vat);
        }
        else
        {
            if (name.Length <= 20)
            {
                outputLines.Add(name);
                outputLines.Add(vat);
            }
            else
            {
                if (name.Length <= 40)
                {
                    string[] k = name.Split(' ');

                    foreach (string s in k)
                    {
                        if ((tmpLine + s).Length <= 20)
                        {
                            tmpLine += s + " ";
                        }
                        else
                        {
                            tmpLine = tmpLine.Trim();

                            string remaining = name.Substring(tmpLine.Length).Trim();
                            if (remaining.Length <= 20)
                            {
                                outputLines.Add(tmpLine);
                                outputLines.Add(remaining);
                                outputLines.Add(vat);
                                break;
                            }
                            else
                            {
                                outputLines.Add(name.Substring(0, 20));
                                outputLines.Add(name.Substring(20));
                                outputLines.Add(vat);
                                break;
                            }
                        }
                    }
                }
                else
                {
                    allFit = false;
                }
            }
        }
    }
}
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
Guntis
  • 496
  • 1
  • 5
  • 19
  • There are many utilities, like [`TextFieldParser`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.visualbasic.fileio.textfieldparser), that already do this. – Dour High Arch Jan 15 '20 at 17:59
  • Create a class for one recipe and put all data into the class. The write an output method that writes all the properties. – jdweng Jan 15 '20 at 17:59
  • Does this answer your question? [Splitting a string / number every Nth Character / Number?](https://stackoverflow.com/questions/4133377/splitting-a-string-number-every-nth-character-number) –  Jan 15 '20 at 18:03
  • @Josh, no. I want a bit smarter "splitter", not just by position. of course it would work, but output is ugly – Guntis Jan 15 '20 at 18:10
  • 2
    Please provide sample input and expected output – Rufus L Jan 15 '20 at 18:12
  • If you want this sort of highly custom behavior where only some words can be split and some cannot then you will need those nasty chain of if statements you mentioned before. .NET doesn't have a built in method for your highly specialized scenario. –  Jan 15 '20 at 18:45
  • Are there always four lines? How are the 4 lines separated? By a blank line? – jdweng Jan 16 '20 at 09:49
  • @jdweng It's four lines. like in document. Line max length is 20 symbols. – Guntis Jan 16 '20 at 17:06
  • What does file look like when there is more than one company is in a file? – jdweng Jan 16 '20 at 17:44
  • When i send data to cash register, i have 4 fields available for customer data: `1,"20 symbols here","20 symbols here","20 symbols here","20 symbols here",0,0.00` this i cannot change. – Guntis Jan 16 '20 at 18:12
  • Some lines have more than 20 characters. Look again at you expected results. – jdweng Jan 17 '20 at 02:02
  • I added a 2nd solution to your code with the way I would write code. – jdweng Jan 17 '20 at 10:32
  • @jdweng Your "Solution 2" should be posted as an answer (with some annotation and/or explanation), not edited into the question. – Adrian Mole Jan 17 '20 at 10:50

1 Answers1

1

Here is my solution :

        static void Main(string[] args)
        {
            string[] inputs = { 
                                "[MyCompany LTD] [AB0123456789] [Not so long address in country]",
                                "[My investment properties LTD] [AB0123456789] [street 24 mycity 2233 country]"

                              };
            foreach (string input in inputs)
            {
                Console.WriteLine("Parsing : '{0}'", input);

                string[] splitArray = input.Split(new char[] { '[', ']' }, StringSplitOptions.RemoveEmptyEntries);
                string remainder = "";
                int index = 0;
                string line = "";
                do
                {
                    if (index < splitArray.Length)
                    {
                        line = remainder + splitArray[index];
                    }
                    else
                    {
                        line = remainder;
                    }
                    remainder = string.Empty;
                    if (line.Trim().Length > 0)
                    {

                        if (line.Length > 20)
                        {
                            remainder = line.Substring(20);
                            line = line.Substring(0, 20);
                        }
                        Console.WriteLine("\t{0}", line);
                    }
                    if (index < splitArray.Length) index++;

                } while ((index <= 4) && ((index < splitArray.Length) || (remainder.Length > 0)));
            }
            Console.ReadLine();
        }
jdweng
  • 33,250
  • 2
  • 15
  • 20