列番号(127など)をExcel列(AAなど)に変換する方法


474

Excelから直接値を取得するオートメーションを使用せずに、C#で数値をExcelの列名に変換する方法

Excel 2007には、1から16384までの可能な範囲があります。これは、Excel 2007がサポートする列の数です。結果の値は、A、AA、AAAなどのExcel列名の形式にする必要があります。


1
使用可能な列の数に制限があることを忘れないでください。例* Excel 2003(v11)は、IV、2 ^ 8、または256カラムまで増加します)。* Excel 2007(v12)は、XFD、2 ^ 14または16384カラムまで対応しています。
スライスされていない


この質問にはC#とExcelのタグが付いています。私たちは2016年に住んでいてEPPLUSがあるので、私はこの質問を古いものとしてフラグを立てます。サーバーで高度なExcelスプレッドシートを作成するために一般的に使用されるC#ライブラリ。これは、GNU Library General Public License(LGPL)の下で利用可能になります。EPPlusを使用すると、列文字列を簡単に取得できます。
Tony_KiloPapaMikeGolf 2016

行と列の制限は、Excelのバージョンよりもファイル形式に依存し、ブックご​​とに異なる可能性があることに注意してください。同じブックでも、古い形式または新しい形式で保存されている場合は変更できます。
Slai

回答:


901

ここに私がそれをする方法があります:

private string GetExcelColumnName(int columnNumber)
{
    int dividend = columnNumber;
    string columnName = String.Empty;
    int modulo;

    while (dividend > 0)
    {
        modulo = (dividend - 1) % 26;
        columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
        dividend = (int)((dividend - modulo) / 26);
    } 

    return columnName;
}

64
このコードはうまく機能します。列AがcolumnNumber 1であると想定しています。列AをcolumnNumber 0として使用するシステムを説明するために、簡単な変更を加える必要がありました。キース
キース・サーモンズ2009

14
@Jduvはを使用して試してみましたStringBuilder。約2倍かかります。これは非常に短い文字列(最大3文字-Excel 2010は列XFDまで)なので、最大2つの文字列連結です。(私は、整数1から16384への変換を100回繰り返しました。つまり、Excelの列AをXFDに変換してテストしました)。
グラハム、

18
理解を深めるために、65を「A」に置き換えます
Stef Heyenrath

11
65の代わりに 'A'を使用する方が良いと思います。そして、26は( 'Z'-'A' + 1)として評価できます。例:const int AlphabetLength = 'Z'-'A' + 1;
Denis Gladkiy 2013年

5
私はゲームに遅れましたが、コードは最適とはほど遠いです。特に、キャストを使用してmodulo呼び出しToString()、適用する必要はありません(int)。C#の世界では、ほとんどの場合、0から番号付けを開始することを考慮して、これが私のリビジョンです:<!-言語:c#-> public static string GetColumnName(int index)//ゼロベース{const byte BASE = 'Z '-' A '+ 1; 文字列名= String.Empty; do {name = Convert.ToChar( 'A' + index%BASE)+ name; インデックス=インデックス/ BASE-1; } while(index> = 0); 名前を返す; }
Herman Kan

63

誰かがVBAなしでExcelでこれを行う必要がある場合、ここに方法があります:

=SUBSTITUTE(ADDRESS(1;colNum;4);"1";"")

ここで、colNumは列番号です

そしてVBAでは:

Function GetColumnName(colNum As Integer) As String
    Dim d As Integer
    Dim m As Integer
    Dim name As String
    d = colNum
    name = ""
    Do While (d > 0)
        m = (d - 1) Mod 26
        name = Chr(65 + m) + name
        d = Int((d - m) / 26)
    Loop
    GetColumnName = name
End Function

2
例:= SUBSTITUTE(TEXT(ADDRESS(1,1000,4)、 "")、 "1"、 "")
Dolph

はい、次のロケールでExcelを使用しています。Excelで関数の引数を区切るために、の代わりに使用されます。これを指摘してくれてありがとう。
vzczc 2010年

2
TEXT関数なしでこれを行いました。TEXT関数の目的は何ですか?
dayuloli 2014年

2
@dayuloliこの回答が書かれてから長い間、正解です。TEXT関数はここでは目的を果たしません。答えを更新します。
vzczc 14年

21

これはC#ではなくPythonですが、少なくとも結果は正しいです。

