-8

The sequence should go like this.
A-Z,AA-AZ,BA-BZ,CA-CZ,.......,ZA-ZZ
After ZZ it should start from AAA.
Then AAA to ZZZ and then AAAA to ZZZZ and so on.

This sequence is pretty much like that of an Excel sheet.

Edit: Added my code

        private void SequenceGenerator()
    {
        var numAlpha = new Regex("(?<Numeric>[0-9]*)(?<Alpha>[a-zA-Z]*)");
        var match = numAlpha.Match(txtBNo.Text);

        var alpha = match.Groups["Alpha"].Value;
        var num = Convert.ToInt32(match.Groups["Numeric"].Value);
        lastChar = alpha.Substring(alpha.Length - 1);

        if (lastChar=="Z")
        {
            lastChar = "A";
            txtBNo.Text = num.ToString() + "A" + alpha.Substring(0, alpha.Length - 1) + lastChar;
        }

        else
        {
            txtBNo.Text = num.ToString() + alpha.Substring(0, alpha.Length - 1) + Convert.ToChar(Convert.ToInt32(Convert.ToChar(lastChar)) + 1);
        }
    }

This is what I've done. But, I know that is a wrong logic.

Thanks.

  • 1
    Have you tried to work on this at all? – Mike Lawson Mar 12 '15 at 08:17
  • How about you give it a shot and come back if you run into a more specific problem? – cbr Mar 12 '15 at 08:17
  • 1
    You convert the numbers 0...x to base-26 (with the symbols A-Z). Solved :) – xanatos Mar 12 '15 at 08:17
  • possible duplicate of [Quickest way to convert a base 10 number to any base in .NET?](http://stackoverflow.com/questions/923771/quickest-way-to-convert-a-base-10-number-to-any-base-in-net) – weston Mar 12 '15 at 08:29

3 Answers3

8

As I've wrote in the comment, it's a base-conversion problem, where your output is in base-26, with symbols A-Z

static string NumToLetters(int num)
{
    string str = string.Empty;

    // We need to do at least a "round" of division
    // to handle num == 0
    do
    {
        // We have to "prepend" the new digit
        str = (char)('A' + (num % 26)) + str;
        num /= 26;
    }
    while (num != 0);

    return str;
}
xanatos
  • 109,618
  • 12
  • 197
  • 280
2

Lucky for you, I've done this once before. the problems I've encountered is that in the Excel sheet there is no 0, not even in double 'digit' 'numbers'. meaning you start with a (that's 1) and then from z (that's 26) you go straight to aa (27). This is why is't not a simple base conversion problem, and you need some extra code to handle this. Testing the function suggested by xanatos results with the following:

NumToLetters(0) --> A

NumToLetters(25) --> Z

NumToLetters(26) --> BA

My solution has more code but it has been tested against Excel and is fully compatible, except it starts with 0 and not 1, meaning that a is 0, z is 25, aa is 26, zz 701, aaa is 702 and so on). you can change it to start from 1 if you want, it's fairly easy.

private static string mColumnLetters = "zabcdefghijklmnopqrstuvwxyz";

// Convert Column name to 0 based index
public static int ColumnIndexByName(string ColumnName)
    {
        string CurrentLetter;
        int ColumnIndex, LetterValue, ColumnNameLength;
        ColumnIndex = -1; // A is the first column, but for calculation it's number is 1 and not 0. however, Index is alsways zero-based.
        ColumnNameLength = ColumnName.Length;
        for (int i = 0; i < ColumnNameLength; i++)
        {
            CurrentLetter = ColumnName.Substring(i, 1).ToLower();
            LetterValue = mColumnLetters.IndexOf(CurrentLetter);
            ColumnIndex += LetterValue * (int)Math.Pow(26, (ColumnNameLength - (i + 1)));
        }
        return ColumnIndex;
    }

// Convert 0 based index to Column name
public static string ColumnNameByIndex(int ColumnIndex)
    {
        int ModOf26, Subtract;
        StringBuilder NumberInLetters = new StringBuilder();
        ColumnIndex += 1; // A is the first column, but for calculation it's number is 1 and not 0. however, Index is alsways zero-based.
        while (ColumnIndex > 0)
        {
            if (ColumnIndex <= 26)
            {
                ModOf26 = ColumnIndex;
                NumberInLetters.Insert(0, mColumnLetters.Substring(ModOf26, 1));
                ColumnIndex = 0;
            }
            else
            {
                ModOf26 = ColumnIndex % 26;
                Subtract = (ModOf26 == 0) ? 26 : ModOf26;
                ColumnIndex = (ColumnIndex - Subtract) / 26;
                NumberInLetters.Insert(0, mColumnLetters.Substring(ModOf26, 1));
            }
        }
        return NumberInLetters.ToString().ToUpper();
    }
Zohar Peled
  • 79,642
  • 10
  • 69
  • 121
  • Your code works with slight modifications. :) – Gagan Bodduluru Mar 12 '15 at 11:49
  • ColumnIndexByName has trouble with some values Index 676 ColumnName ZA back to Index 0 Index 677 ColumnName ZB back to Index 1 – Doug Ferguson Feb 21 '23 at 19:40
  • @DougFerguson This code is probably 10 years old by now (I know it was posted 8 years ago). If there's a bug, you might be in a better position than me to solve it, since it's a very long time since I last used it. – Zohar Peled Feb 22 '23 at 07:27
1

Try this method:

public static IEnumerable<string> GenerateItems()
{
    var buffer = new[] { '@' };
    var maxIdx = 0;
    while(true)
    {
        var i = maxIdx;
        while (true)
        {
            if (buffer[i] < 'Z')
            {
                buffer[i]++;
                break;
            }

            if (i == 0)
            {
                buffer = Enumerable.Range(0, ++maxIdx + 1).Select(c => 'A').ToArray();
                break;
            }

            buffer[i] = 'A';
            i--;
        }

        yield return new string(buffer);
    }
    // ReSharper disable once FunctionNeverReturns
}

This is infinite generator of alphabetical sequence you need, you must restrict count of items like this:

var sequence = GenerateItems().Take(10000).ToArray();

Do not call it like this (it cause infinite loop):

foreach (var i in GenerateItems())
    Console.WriteLine(i);
rtf_leg
  • 1,789
  • 1
  • 15
  • 27
  • This is a nice solution, but you need to only use the value of the last cell. – Zohar Peled Mar 12 '15 at 09:48
  • "but you need to only use the value of the last cell" - I think I don't understand you, can you explain? – rtf_leg Mar 12 '15 at 10:00
  • try running your solution. you will get an array of string containing all the values between A to the desired value. so if you run it like this var sequence = GenerateItems().Take(4).ToArray(); you will get an array like this: {"A", "B", "C", "D"}. – Zohar Peled Mar 12 '15 at 11:00
  • Yes, of course, it is required in question, isn't it? I can add some skip logic to implement startFrom functionality. – rtf_leg Mar 12 '15 at 11:06
  • Maybe you are correct and I've missed it. I've suggested a way to translate a single number to it's string representation and back, but perhaps I misunderstood the question. – Zohar Peled Mar 12 '15 at 11:08
  • Yes, it is, but I will implement startFrom logic anyway - it would be more usable solution :-) – rtf_leg Mar 12 '15 at 11:16