.net - traductor - Traducir un índice de columna en un nombre de columna de Excel
traductor gratis español ingles (14)
Dado un índice de columnas, ¿cómo se puede obtener un nombre de columna Excel?
El problema es más complicado de lo que parece porque no es solo base-26. Las columnas no se envuelven como lo harían los dígitos normales. Incluso el ejemplo de soporte de Microsoft no escala más allá de ZZZ.
Descargo de responsabilidad: Este es un código que había hecho hace un tiempo, y volvió a aparecer en mi escritorio hoy. Pensé que era digno de publicar aquí como una pregunta pre-respondida.
Es por esta misma razón que evito los nombres de columna en la interfaz programada para Excel. El uso de números de columna funciona muy bien en referencias de celda (r, c) y direccionamiento R1C1.
EDITAR: La función Rango también toma referencias de celda, como en Rango (Celda (r1, c1), Celda (r2, c2)). Además, puede usar la función Dirección para obtener la dirección de estilo A1 de una celda o rango.
EDIT2: Aquí hay una función VBA que usa la función Address () para recuperar el nombre de la columna:
Function colname(colindex)
x = Cells(1, colindex).Address(False, False) '' get the range name (e.g. AB1)
colname = Mid(x, 1, Len(x) - 1) '' return all but last character
End Function
La respuesta que se me ocurrió es ser un poco recursivo. Este código está en VB.Net:
Function ColumnName(ByVal index As Integer) As String
Static chars() As Char = {"A"c, "B"c, "C"c, "D"c, "E"c, "F"c, "G"c, "H"c, "I"c, "J"c, "K"c, "L"c, "M"c, "N"c, "O"c, "P"c, "Q"c, "R"c, "S"c, "T"c, "U"c, "V"c, "W"c, "X"c, "Y"c, "Z"c}
index -= 1 ''''//adjust so it matches 0-indexed array rather than 1-indexed column
Dim quotient As Integer = index / 26 ''''//normal / operator rounds. / does integer division, which truncates
If quotient > 0 Then
ColumnName = ColumnName(quotient) & chars(index Mod 26)
Else
ColumnName = chars(index Mod 26)
End If
End Function
Y en C #:
string ColumnName(int index)
{
index -= 1; //adjust so it matches 0-indexed array rather than 1-indexed column
int quotient = index / 26;
if (quotient > 0)
return ColumnName(quotient) + chars[index % 26].ToString();
else
return chars[index % 26].ToString();
}
private char[] chars = new char[] {''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''};
El único inconveniente es que utiliza columnas de 1 índice en lugar de 0 indexadas.
# Python 2.x, no recursive function calls
def colname_from_colx(colx):
assert colx >= 0
colname = ''''
r = colx
while 1:
r, d = divmod(r, 26)
colname = chr(d + ord(''A'')) + colname
if not r:
return colname
r -= 1
public static String translateColumnIndexToName(int index) {
//assert (index >= 0);
int quotient = (index)/ 26;
if (quotient > 0) {
return translateColumnIndexToName(quotient-1) + (char) ((index % 26) + 65);
} else {
return "" + (char) ((index % 26) + 65);
}
}
y la prueba:
for (int i = 0; i < 100; i++) {
System.out.println(i + ": " + translateColumnIndexToName(i));
}
aquí está el resultado:
0: A
1: B
2: C
3: D
4: E
5: F
6: G
7: H
8: I
9: J
10: K
11: L
12: M
13: N
14: O
15: P
16: Q
17: R
18: S
19: T
20: U
21: V
22: W
23: X
24: Y
25: Z
26: AA
27: AB
28: AC
Necesitaba 0 basado en POI
y la traducción del índice a los nombres:
public static int translateComunNameToIndex0(String columnName) {
if (columnName == null) {
return -1;
}
columnName = columnName.toUpperCase().trim();
int colNo = -1;
switch (columnName.length()) {
case 1:
colNo = (int) columnName.charAt(0) - 64;
break;
case 2:
colNo = ((int) columnName.charAt(0) - 64) * 26 + ((int) columnName.charAt(1) - 64);
break;
default:
//illegal argument exception
throw new IllegalArgumentException(columnName);
}
return colNo;
}
La versión php, gracias a esta publicación para ayudarme a resolverlo! ^^
/**
* Get excel column name
* @param index : a column index we want to get the value in excel column format
* @return (string) : excel column format
*/
function getexcelcolumnname($index) {
//Get the quotient : if the index superior to base 26 max ?
$quotient = $index / 26;
if ($quotient >= 1) {
//If yes, get top level column + the current column code
return getexcelcolumnname($quotient-1). chr(($index % 26)+65);
} else {
//If no just return the current column code
return chr(65 + $index);
}
}
Disfruto escribiendo funciones recursivas, pero no creo que sea necesario aquí. Esta es mi solución en VB. Funciona hasta la columna ZZ. Si alguien puede decirme si funciona para AAA a ZZZ, sería bueno saberlo.
Public Function TranslateColumnIndexToName(index As Integer) As String
''
Dim remainder As Integer
Dim remainder2 As Integer
Dim quotient As Integer
Dim quotient2 As Integer
''
quotient2 = ((index) / (26 * 26)) - 2
remainder2 = (index Mod (26 * 26)) - 1
quotient = ((remainder2) / 26) - 2
remainder = (index Mod 26) - 1
''
If quotient2 > 0 Then
TranslateColumnIndexToName = ChrW(quotient2 + 65) & ChrW(quotient + 65) & ChrW(remainder + 65)
ElseIf quotient > 0 Then
TranslateColumnIndexToName = ChrW(quotient + 65) & ChrW(remainder + 65)
Else
TranslateColumnIndexToName = ChrW(remainder + 65)
End If
Función final
Aquí está el increíble código de Joel modificado para trabajar con índices de columna basados en cero y sin la matriz de caracteres.
Public Shared Function GetExcelColumn(ByVal index As Integer) As String
Dim quotient As Integer = index / 26 ''''//Truncate
If quotient > 0 Then
Return GetExcelColumn(quotient - 1) & Chr((index Mod 26) + 64).ToString
Else
Return Chr(index + 64).ToString
End If
End Function
Esta es una publicación anterior, pero después de ver algunas de las soluciones, se me ocurrió mi propia variación de C #. Basado en 0, sin recursión:
public static String GetExcelColumnName(int columnIndex)
{
if (columnIndex < 0)
{
throw new ArgumentOutOfRangeException("columnIndex: " + columnIndex);
}
Stack<char> stack = new Stack<char>();
while (columnIndex >= 0)
{
stack.Push((char)(''A'' + (columnIndex % 26)));
columnIndex = (columnIndex / 26) - 1;
}
return new String(stack.ToArray());
}
Aquí hay algunos resultados de la prueba en puntos clave de transición:
0: A
1: B
2: C
...
24: Y
25: Z
26: AA
27: AB
...
50: AY
51: AZ
52: BA
53: BB
...
700: ZY
701: ZZ
702: AAA
703: AAB
Aquí está mi solución en C #
// test
void Main()
{
for( var i = 0; i< 1000; i++ )
{ var byte_array = code( i );
Console.WriteLine("{0} | {1} | {2}", i, byte_array, offset(byte_array));
}
}
// Converts an offset to AAA code
public string code( int offset )
{
List<byte> byte_array = new List<byte>();
while( offset >= 0 )
{
byte_array.Add( Convert.ToByte(65 + offset % 26) );
offset = offset / 26 - 1;
}
return ASCIIEncoding.ASCII.GetString( byte_array.ToArray().Reverse().ToArray());
}
// Converts AAA code to an offset
public int offset( string code)
{
var offset = 0;
var byte_array = Encoding.ASCII.GetBytes( code ).Reverse().ToArray();
for( var i = 0; i < byte_array.Length; i++ )
{
offset += (byte_array[i] - 65 + 1) * Convert.ToInt32(Math.Pow(26.0, Convert.ToDouble(i)));
}
return offset - 1;
}
Aquí está mi respuesta en C #, para traducir ambas formas entre el índice de la columna y el nombre de la columna.
/// <summary>
/// Gets the name of a column given the index, as it would appear in Excel.
/// </summary>
/// <param name="columnIndex">The zero-based column index number.</param>
/// <returns>The name of the column.</returns>
/// <example>Column 0 = A, 26 = AA.</example>
public static string GetColumnName(int columnIndex)
{
if (columnIndex < 0) throw new ArgumentOutOfRangeException("columnIndex", "Column index cannot be negative.");
var dividend = columnIndex + 1;
var columnName = string.Empty;
while (dividend > 0)
{
var modulo = (dividend - 1) % 26;
columnName = Convert.ToChar(65 + modulo) + columnName;
dividend = (dividend - modulo) / 26;
}
return columnName;
}
/// <summary>
/// Gets the zero-based column index given a column name.
/// </summary>
/// <param name="columnName">The column name.</param>
/// <returns>The index of the column.</returns>
public static int GetColumnIndex(string columnName)
{
var index = 0;
var total = 0;
for (var i = columnName.Length - 1; i >= 0; i--)
total += (columnName.ToUpperInvariant()[i] - 64) * (int)Math.Pow(26, index++);
return total - 1;
}
En Ruby:
class Fixnum
def col_name
quot = self/26
(quot>0 ? (quot-1).col_name : "") + (self%26+65).chr
end
end
puts 0.col_name # => "A"
puts 51.col_name # => "AZ"
Esta versión de JavaScript muestra que en su núcleo se trata de una conversión a la base 26:
function colName(x)
{
x = (parseInt("ooooooop0", 26) + x).toString(26);
return x.slice(x.indexOf(''p'') + 1).replace(/./g, function(c)
{
c = c.charCodeAt(0);
return String.fromCharCode(c < 64 ? c + 17 : c - 22);
});
}
El .toString(26)
muestra que Joel Coehoorn está equivocado: es una conversión de base simple.
(Nota: Tengo una implementación más directa basada en la respuesta de producción de Dana. Es menos pesada, funciona para números más grandes, aunque eso no me afectará, pero tampoco muestra el principio matemático tan claramente).
PD Aquí está la función evaluada en puntos importantes:
0 A
1 B
9 J
10 K
24 Y
25 Z
26 AA
27 AB
700 ZY
701 ZZ
702 AAA
703 AAB
18276 ZZY
18277 ZZZ
18278 AAAA
18279 AAAB
475252 ZZZY
475253 ZZZZ
475254 AAAAA
475255 AAAAB
12356628 ZZZZY
12356629 ZZZZZ
12356630 AAAAAA
12356631 AAAAAB
321272404 ZZZZZY
321272405 ZZZZZZ
321272406 AAAAAAA
321272407 AAAAAAB
8353082580 ZZZZZZY
8353082581 ZZZZZZZ
8353082582 AAAAAAAA
8353082583 AAAAAAAB
Solución de JavaScript
/**
* Calculate the column letter abbreviation from a 0 based index
* @param {Number} value
* @returns {string}
*/
getColumnFromIndex = function (value) {
var base = ''ABCDEFGHIJKLMNOPQRSTUVWXYZ''.split('''');
value++;
var remainder, result = "";
do {
remainder = value % 26;
result = base[(remainder || 26) - 1] + result;
value = Math.floor(value / 26);
} while (value > 0);
return result;
};
en python, con recursión. traducido de la respuesta de Joey . hasta el momento, se ha probado que funciona hasta GetExcelByColumn (35) = ''AI''
def GetExcelColumn(index):
quotient = int(index / 26)
if quotient > 0:
return GetExcelColumn(quotient) + str(chr((index % 26) + 64))
else:
return str(chr(index + 64))