def ColIdxToXlName(idx):
    if idx < 1:
        raise ValueError("Index is too small")
    result = ""
    while True:
        if idx > 26:
            idx, r = divmod(idx - 1, 26)
            result = chr(r + ord('A')) + result
        else:
            return chr(idx + ord('A') - 1) + result


for i in xrange(1, 1024):
    print "%4d : %s" % (i, ColIdxToXlName(i))

はい、私はdownVotedしました。質問がC#の場合はPythonを投稿しないでください。そして、はい、もっと多くの人がこれを行うべきです。
KyloRen

1
質問のタイトルはC#を意味するものではないため、C#を無視しない多くの人々がここに来る可能性があります。したがって、Pythonで共有していただきありがとうございます。
Tim-Erwin

20

たとえば、AAZのようなExcelの列アドレスから整数への変換と、任意の整数からExcelへの変換の両方が必要になる場合があります。以下の2つのメソッドは、まさにそれを行います。1ベースのインデックス付けを想定し、「配列」の最初の要素は要素番号1です。ここではサイズに制限がないため、ERRORなどのアドレスを使用でき、列番号2613824 ...

public static string ColumnAdress(int col)
{
  if (col <= 26) { 
    return Convert.ToChar(col + 64).ToString();
  }
  int div = col / 26;
  int mod = col % 26;
  if (mod == 0) {mod = 26;div--;}
  return ColumnAdress(div) + ColumnAdress(mod);
}

public static int ColumnNumber(string colAdress)
{
  int[] digits = new int[colAdress.Length];
  for (int i = 0; i < colAdress.Length; ++i)
  {
    digits[i] = Convert.ToInt32(colAdress[i]) - 64;
  }
  int mul=1;int res=0;
  for (int pos = digits.Length - 1; pos >= 0; --pos)
  {
    res += digits[pos] * mul;
    mul *= 26;
  }
  return res;
}

13

最初の投稿でエラーを発見したので、座って計算することにしました。私が見つけたのは、別の人が投稿したように、Excelの列を識別するために使用される数体系が基数26の体系ではないことです。基数10で次のことを検討してください。これは、アルファベットの文字でも行うことができます。

スペース:................................... S1、S2、S3:S1、S2、S3
............ ........................ 0、00、000:.. A、AA、AAA
............. ................................. 1、01、001:.. B、AB、AAB
.............. ......................…、…、…:..…、…、…
............... .....................
9、99、999 :.. Z、ZZ、ZZZ 空間内の合計状態:10、100、1000:26、676、17576
総州:............... 1110 ................ 18278

Excelは、基数26を使用して、個々のアルファベット空間の列に番号を付けます。一般に、状態空間の進行はa、a ^ 2、a ^ 3、…で、一部の基数aであり、状態の総数はa + aです。 ^ 2 + a ^ 3 +…。

最初のN個のスペースでステートAの総数を求めたいとします。そのための式は、A =(a)(a ^ N-1)/(a-1)です。インデックスKに対応するスペースNを見つける必要があるため、これは重要です。Kが数体系のどこにあるかを知りたい場合は、AをKに置き換えてNを解く必要があります。解はN = log {ベースa}(A(a-1)/ a +1)。a = 10とK = 192の例を使用すると、N = 2.23804…であることがわかります。これは、Kが2より少し大きいため、3番目のスペースの先頭にあることを示しています。

次のステップは、現在の空間内の正確な距離を見つけることです。これを見つけるには、Nのフロアを使用して生成されたAをKから減算します。この例では、Nのフロアは2です。したがって、A =(10)(10 ^ 2 – 1)/(10-1)= 110です。これは、最初の2つのスペースの状態を組み合わせると予想されるとおりです。これらの最初の110の状態は最初の2つのスペースですでに説明されているため、これをKから差し引く必要があります。これにより、82の州が残ります。したがって、この数体系では、基数10の192の表現は082です。

ゼロのベースインデックスを使用するC#コードは

    private string ExcelColumnIndexToName(int Index)
    {
        string range = string.Empty;
        if (Index < 0 ) return range;
        int a = 26;
        int x = (int)Math.Floor(Math.Log((Index) * (a - 1) / a + 1, a));
        Index -= (int)(Math.Pow(a, x) - 1) * a / (a - 1);
        for (int i = x+1; Index + i > 0; i--)
        {
            range = ((char)(65 + Index % a)).ToString() + range;
            Index /= a;
        }
        return range;
    }

//古い投稿

