65.9K
CodeProject 正在变化。 阅读更多。
Home

带字母计数扩展

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.17/5 (3投票s)

2011年6月22日

CPOL

2分钟阅读

viewsIcon

20652

downloadIcon

295

一对围绕 Zeltera 的“带字母计数”代码的包装器,用于生成“整数到 Excel 列”和“Excel 列到整数”。

引言

如果您需要像 Excel 那样按字母计数列,请查看 Zeltera 的 "使用字母计数"。
他的例程可以扩展为将整数转换为 Excel 列,或将 Excel 列转换为整数。很久以前,我编写了两个非常简单、效率低的循环包装器,围绕 Zeltera 的核心代码来完成这项工作。在这里,我提供了一种计算结果的方法,以将循环次数减少到不超过 26 次。

背景

Zeltera 的例程很好地从 "a" 计数到 "z",然后跳到 "aa" 到 "xdf"(Excel 的最大值)。由于我只想“完成这项工作”,所以我编写了以下小包装器。(此处已最小化)。这些循环只是从 "a" 到任何字母。计算机速度很快,我不需要处理大量的列,因此计算时间并不重要。(我相信你也写过你知道效率很低的代码。)

string IntToExcelColumn(int value)
    string str = "a";
    for (int inx = 1; inx < value; inx++) { str = GetNext(str); }
    return str;

int ExcelColumnToInt(string column)
    for (int inx = 1; inx < 16384; inx++)
    {
        string str = IntToExcelColumn(inx).ToLower();
        if (String.Compare(col, str) == 0) { return inx; }
    }

代码讨论

Excel 将列数限制为 XDF,即 16384 列。显然,使用单个字母,可以从 1 到 26,列 A 到 Z。因此,可以推断出要到达 AA,需要经过 26 两次。因此,由于 G 是字母表中的第 7 个字母,AG 的计算结果为 (26 * 2) + 7 = 59。按照这个推理,AAA 的数值必须是 676 (26 x 26 = 676)。然后,你只需要进行推广即可。

我提出了这些规则(示例: "G", "GG", "GGG")来获得一个整数

1)  For one alpha: The numeric value within the alphabet.
    Thus:  (G = 7)

2)  For two alphas: the numeric value of the most significant times 26 
    plus the numeric value of the lest significant.
    Thus:  (G# = 26 x 7 = 182) + (#G = 7) = 189

3)  For three alphas: the numeric value of the most significant time 676 
    plus 26 times the next most significant plus the numeric value of the lest significant.
    Thus (G## = 676 x 7 = 4732) + (#G# = 182) + (##G = 7) = 4921

4)  No further as Excel is limited to three alphas (XFD, 16384).

这些也可以用来生成字母列。如果将结果除以 676,则得到最高位字母的值,然后将余数除以 26,则得到下一位字母的值;剩下的就是最低位字母。

代码

const int MAXINT = 16384;
const int TWOALPHAS = 26;
const int THREEALPHAS = 676;

// Input must be greater than 0 and less than or equal to 16384
// On error: returns an empty string
public string IntToExcelColumn(int value)
{
    // Excel is limited to the integer 16384, XFD
    if ((value < 1) || (value > MAXINT)) return String.Empty;

    // Discussion on converting from a column to an integer:
    //1) For one alpha: The numeric value within the alphabet
    //    Thus:  G = 7
    //2) For two alphas: the numeric value of the most significant times 26 plus
    //   the numeric value of the lest significant.
    //    Thus:  (G = 26 x 7 = 182) + (G = 7) = 189
    //3) For three alphas: the numeric value of the most significant time 676 plus
    //   26 times the next most significant plus the numeric value of the lest significant
    //    Thus (G## = 676 x 7 = 4732) + (#G# = 182) + (##G = 7) = 4921
    //4) No further as Excel is limited to three alphas (XFD, 16384).

    // Discussion on converting from an integer to a column
    // The numbers above apply.  If one divides by 676, one gets the value of the third alpha
    // Then the remainder by 26 one gets the value of the second alpha; and what is
    // left over is the final alpha.

    int remainder = value;
    int[] aryInt = new int[3];
    string[] aryStr = new string[3];
  
    if (remainder > THREEALPHAS)
    {
        aryInt[2] = remainder / THREEALPHAS;
        remainder = remainder % THREEALPHAS;
        aryStr[2] = CountUpToValue(aryInt[2]);

        aryInt[1] = remainder / TWOALPHAS;
        remainder = remainder % TWOALPHAS;
        aryStr[1] = CountUpToValue(aryInt[1]);
    }
    else if (value > TWOALPHAS)
    {
        aryInt[1] = remainder / TWOALPHAS;
        remainder = remainder % TWOALPHAS;
        aryStr[1] = CountUpToValue(aryInt[1]);
    }
    aryInt[0] = remainder;
    aryStr[0] = CountUpToValue(aryInt[0]);

    string rtn = aryStr[2] + aryStr[1] + aryStr[0];
    return rtn.ToUpper();
}

