web-dev-qa-db-fra.com

Comment convertir un numéro de colonne (par exemple 127) en une colonne Excel (par exemple AA)

Comment convertir un nombre numérique en un nom de colonne Excel en C # sans utiliser l'automatisation pour obtenir la valeur directement à partir d'Excel.

Excel 2007 a une plage possible de 1 à 16384, ce qui correspond au nombre de colonnes qu’il prend en charge. Les valeurs résultantes doivent être sous la forme de noms de colonnes Excel, par exemple. A, AA, AAA etc.

425
robertkroll

Voici comment je le fais:

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;
}
819
Graham

Si quelqu'un doit le faire dans Excel sans VBA, voici une solution:

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

où numNum est le numéro de colonne

Et en 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
54
vzczc

Désolé, il s’agit de Python au lieu de C #, mais au moins les résultats sont corrects:

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))
20
RoMa

Vous aurez peut-être besoin d'une conversion dans les deux sens, par exemple à partir d'une adresse de colonne Excel telle que AAZ en entier et d'un entier en Excel. Les deux méthodes ci-dessous feront exactement cela. Supposons que 1 soit indexé, le premier élément de vos "tableaux" est l’élément numéro 1 . Aucune limite de taille ici, vous pouvez donc utiliser des adresses telles que ERROR (numéro de colonne 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;
}
17
Arent Arntzen

J'ai découvert une erreur dans mon premier message, alors j'ai décidé de m'asseoir et de faire le calcul. Ce que j’ai trouvé, c’est que le système de numérotation utilisé pour identifier les colonnes Excel n’est pas un système de base 26, comme l’a signalé une autre personne. Considérez ce qui suit en base 10. Vous pouvez également le faire avec les lettres de l’alphabet.

Espace: ......................... S1, S2, S3: S1, S2, S3
.................................... 0, 00, 000: .. A, AA , AAA
.................................... 1, 01, 001: .. B, AB , AAB
....................................…,…,…: ..…,… ,…
.................................... 9, 99, 999: .. Z, ZZ , ZZZ
Nombre total d'états dans l'espace: 10, 100, 1000: 26, 676, 17576
Total des états: ............... 1110 ................ 18278

Excel numérote les colonnes dans les espaces alphabétiques individuels à l'aide de la base 26. Vous pouvez constater qu'en général, la progression de l'espace des états est a, a ^ 2, a ^ 3,… pour une base a et que le nombre total d'états est a + a ^ 2 + a ^ 3 +…. 

Supposons que vous souhaitiez trouver le nombre total d'états A dans les N premiers espaces. La formule pour ce faire est A = (a) (a ^ N - 1)/(a-1). Ceci est important car nous devons trouver l’espace N qui correspond à notre indice K. Si je veux savoir où K se situe dans le système de numérotation, j’ai besoin de remplacer A par K et de résoudre pour N. La solution est N = log { base a} (A (a-1)/a +1). Si j'utilise l'exemple de a = 10 et K = 192, je sais que N = 2,23804…. Cela me dit que K se situe au début du troisième espace puisqu'il est un peu plus grand que deux.

La prochaine étape consiste à trouver exactement à quelle distance de l’espace actuel nous sommes. Pour trouver cela, soustrayez de K le A généré en utilisant le plancher de N. Dans cet exemple, le plancher de N est deux. Donc, A = (10) (10 ^ 2 - 1)/(10-1) = 110, comme prévu lorsque vous combinez les états des deux premiers espaces. Ceci doit être soustrait de K car ces 110 premiers états auraient déjà été pris en compte dans les deux premiers espaces. Cela nous laisse avec 82 états. Ainsi, dans ce système de numération, la représentation de 192 en base 10 est 082. 

Le code C # utilisant un indice de base de zéro est

    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;
    }

// Old Post

Une solution zéro en 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;
    }
13
John

Facile avec récursion.

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) );
}
9
Peter
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;

Update: Peter le commentaire de/est correct. C'est ce que je reçois pour écrire du code dans le navigateur. :-) Ma solution ne compilait pas, il manquait la lettre la plus à gauche et la chaîne était construite dans l'ordre inverse - tout est maintenant corrigé.

