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.
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;
}
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
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))
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;
}
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;
}
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) );
}
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;
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;
}
..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;
}
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);
}
}
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;
}
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));
}
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
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);
}
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
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))
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;
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».
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;
}
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;
};
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;
}
}
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;
}
Une autre façon de VBA
Public Function GetColumnName(TargetCell As Range) As String
GetColumnName = Split(CStr(TargetCell.Address), "$")(1)
End Function
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;
};
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 ....
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 .
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:
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;
}
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));
}
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)));
}
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;
}
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
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;
}
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
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)
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
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;
}
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
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.
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())
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));
}
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
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.
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.
(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());
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
// 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
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
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