//--------------------------------------------------------------
// Computes the excel column integer
// Input is limited to one three alphas with the maximum "XDF"
// On error: returns 0
public int ExcelColumnToInt(string column)
{
    // Discussion:
    // 1) For one alpha: The numeric value within the alphabet
    //      Thus:  G = 7
    // 2) For two alphas: the numeric value of the most significant times 26 plus
    //    the numeric value of the lest significant.
    //      Thus:  (G = 26 x 7 = 182) + (G = 7) = 189
    // 3) For three alphas: the numeric value of the most significant time 676 plus
    //    26 times the next most significant plus the numeric value of the lest significant
    //      Thus (G## = 676 x 7 = 4732) + (#G# = 182) + (##G = 7) = 4921
    // 4) No further as Excel is limited to three alphas (XFD, 16384).

    string col = column.ToLower();

    // Verify a valid input
    if (col.Length > 3) return 0;

    int[] aryInt = new int[3];
    int[] aryCalc = new int[3];
    for (int inx = 0; inx < col.Length; inx++)
    {
        aryInt[inx] = CountToAlpha(col.Substring(inx, 1));
        if (aryInt[inx] == 0) return 0;

        if (col.Length == 1)
        {
            aryCalc[inx] = aryInt[inx];
            if (aryInt[inx] == 0) return 0;
        }
        else if (col.Length == 2)
        {
            switch (inx)
            {
                case 0: aryCalc[inx] = aryInt[inx] * TWOALPHAS; break;
                case 1: aryCalc[inx] = aryInt[inx]; break;
            }
        }
        else
        {
            switch (inx)
            {
                case 0: aryCalc[inx] = aryInt[inx] * THREEALPHAS; break;
                case 1: aryCalc[inx] = aryInt[inx] * TWOALPHAS; break;
                case 2: aryCalc[inx] = aryInt[inx]; break;
            }
        }
    }

    int rtn = aryCalc[0] + aryCalc[1] + aryCalc[2];
    if (rtn > MAXINT) return 0;
    return rtn;
}

你需要这两个小包装器

//--------------------------------------------------------------
// For internal call to verify valid input
// Expect lower case input
// Feed values 1 through 26 (a-z) 
private string CountUpToValue(int value)
{
    string str = "a";
    if (value == 1) return str;

    for (int inx = 1; inx < value; inx++)
    {
        str = GetNext(str);
    }
    return str;
}
    
//--------------------------------------------------------------
// For internal call to verify valid input
// Expect lower case input
// Feed only one apha letter "a" through "z"
private int CountToAlpha(string column)
{
    string str;
    for (int inx = 1; inx < (MAXINT + 1); inx++)
    {
        str = CountUpToValue(inx);
        if (String.Compare(column, str) == 0)
        {
            return inx;
        }
    }
    return 0;
}

最后,你需要 Zeltera 的这段代码

// From Code Project: "Count with letters" by Zeltera 17 Jun 2007 
private String GetNext(String currentString)
{
    currentString = currentString.ToLower();
    if (currentString.Length == 0)
        return "a";

    Char lastCharacter = currentString[currentString.Length - 1];
    String subString = currentString.Substring(0, currentString.Length - 1);

    if (lastCharacter == 'z')
        return GetNext(subString) + 'a';
    else
        return subString + (char)((int)lastCharacter + 1);
}

关注点

由于从效率低的循环到少量计算,处理速度得到了极大的提高,从...

public string IntToExcelColumn(int value)

...和...

public int ExcelColumnToInt(string column)

...到编写使用它们的附加范围型包装器,就很容易了

public List<string> IntToExcelColumnsList(string start, int count)
public List<string> IntToExcelColumnsList(int first, int count)
public List<string> ColumnToExcelColumnList(string start, int count)
public List<string> ColumnToExcelColumnList(int start, int end)
public List<string> ColumnToExcelColumnList(string start, string end)

如果您需要它们,请下载 ExcelUtils 库的源代码。其中还有其他东西。我不保证其他代码。请在使用前对其进行测试,因为我很久没有使用过它了。

历史

  • 2011年6月21日:初始版本
© . All rights reserved.