Mis à part les bugs, l’algorithme convertit un nombre de la base 10 à la base 26.

Update 2: Joel Coehoorn a raison - le code ci-dessus renvoie AB pour 27. S'il s'agissait d'un nombre réel en base 26, AA serait égal à A et le prochain nombre après Z serait 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;
9
Franci Penov

Cette réponse est en 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;
}
8
MaVRoSCy

..Et converti en php:

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

Je suis surpris que toutes les solutions à ce jour contiennent des itérations ou des récursions.

Voici ma solution qui fonctionne à temps constant (pas de boucles). Cette solution fonctionne pour toutes les colonnes Excel possibles et vérifie que l'entrée peut être transformée en une colonne Excel. Les colonnes possibles sont dans la plage [A, XFD] ou [1, 16384]. (Cela dépend de votre version d'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);
    }
}
7
user2023861

Même implémentation en 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; 
    }  
6
Balaji.N.S

Un peu tard dans le jeu, mais voici le code que j'utilise (en 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));
}
5
Kelly L

Je voulais ajouter la classe statique que j'utilise pour l'interopérabilité entre col index et col Label. J'utilise une réponse acceptée modifiée pour ma méthode 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;
    }
}

Utilisez ceci comme ...

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

Ajoutons simplement une implémentation C # à deux lignes utilisant la récursivité, car toutes les réponses semblent ici bien plus compliquées que nécessaire.

/// <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);
}
5
Extragorey

Après avoir examiné toutes les versions fournies ici, j'ai décidé d'en faire une moi-même, en utilisant la récursivité.

Voici ma version 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
user932708

si vous le voulez juste pour une formule de cellule sans code, en voici une formule:

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

En Delphi (Pascal):

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;
4
JRL
private String getColumn(int c) {
    String s = "";
    do {
        s = (char)('A' + (c % 26)) + s;
        c /= 26;
    } while (c-- > 0);
    return s;
}

Ce n'est pas exactement la base 26, il n'y a pas de 0 dans le système. Si c'était le cas, «Z» serait suivi de «BA» et non de «AA».

3
rubberduckie

En Perl, pour une entrée de 1 (A), 27 (AA), etc.

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
Myforwik

Solution 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;
};
2
Ally

Affinage de la solution d'origine (en 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
ShloEmi

Voici une version d'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
Rob

Une autre façon de VBA

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

Ceci est une version javascript selon le code de Graham

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

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

    return columnName;
};
1
Kevin

J'essaie de faire la même chose en Java .... J'ai écrit le code suivant:

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;
}

Maintenant, une fois que je l'ai exécuté avec columnNumber = 29, il me donne le résultat = "CA" (au lieu de "AC") Un commentaire sur ce qu'il manque .. Mais en regardant la réponse de Graham, je suis un peu confus ....

1
Hasan

C’est la question à laquelle tous les autres, ainsi que la redirection vers Google, m’appelle donc ici.

Beaucoup de ces réponses sont correctes mais trop lourdes pour des situations simples comme lorsque vous n'avez pas plus de 26 colonnes. Si vous avez un doute quant à savoir si vous pouvez entrer dans les colonnes à double caractère, ignorez cette réponse, mais si vous êtes certain de ne pas le faire, vous pouvez le faire aussi simplement que cela en 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);
}

Heck, si vous êtes sûr de ce que vous transmettez, vous pouvez même supprimer la validation et utiliser ceci en ligne:

(char)('A' + index)

Ce sera très similaire dans de nombreuses langues afin que vous puissiez l’adapter au besoin.

Encore une fois, utilisez-le uniquement si vous êtes sûr à 100% de ne pas avoir plus de 26 colonnes .

1
Vlad Schnakovszki

Désolé, il s’agit de Python au lieu de C #, mais au moins les résultats sont corrects:

def Excel_column_number_to_name(column_number):
    output = ""
    index = column_number-1
    while index >= 0:
        character = chr((index%26)+ord('A'))
        output = output + character
        index = index/26 - 1

    return output[::-1]


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