C#のゼロベースのソリューション。

    private string ExcelColumnIndexToName(int Index)
    {
        string range = "";
        if (Index < 0 ) return range;
        for(int i=1;Index + i > 0;i=0)
        {
            range = ((char)(65 + Index % 26)).ToString() + range;
            Index /= 26;
        }
        if (range.Length > 1) range = ((char)((int)range[0] - 1)).ToString() + range.Substring(1);
        return range;
    }

ああ、理由はわかりませんが、このソリューションが好きです。ロジックを上手に使用するだけで豪華なものはありません。ただし、C#で空の文字列をstring range = string.Emptyとして指定することをお勧めします。
匿名タイプ

はい、とても良い説明です。しかし、それもベース27ではないとだけ言ってもいいですか?あなたの説明は、研究されたときにこれを示していますが、上部に簡単に言及することで、他の数人の人をある程度救うことができます。
マリウス

10
int nCol = 127;
string sChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string sCol = "";
while (nCol >= 26)
{
    int nChar = nCol % 26;
    nCol = (nCol - nChar) / 26;
    // You could do some trick with using nChar as offset from 'A', but I am lazy to do it right now.
    sCol = sChars[nChar] + sCol;
}
sCol = sChars[nCol] + sCol;

アップデートピーターのコメントは正しい。これが、ブラウザでコードを書くことで得られるものです。:-)私の解決策はコンパイルされていませんでした、それは左端の文字が欠けていて、文字列を逆の順序で構築していました-すべて修正されました。

バグはさておき、アルゴリズムは基本的に数値を10進数から26進数に変換しています。

Update 2Joel Coehoorn正解です。上記のコードは27に対してABを返します。それが26の実数の場合、AAはAに等しく、Zの後の次の番号はBAになります。

int nCol = 127;
string sChars = "0ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string sCol = "";
while (nCol > 26)
{
    int nChar = nCol % 26;
    if (nChar == 0)
        nChar = 26;
    nCol = (nCol - nChar) / 26;
    sCol = sChars[nChar] + sCol;
}
if (nCol != 0)
    sCol = sChars[nCol] + sCol;

コードはコンパイルされません(sColが初期化されていません)。もしそうなら、それは正しい答えを与えません。
ピーター

5
この答えは間違っています。Base26では十分ではありません。ZからAAにラップするとどうなるかを考えます。Aが0桁に相当する場合、それは、それが1桁の場合は、それは9から11のラッピングのようなものだ9から00にwrapingようなものだ
ジョエルCoehoorn

4
更新後、はっきりしません...どちらのアルゴリズムが正しくなりましたか?もしそうなら、どちらが2番目ですか?私はこれを編集して、後世のためにそれを明らかにします...
JoeCool 2009

10

再帰で簡単です。

public static string GetStandardExcelColumnName(int columnNumberOneBased)
{
  int baseValue = Convert.ToInt32('A');
  int columnNumberZeroBased = columnNumberOneBased - 1;

  string ret = "";

  if (columnNumberOneBased > 26)
  {
    ret = GetStandardExcelColumnName(columnNumberZeroBased / 26) ;
  }

  return ret + Convert.ToChar(baseValue + (columnNumberZeroBased % 26) );
}

1
..またはループ。ここで再帰を使用する本当の理由はありません。
Blorgbeardは、

1
26だけではないので、再帰的なソリューションははるかに単純です。
Joel Coehoorn、2008年

このルーチンは実際には機能しません。たとえば、GetStandardExcelColumnName(26)は@ GetStandardExcelColumnName(52)がB @を返します
sgmoore

1
「最も単純な」ソリューションとは対照的に、最も明確なものが最善です。
匿名タイプ

9

ここでのすべての答えは必要以上に複雑に思われるため、再帰を使用して単純な2行のC#実装を投入するだけです。

/// <summary>
/// Gets the column letter(s) corresponding to the given column number.
/// </summary>
/// <param name="column">The one-based column index. Must be greater than zero.</param>
/// <returns>The desired column letter, or an empty string if the column number was invalid.</returns>
public static string GetColumnLetter(int column) {
    if (column < 1) return String.Empty;
    return GetColumnLetter((column - 1) / 26) + (char)('A' + (column - 1) % 26);
}

8

..そしてphpに変換されます:

function GetExcelColumnName($columnNumber) {
    $columnName = '';
    while ($columnNumber > 0) {
        $modulo = ($columnNumber - 1) % 26;
        $columnName = chr(65 + $modulo) . $columnName;
        $columnNumber = (int)(($columnNumber - $modulo) / 26);
    }
    return $columnName;
}

利用ord('A')代わりに65の
Mulli

8

これまでのすべてのソリューションに反復または再帰が含まれていることに驚いています。

これは、一定の時間で実行される(ループなし)ソリューションです。このソリューションは、考えられるすべてのExcel列で機能し、入力をExcel列に変換できることを確認します。可能な列は、[A、XFD]または[1、16384]の範囲です。(これはExcelのバージョンによって異なります)

private static string Turn(uint col)
{
    if (col < 1 || col > 16384) //Excel columns are one-based (one = 'A')
        throw new ArgumentException("col must be >= 1 and <= 16384");

    if (col <= 26) //one character
        return ((char)(col + 'A' - 1)).ToString();

    else if (col <= 702) //two characters
    {
        char firstChar = (char)((int)((col - 1) / 26) + 'A' - 1);
        char secondChar = (char)(col % 26 + 'A' - 1);

        if (secondChar == '@') //Excel is one-based, but modulo operations are zero-based
            secondChar = 'Z'; //convert one-based to zero-based

        return string.Format("{0}{1}", firstChar, secondChar);
    }

    else //three characters
    {
        char firstChar = (char)((int)((col - 1) / 702) + 'A' - 1);
        char secondChar = (char)((col - 1) / 26 % 26 + 'A' - 1);
        char thirdChar = (char)(col % 26 + 'A' - 1);

        if (thirdChar == '@') //Excel is one-based, but modulo operations are zero-based
            thirdChar = 'Z'; //convert one-based to zero-based

        return string.Format("{0}{1}{2}", firstChar, secondChar, thirdChar);
    }
}

2
参考:@Grahamの回答(およびおそらく他の回答)は、あなたの回答よりも一般的です。これらは、列名で4文字以上をサポートしています。そして、それがまさに彼らが反復的である理由です。
バーナードパウルス2013

実際、intsではなく無制限の整数を使用した場合、結果の列名は任意に長くなる可能性があります(たとえば、pythonの回答の場合)
bernard paulus

1
私のデータが16,384列のスプレッドシートに対して大きすぎる場合、私は頭を撃ちます。とにかく、Excelは可能な3文字の列すべてをサポートしていません(XFDで切り捨てられ、1,894列が残ります)。とにかく今。必要に応じて、今後回答を更新します。
user2023861 2013

:)それを知らなかった!私のコメントは、さまざまなアルゴリズムの理論的特性に関するものでした。
バーナードパウルス2013

これはおそらく最も簡単で明確な解決策です。
フアン

8

この答えはjavaScriptにあります:

function getCharFromNumber(columnNumber){
    var dividend = columnNumber;
    var columnName = "";
    var modulo;

    while (dividend > 0)
    {
        modulo = (dividend - 1) % 26;
        columnName = String.fromCharCode(65 + modulo).toString() + columnName;
        dividend = parseInt((dividend - modulo) / 26);
    } 
    return  columnName;
}

6

Javaでの同じ実装

public String getExcelColumnName (int columnNumber) 
    {     
        int dividend = columnNumber;   
        int i;
        String columnName = "";     
        int modulo;     
        while (dividend > 0)     
        {        
            modulo = (dividend - 1) % 26;         
            i = 65 + modulo;
            columnName = new Character((char)i).toString() + columnName;        
            dividend = (int)((dividend - modulo) / 26);    
        }       
        return columnName; 
    }  

5

ここで提供されているすべてのバージョンを確認した後、再帰を使用して自分で実行することを決定しました。

これが私のvb.netバージョンです:

Function CL(ByVal x As Integer) As String
    If x >= 1 And x <= 26 Then
        CL = Chr(x + 64)
    Else
        CL = CL((x - x Mod 26) / 26) & Chr((x Mod 26) + 1 + 64)
    End If
End Function

5

