Fastest function to generate Excel column letters in C#

前端 未结 21 1738
无人共我
无人共我 2020-11-29 02:30

What is the fastest c# function that takes and int and returns a string containing a letter or letters for use in an Excel function? For example, 1 returns \"A\", 26 return

相关标签:
21条回答
  • 2020-11-29 02:52

    It is recursive. Fast, and right :

    class ToolSheet
    {
    
    
        //Not the prettyest but surely the fastest :
        static string[] ColName = new string[676];
    
    
        public ToolSheet()
        {
            ColName[0] = "A";
            for (int index = 1; index < 676; ++index) Recurse(index, index);
    
        }
    
        private int Recurse(int i, int index)
        {
            if (i < 1) return 0;
            ColName[index] = ((char)(65 + i % 26)).ToString() + ColName[index];
    
            return Recurse(i / 26, index);
        }
    
        public string GetColName(int i)
        {
            return ColName[i - 1];
        }
    
    
    
    }
    
    0 讨论(0)
  • 2020-11-29 02:53
    private String columnLetter(int column) {
        if (column <= 0) 
            return "";
        if (column <= 26){
            return (char) (column + 64) + "";
        }
    
        if (column%26 == 0){
            return columnLetter((column/26)-1) + columnLetter(26) ;        
        }
    
        return columnLetter(column/26) + columnLetter(column%26) ;        
    }
    
    0 讨论(0)
  • 2020-11-29 03:01

    Caching really does cut the runtime of 10,000,000 random calls to 1/3 its value though:

        static Dictionary<int, string> LetterDict = new Dictionary<int, string>(676);
        public static string LetterWithCaching(int index)
        {
            int intCol = index - 1;
            if (LetterDict.ContainsKey(intCol)) return LetterDict[intCol];
            int intFirstLetter = ((intCol) / 676) + 64;
            int intSecondLetter = ((intCol % 676) / 26) + 64;
            int intThirdLetter = (intCol % 26) + 65;
            char FirstLetter = (intFirstLetter > 64) ? (char)intFirstLetter : ' ';
            char SecondLetter = (intSecondLetter > 64) ? (char)intSecondLetter : ' ';
            char ThirdLetter = (char)intThirdLetter;
            String s = string.Concat(FirstLetter, SecondLetter, ThirdLetter).Trim();
            LetterDict.Add(intCol, s);
            return s;
        }
    

    I think caching in the worst-case (hit every value) couldn't take up more than 250kb (17576 possible values * (sizeof(int)=4 + sizeof(char)*3 + string overhead=2)

    0 讨论(0)
  • 2020-11-29 03:02

    You could pre-generate all the values into an array of strings. This would take very little memory and could be calculated on the first call.

    0 讨论(0)
  • 2020-11-29 03:04

    Here is a concise implementation using LINQ.

    static IEnumerable<string> GetExcelStrings()
    {
        string[] alphabet = { string.Empty, "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" };
    
        return from c1 in alphabet
               from c2 in alphabet
               from c3 in alphabet.Skip(1)                    // c3 is never empty
               where c1 == string.Empty || c2 != string.Empty // only allow c2 to be empty if c1 is also empty
               select c1 + c2 + c3;
    }
    

    This generates A to Z, then AA to ZZ, then AAA to ZZZ.

    On my PC, calling GetExcelStrings().ToArray() takes about 30 ms. Thereafter, you can refer to this array of strings if you need it thousands of times.

    0 讨论(0)
  • 2020-11-29 03:04

    @Neil N -- nice code I think the thirdLetter should have a +64 rather than +65 ? am I right?

    public string Letter(int intCol) {
    
        int intFirstLetter = ((intCol) / 676) + 64;
        int intSecondLetter = ((intCol % 676) / 26) + 64;
        int intThirdLetter = (intCol % 26) + 65;  ' SHOULD BE + 64?
    
        char FirstLetter = (intFirstLetter > 64) ? (char)intFirstLetter : ' ';
        char SecondLetter = (intSecondLetter > 64) ? (char)intSecondLetter : ' ';
        char ThirdLetter = (char)intThirdLetter;
    
        return string.Concat(FirstLetter, SecondLetter, ThirdLetter).Trim();
    }
    
    0 讨论(0)
提交回复
热议问题