Passé ces cas de test:

  • Numéro de colonne: 494286 => ABCDZ 
  • Numéro de colonne: 27 => AA
  • Numéro de colonne: 52 => AZ
1
DataEngineer

Bien que je sois en retard au jeu, la réponse de Graham est loin d’être optimal. En particulier, vous n'avez pas à utiliser la variable modulo, appeler ToString() et appliquer le transtypage (int). Considérant que dans la plupart des cas, dans le monde C #, la numérotation commence à 0, voici ma révision:

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;
}
1
Herman Kan

Ces mes codes pour convertir un nombre spécifique (index commençant à 1) en colonne 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;
    }

Mon unité de test:

    [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
S_R

Déjà plus de 30 solutions, mais voici ma solution monoligne en C # ...

public string IntToExcelColumn(int i)
{
    return ((i<16926? "" : ((char)((((i/26)-1)%26)+65)).ToString()) + (i<2730? "" : ((char)((((i/26)-1)%26)+65)).ToString()) + (i<26? "" : ((char)((((i/26)-1)%26)+65)).ToString()) + ((char)((i%26)+65)));
}
1
AlishahNovin

Voici mon implémentation super tardive en PHP. Celui-ci est récursif. Je l'ai écrit juste avant d'avoir trouvé ce post. Je voulais voir si d'autres avaient déjà résolu ce problème ...

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
Gordon Freeman

Concis et élégant Ruby version:

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
0
Iwan B.

Implémentation de NodeJS:

/**
* getColumnFromIndex
* Helper that returns a column value (A-XFD) for an index value (integer).
* The column follows the Common Spreadsheet Format e.g., A, AA, AAA.
* See https://stackoverflow.com/questions/181596/how-to-convert-a-column-number-eg-127-into-an-Excel-column-eg-aa/3444285#3444285
* @param numVal: Integer
* @return String
*/
getColumnFromIndex: function(numVal){
   var dividend = parseInt(numVal);
   var columnName = '';
   var modulo;
   while (dividend > 0) {
      modulo = (dividend - 1) % 26;
      columnName = String.fromCharCode(65 + modulo) + columnName;
      dividend = parseInt((dividend - modulo) / 26);
   }
   return columnName;
},

Merci à Convertissez l’alphabet de colonne Excel (par exemple AA) en nombre (par exemple 25) . Et inversement:

/**
* getIndexFromColumn
* Helper that returns an index value (integer) for a column value (A-XFD).
* The column follows the Common Spreadsheet Format e.g., A, AA, AAA.
* See https://stackoverflow.com/questions/9905533/convert-Excel-column-alphabet-e-g-aa-to-number-e-g-25
* @param strVal: String
* @return Integer
*/
getIndexFromColumn: function(val){
   var base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', i, j, result = 0;
   for (i = 0, j = val.length - 1; i < val.length; i += 1, j -= 1) {
      result += Math.pow(base.length, j) * (base.indexOf(val[i]) + 1);
   }
   return result;
}
0
Rob Sawyer

Une autre solution:

private void Foo()
{
   l_ExcelApp = new Excel.ApplicationClass();
   l_ExcelApp.ReferenceStyle = Excel.XlReferenceStyle.xlR1C1;
   // ... now reference by R[row]C[column], Ex. A1 <==> R1C1, C6 <==> R3C6, ...
}

voir plus ici - Référencement de cellules dans Excel pour tout le monde! du Dr Nitin Paranjape

0
ShloEmi

Je viens de faire ce travail aujourd'hui, mon implémentation utilise la récursivité:

private static string GetColumnLetter(string colNumber)
{
    if (string.IsNullOrEmpty(colNumber))
    {
        throw new ArgumentNullException(colNumber);
    }

    string colName = String.Empty;

    try
    {
        var colNum = Convert.ToInt32(colNumber);
        var mod = colNum % 26;
        var div = Math.Floor((double)(colNum)/26);
        colName = ((div > 0) ? GetColumnLetter((div - 1).ToString()) : String.Empty) + Convert.ToChar(mod + 65);
    }
    finally
    {
        colName = colName == String.Empty ? "A" : colName;
    }

    return colName;
}

Ceci considère le nombre venant sous forme de chaîne la méthode et les nombres commençant par "0" (A = 0)

0
Madison Tobal

Vu une autre réponse VBA - cela peut être fait dans Excel-vba avec un fichier UDF d'une ligne:

Function GetColLetter(ByVal colID As Integer) As String
    GetColLetter = Split(Cells(1, colID).Address, "$")(1)
End Function
0
Sam

Voici ce que Graham a écrit dans Powershell:

function ConvertTo-ExcelColumnID {
param (
    [parameter(Position = 0,
        HelpMessage = "A 1-based index to convert to an Excel column ID. e.g. 2 => 'B', 29 => 'AC'",
        Mandatory = $true)]
    [int]$index
);

[string]$result = '';
if ($index -le 0 ) {
    return $result;
}

while ($index -gt 0) {
    [int]$modulo = ($index - 1) % 26;
    $character = [char]($modulo + [int][char]'A');
    $result = $character + $result;
    [int]$index = ($index - $modulo) / 26;
}

return $result;

}

0
user1098928

En utilisant ceci dans VB.Net 2005:

Private Function ColumnName(ByVal ColumnIndex As Integer) As String

   Dim Name As String = ""

   Name = (New Microsoft.Office.Interop.Owc11.Spreadsheet).Columns.Item(ColumnIndex).Address(False, False, Microsoft.Office.Interop.Owc11.XlReferenceStyle.xlA1)
   Name = Split(Name, ":")(0)

   Return Name

End Function
0
user121385

La plupart des réponses précédentes sont correctes. Voici un autre moyen de convertir le nombre de colonnes en colonnes Excel .. La solution est assez simple si nous considérons cela comme une conversion de base. Convertissez simplement le numéro de colonne en base 26 car il n’ya que 26 lettres . Voici comment procéder: 

pas:

  • définir la colonne comme un quotient

  • soustrayez-en une à la variable quotient (de l'étape précédente) car nous devons nous retrouver sur table ascii avec 97 étant a.

  • diviser par 26 et obtenir le reste.

  • ajouter +97 au reste et convertir en caractère (puisque 97 est "a" dans la table ASCII)
  • quotient devient le nouveau quotient/26 (puisque nous pourrions dépasser 26 colonnes)
  • continuez jusqu'à ce que le quotient soit supérieur à 0, puis renvoyez le résultat

voici le code qui fait ça :)

def convert_num_to_column(column_num):
    result = ""
    quotient = column_num
    remainder = 0
    while (quotient >0):
        quotient = quotient -1
        remainder = quotient%26
        result = chr(int(remainder)+97)+result
        quotient = int(quotient/26)
    return result

print("--",convert_num_to_column(1).upper())
0
grepit
public static string ConvertToAlphaColumnReferenceFromInteger(int columnReference)
    {
        int baseValue = ((int)('A')) - 1 ;
        string lsReturn = String.Empty; 

        if (columnReference > 26) 
        {
            lsReturn = ConvertToAlphaColumnReferenceFromInteger(Convert.ToInt32(Convert.ToDouble(columnReference / 26).ToString().Split('.')[0]));
        } 

        return lsReturn + Convert.ToChar(baseValue + (columnReference % 26));            
    }
0
Daniel

Merci pour les réponses ici !! m'a aidé à trouver ces fonctions d'assistance pour certaines interactions avec l'API Google Sheets sur laquelle je travaille dans Elixir/Phoenix

voici ce que je suis venu avec (pourrait probablement utiliser une validation supplémentaire et la gestion des erreurs)

Dans Elixir:

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

Et la fonction inverse: 

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

Et quelques tests:

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
0
phlare

Voici comment je le ferais en Python. L'algorithme est expliqué ci-dessous:

alph = ('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')
def labelrec(n, res):
    if n<26:
        return alph[n]+res
    else:
        rem = n%26
        res = alph[rem]+res
        n = n/26-1
        return labelrec(n, res)

La fonction labelrec peut être appelée avec le numéro et une chaîne vide telle que:

print labelrec(16383, '')

Voici pourquoi cela fonctionne: Si les nombres décimaux étaient écrits de la même manière que les colonnes de la feuille Excel, le nombre 0-9 serait écrit normalement, mais 10 deviendrait "00" et ensuite 20 deviendrait "10", etc. Cartographier quelques nombres:

0 - 0

9 - 9

10h00

20 - 10

100 - 90

110 - 000

1110 - 0000

Donc, le schéma est clair. À partir de l'endroit où se trouve l'unité, si un nombre est inférieur à 10, sa représentation est identique à celle du nombre lui-même. Sinon, vous devez ajuster le nombre restant en le soustrayant de 1 et en recurse. Vous pouvez arrêter lorsque le nombre est inférieur à 10.

La même logique est appliquée pour les nombres de base 26 dans la solution ci-dessus.

P.S. Si vous voulez que les numéros commencent à 1, appelez la même fonction pour le numéro entré après l'avoir diminuée de 1.

0
lambdapilgrim

Si vous souhaitez référencer la cellule progressivement, vous obtiendrez un code beaucoup plus lisible si vous utilisez la méthode Cells d'une feuille. Il prend un index de ligne et de colonne au lieu d'une référence de cellule traditionnelle. C'est très similaire à la méthode Offset.

0
pipTheGeek

(Je me rends compte que la question concerne C # cependant, si quelqu'un qui lit a besoin de faire la même chose avec Java, alors ce qui suit peut être utile)

Il s'avère que cela peut être facilement fait en utilisant la classe "CellReference" dans Jakarta POI . En outre, la conversion peut être faite dans les deux sens.

// Convert row and column numbers (0-based) to an Excel cell reference
CellReference numbers = new CellReference(3, 28);
System.out.println(numbers.formatAsString());

// Convert an Excel cell reference back into digits
CellReference reference = new CellReference("AC4");
System.out.println(reference.getRow() + ", " + reference.getCol());
0
Ian

Version F # de chaque manière

let rec getExcelColumnName x  = if x<26 then int 'A'+x|>char|>string else (x/26-1|>c)+ c(x%26)

pardon the minimizing, travaillait sur une meilleure version de https://stackoverflow.com/a/4500043/57883


et la direction opposée:

// return values start at 0
let getIndexFromExcelColumnName (x:string) =
    let a = int 'A'
    let fPow len i =
        Math.Pow(26., len - 1 - i |> float)
        |> int

    let getValue len i c = 
        int c - a + 1 * fPow len i
    let f i = getValue x.Length i x.[i]
    [0 .. x.Length - 1]
    |> Seq.map f
    |> Seq.sum
    |> fun x -> x - 1
0
Maslow

J'utilise celui-ci dans VB.NET 2003 et ça marche bien ...

Private Function GetExcelColumnName(ByVal aiColNumber As Integer) As String
    Dim BaseValue As Integer = Convert.ToInt32(("A").Chars(0)) - 1
    Dim lsReturn As String = String.Empty

    If (aiColNumber > 26) Then
        lsReturn = GetExcelColumnName(Convert.ToInt32((Format(aiColNumber / 26, "0.0").Split("."))(0)))
    End If

    GetExcelColumnName = lsReturn + Convert.ToChar(BaseValue + (aiColNumber Mod 26))
End Function
0
Manuel

Mise en œuvre d'Objective-C:

-(NSString*)getColumnName:(int)n {
     NSString *name = @"";
     while (n>0) {
     n--;
     char c = (char)('A' + n%26);
     name = [NSString stringWithFormat:@"%c%@",c,name];
     n = n/26;
  }    
     return name;

}

Mise en œuvre rapide:

func getColumnName(n:Int)->String{
 var columnName = ""
 var index = n
 while index>0 {
     index--
     let char = Character(UnicodeScalar(65 + index%26))
     columnName = "\(char)\(columnName)"
     index = index / 26
 }
 return columnName

}

La réponse est basée sur: https://stackoverflow.com/a/4532562/2231118

0
bpolat