ゲームには少し遅れますが、私が使用するコードは次のとおりです(C#で):

private static readonly string _Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static int ColumnNameParse(string value)
{
    // assumes value.Length is [1,3]
    // assumes value is uppercase
    var digits = value.PadLeft(3).Select(x => _Alphabet.IndexOf(x));
    return digits.Aggregate(0, (current, index) => (current * 26) + (index + 1));
}

2
あなたは尋ねられたものの逆を行いましたが、あなたのラムダフーのために+1しました。
ヌレティン

IndexOfかなり遅いので、逆マッピングを事前に計算しておくとよいでしょう。
ウラッド

5

colインデックスとcol Labelを相互運用するために、使用している静的クラスを投入したいと思いました。ColumnLabelメソッドに変更された承認済みの回答を使用します

public static class Extensions
{
    public static string ColumnLabel(this int col)
    {
        var dividend = col;
        var columnLabel = string.Empty;
        int modulo;

        while (dividend > 0)
        {
            modulo = (dividend - 1) % 26;
            columnLabel = Convert.ToChar(65 + modulo).ToString() + columnLabel;
            dividend = (int)((dividend - modulo) / 26);
        } 

        return columnLabel;
    }
    public static int ColumnIndex(this string colLabel)
    {
        // "AD" (1 * 26^1) + (4 * 26^0) ...
        var colIndex = 0;
        for(int ind = 0, pow = colLabel.Count()-1; ind < colLabel.Count(); ++ind, --pow)
        {
            var cVal = Convert.ToInt32(colLabel[ind]) - 64; //col A is index 1
            colIndex += cVal * ((int)Math.Pow(26, pow));
        }
        return colIndex;
    }
}

このように使用してください...

30.ColumnLabel(); // "AD"
"AD".ColumnIndex(); // 30

4

コードなしのセルの数式に必要な場合は、次の数式を使用します。

IF(COLUMN()>=26,CHAR(ROUND(COLUMN()/26,1)+64)&CHAR(MOD(COLUMN(),26)+64),CHAR(COLUMN()+64))

4

Delphi(パスカル)の場合:

function GetExcelColumnName(columnNumber: integer): string;
var
  dividend, modulo: integer;
begin
  Result := '';
  dividend := columnNumber;
  while dividend > 0 do begin
    modulo := (dividend - 1) mod 26;
    Result := Chr(65 + modulo) + Result;
    dividend := (dividend - modulo) div 26;
  end;
end;

3
private String getColumn(int c) {
    String s = "";
    do {
        s = (char)('A' + (c % 26)) + s;
        c /= 26;
    } while (c-- > 0);
    return s;
}

厳密に26を底とするのではなく、システムに0はありません。ある場合、「Z」の後に「AA」ではなく「BA」が続きます。


3

perlでは、1(A)、27(AA)などの入力の場合

sub excel_colname {
  my ($idx) = @_;       # one-based column number
  --$idx;               # zero-based column index
  my $name = "";
  while ($idx >= 0) {
    $name .= chr(ord("A") + ($idx % 26));
    $idx   = int($idx / 26) - 1;
  }
  return scalar reverse $name;
}

2

元のソリューションを洗練する(C#で):

public static class ExcelHelper
{
    private static Dictionary<UInt16, String> l_DictionaryOfColumns;

    public static ExcelHelper() {
        l_DictionaryOfColumns = new Dictionary<ushort, string>(256);
    }

    public static String GetExcelColumnName(UInt16 l_Column)
    {
        UInt16 l_ColumnCopy = l_Column;
        String l_Chars = "0ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        String l_rVal = "";
        UInt16 l_Char;


        if (l_DictionaryOfColumns.ContainsKey(l_Column) == true)
        {
            l_rVal = l_DictionaryOfColumns[l_Column];
        }
        else
        {
            while (l_ColumnCopy > 26)
            {
                l_Char = l_ColumnCopy % 26;
                if (l_Char == 0)
                    l_Char = 26;

                l_ColumnCopy = (l_ColumnCopy - l_Char) / 26;
                l_rVal = l_Chars[l_Char] + l_rVal;
            }
            if (l_ColumnCopy != 0)
                l_rVal = l_Chars[l_ColumnCopy] + l_rVal;

            l_DictionaryOfColumns.ContainsKey(l_Column) = l_rVal;
        }

        return l_rVal;
    }
}

2

これはActionscriptバージョンです:

private var columnNumbers:Array = ['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'];

    private function getExcelColumnName(columnNumber:int) : String{
        var dividend:int = columnNumber;
        var columnName:String = "";
        var modulo:int;

        while (dividend > 0)
        {
            modulo = (dividend - 1) % 26;
            columnName = columnNumbers[modulo] + columnName;
            dividend = int((dividend - modulo) / 26);
        } 

        return columnName;
    }

2

JavaScriptソリューション

/**
 * Calculate the column letter abbreviation from a 1 based index
 * @param {Number} value
 * @returns {string}
 */
getColumnFromIndex = function (value) {
    var base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
    var remainder, result = "";
    do {
        remainder = value % 26;
        result = base[(remainder || 26) - 1] + result;
        value = Math.floor(value / 26);
    } while (value > 0);
    return result;
};

1
インデックス26と27を試してください。非常に近いですが、1つずれています。
エリック

値= Math.floor(値/ 26); value = Math.ceil(value / 26)-1である必要があります。
Henry Liu

2

これらの私のコードは、特定の数値(インデックスは1から始まります)をExcelの列に変換します。

    public static string NumberToExcelColumn(uint number)
    {
        uint originalNumber = number;

        uint numChars = 1;
        while (Math.Pow(26, numChars) < number)
        {
            numChars++;

            if (Math.Pow(26, numChars) + 26 >= number)
            {
                break;
            }               
        }

        string toRet = "";
        uint lastValue = 0;

        do
        {
            number -= lastValue;

            double powerVal = Math.Pow(26, numChars - 1);
            byte thisCharIdx = (byte)Math.Truncate((columnNumber - 1) / powerVal);
            lastValue = (int)powerVal * thisCharIdx;

            if (numChars - 2 >= 0)
            {
                double powerVal_next = Math.Pow(26, numChars - 2);
                byte thisCharIdx_next = (byte)Math.Truncate((columnNumber - lastValue - 1) / powerVal_next);
                int lastValue_next = (int)Math.Pow(26, numChars - 2) * thisCharIdx_next;

                if (thisCharIdx_next == 0 && lastValue_next == 0 && powerVal_next == 26)
                {
                    thisCharIdx--;
                    lastValue = (int)powerVal * thisCharIdx;
                }
            }

            toRet += (char)((byte)'A' + thisCharIdx + ((numChars > 1) ? -1 : 0));

            numChars--;
        } while (numChars > 0);

        return toRet;
    }

私の単体テスト:

    [TestMethod]
    public void Test()
    {
        Assert.AreEqual("A", NumberToExcelColumn(1));
        Assert.AreEqual("Z", NumberToExcelColumn(26));
        Assert.AreEqual("AA", NumberToExcelColumn(27));
        Assert.AreEqual("AO", NumberToExcelColumn(41));
        Assert.AreEqual("AZ", NumberToExcelColumn(52));
        Assert.AreEqual("BA", NumberToExcelColumn(53));
        Assert.AreEqual("ZZ", NumberToExcelColumn(702));
        Assert.AreEqual("AAA", NumberToExcelColumn(703));
        Assert.AreEqual("ABC", NumberToExcelColumn(731));
        Assert.AreEqual("ACQ", NumberToExcelColumn(771));
        Assert.AreEqual("AYZ", NumberToExcelColumn(1352));
        Assert.AreEqual("AZA", NumberToExcelColumn(1353));
        Assert.AreEqual("AZB", NumberToExcelColumn(1354));
        Assert.AreEqual("BAA", NumberToExcelColumn(1379));
        Assert.AreEqual("CNU", NumberToExcelColumn(2413));
        Assert.AreEqual("GCM", NumberToExcelColumn(4823));
        Assert.AreEqual("MSR", NumberToExcelColumn(9300));
        Assert.AreEqual("OMB", NumberToExcelColumn(10480));
        Assert.AreEqual("ULV", NumberToExcelColumn(14530));
        Assert.AreEqual("XFD", NumberToExcelColumn(16384));
    }

テストでの最大セル参照が何であるかを示すための+1(XFD)-Webでその情報を見つけるのがどれほど難しいか信じられないでしょう。
controlbox

2

私はゲームに遅れましたが、グラハムの答えは最適とはほど遠いです。特に、キャストmodulo、呼び出しToString()、適用を使用する必要はありません(int)。C#の世界ではほとんどの場合、0から番号付けを開始することを考えると、これが私のリビジョンです。

public static string GetColumnName(int index) // zero-based
{
    const byte BASE = 'Z' - 'A' + 1;
    string name = String.Empty;

    do
    {
        name = Convert.ToChar('A' + index % BASE) + name;
        index = index / BASE - 1;
    }
    while (index >= 0);

    return name;
}

2

別のVBA方法

Public Function GetColumnName(TargetCell As Range) As String
    GetColumnName = Split(CStr(TargetCell.Cells(1, 1).Address), "$")(1)
End Function

1

これが私のPHPでの非常に遅い実装です。これは再帰的です。この投稿を見つける直前に書きました。他の人がこの問題をすでに解決しているかどうかを確認したかった...

public function GetColumn($intNumber, $strCol = null) {

    if ($intNumber > 0) {
        $intRem = ($intNumber - 1) % 26;
        $strCol = $this->GetColumn(intval(($intNumber - $intRem) / 26), sprintf('%s%s', chr(65 + $intRem), $strCol));
    }

    return $strCol;
}

1

私はJavaで同じことをしようとしています...私は次のコードを書きました:

private String getExcelColumnName(int columnNumber) {

    int dividend = columnNumber;
    String columnName = "";
    int modulo;

    while (dividend > 0)
    {
        modulo = (dividend - 1) % 26;

        char val = Character.valueOf((char)(65 + modulo));

        columnName += val;

        dividend = (int)((dividend - modulo) / 26);
    } 

    return columnName;
}

columnNumber = 29を指定して実行すると、「AC」の代わりに「CA」という結果が返されます。StringBuilderでそれを元に戻すことができることはわかっています。しかし、グラハムの答えを見て、私は少し混乱しています...


グラハムは言う:( columnName = Convert.ToChar(65 + modulo).ToString() + columnNameすなわち、値+ ColName)。Hasanの columnName += val;コメント:(つまり、ColName +値)
mcalex 2013年

新しい文字を前に追加するのではなく、追加します。する必要がありますcolumnName = columnName + val
ドメニックD.

1

簡潔でエレガントなRubyバージョン:

def col_name(col_idx)
    name = ""
    while col_idx>0
        mod     = (col_idx-1)%26
        name    = (65+mod).chr + name
        col_idx = ((col_idx-mod)/26).to_i
    end
    name
end

1

これは他のすべての人とGoogleがリダイレクトする質問なので、ここに投稿します。

これらの回答の多くは正しいですが、26列を超えていない場合など、単純な状況では扱いにくいです。2文字の列に入る可能性があるかどうか疑わしい場合は、この回答を無視してください。そうでない場合は、C#でこれと同じくらい簡単に行うことができます。

public static char ColIndexToLetter(short index)
{
    if (index < 0 || index > 25) throw new ArgumentException("Index must be between 0 and 25.");
    return (char)('A' + index);
}

一体何を渡すかについて自信がある場合は、検証を削除してこのインラインを使用することもできます。

(char)('A' + index)

これは多くの言語で非常によく似ているので、必要に応じて変更できます。

繰り返しますが、これは26列を超えないことが100%確実である場合のみ使用してください


1

ここで答えてくれてありがとう!! Elixir / Phoenixで作業しているGoogle Sheets APIとのやり取りのためにこれらのヘルパー関数を思い付くのに役立ちました

ここに私が思いついたものがあります(おそらくいくつかの追加の検証とエラー処理を使用することができます)

エリクサーで:

def number_to_column(number) do
  cond do
    (number > 0 && number <= 26) ->
      to_string([(number + 64)])
    (number > 26) ->
      div_col = number_to_column(div(number - 1, 26))
      remainder = rem(number, 26)
      rem_col = cond do
        (remainder == 0) ->
          number_to_column(26)
        true ->
          number_to_column(remainder)
      end
      div_col <> rem_col
    true ->
      ""
  end
end

そして逆関数:

def column_to_number(column) do
  column
    |> to_charlist
    |> Enum.reverse
    |> Enum.with_index
    |> Enum.reduce(0, fn({char, idx}, acc) ->
      ((char - 64) * :math.pow(26,idx)) + acc
    end)
    |> round
end

そしていくつかのテスト:

describe "test excel functions" do
  @excelTestData [{"A", 1}, {"Z",26}, {"AA", 27}, {"AB", 28}, {"AZ", 52},{"BA", 53}, {"AAA", 703}]

  test "column to number" do
    Enum.each(@excelTestData, fn({input, expected_result}) ->
      actual_result = BulkOnboardingController.column_to_number(input)
      assert actual_result == expected_result
    end)
  end

  test "number to column" do
    Enum.each(@excelTestData, fn({expected_result, input}) ->
      actual_result = BulkOnboardingController.number_to_column(input)
      assert actual_result == expected_result
    end)
  end
end
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.