Convertir el índice de columna en la letra de columna correspondiente

86

Necesito convertir un índice de columna de la hoja de cálculo de Google en su valor de letra correspondiente, por ejemplo, dada una hoja de cálculo:

ingrese la descripción de la imagen aquí

Necesito hacer esto (esta función obviamente no existe, es un ejemplo):

getColumnLetterByIndex(4);  // this should return "D"
getColumnLetterByIndex(1);  // this should return "A"
getColumnLetterByIndex(6);  // this should return "F"

Ahora, no recuerdo exactamente si el índice comienza desde 0o desde 1, de todos modos el concepto debería ser claro.

No encontré nada sobre esto en la documentación del gas. ¿Estoy ciego? ¿Alguna idea?

Gracias

BeNdErR
fuente
14
¿Cómo es que esto no está incorporado?
Cyril Duchon-Doris
1
Duplicado: stackoverflow.com/questions/12699030/…
Ondra Žižka
1
Mejor respuesta
Stephen M. Harris
1
X = (n) => (a = Math.floor (n / 26))> = 0? X (a-1) + String.fromCharCode (65+ (n% 26)): '';
Pascal DeMilly

Respuestas:

154

Los escribí hace un tiempo para varios propósitos (devolveré los nombres de columna de doble letra para los números de columna> 26):

function columnToLetter(column)
{
  var temp, letter = '';
  while (column > 0)
  {
    temp = (column - 1) % 26;
    letter = String.fromCharCode(temp + 65) + letter;
    column = (column - temp - 1) / 26;
  }
  return letter;
}

function letterToColumn(letter)
{
  var column = 0, length = letter.length;
  for (var i = 0; i < length; i++)
  {
    column += (letter.charCodeAt(i) - 64) * Math.pow(26, length - i - 1);
  }
  return column;
}
AdamL
fuente
1
¿El máximo es menor que ZZ?
Old Geezer
1
Acaba de utilizar esto a números de las columnas de la subasta: var column = letterToColumn(AA); columnToLetter(column + 1);. Podría ser útil para alguien.
joshfindit
1
Sugiero cambiar column += (letter.charCodeAt(i) - 64) * Math.pow(26, length - i - 1);a column += (letter.toUpperCase().charCodeAt(i) - 64) * Math.pow(26, length - i - 1);para que funcione si lettercontiene letras minúsculas, de lo contrario, ase generaría en 33lugar de1
tukusejssirs
fwiw - esta fue una entrevista Q para mí en uno de los grandes Cos
Taylor Halliday
Yo creo que String.fromCharCode que no funciona en Apps Script
c-an
69

Esto funciona bien

=REGEXEXTRACT(ADDRESS(ROW(); COLUMN()); "[A-Z]+")

incluso para columnas más allá de Z.

Demo de función

Simplemente reemplácelo COLUMN()con su número de columna. El valor de ROW()no importa.

wronex
fuente
4
está utilizando fórmulas, no GAS
BeNdErR
11
Esto funciona muy bien. Aunque esto no usa GAS (con el que se etiqueta la pregunta), las funciones integradas son casi siempre preferibles dado que no necesitan estar escritas en absoluto y, en mi experiencia, se ejecutan significativamente más rápido.
kevinmicke
36
=SUBSTITUTE(ADDRESS(1,COLUMN(),4), "1", "")

Esto toma su celda, obtiene su dirección como, por ejemplo, C1 y elimina el "1".

ingrese la descripción de la imagen aquí

Cómo funciona

  • COLUMN() da el número de la columna de la celda.
  • ADDRESS(1, ..., <format>)da una dirección de una celda, en formato especificado por <format>parámetro. 4significa la dirección que conoce, por ejemplo C1.
  • Finalmente, SUBSTITUTE(..., "1", "")reemplaza el 1en la dirección C1, por lo que te queda la letra de la columna.
Ondra Žižka
fuente
3
Esta es una solución elegante, me gusta más. No estoy seguro de por qué no tiene más votos a favor.
singularidad
1
Obtuve esto al intentarlo: screencast.com/t/Jmc8L9W5LB . Me di cuenta de esto. Lo resolví reemplazando todas las comas con punto y coma. Este es probablemente un problema de localización
David
@David, me funciona con comas. Tal vez se deba a la configuración regional.
Ondra Žižka
1
La pregunta es solicitar una función para usar en scripts, mientras que esta solución proporciona una fórmula para usar en celdas.
markshep
Solución realmente elegante.
Gabz
23

Esto funciona en rangos A-Z

=char(64+column())

SauloAlessandre
fuente
3
Esto es bastante complicado para las personas que no tienen experiencia en programación y no funcionan en columnas más allá de "Z" (es decir, "AA"), pero me gusta de todos modos porque es el cálculo más corto y rápido (por ejemplo, podría tener 1,000 s de estos van a la vez sin que su computadora sude).
Dave
21

No es necesario reinventar la rueda aquí, use la gama GAS en su lugar:

 var column_index = 1; // your column to resolve
 
 var ss = SpreadsheetApp.getActiveSpreadsheet();
 var sheet = ss.getSheets()[0];
 var range = sheet.getRange(1, column_index, 1, 1);

 Logger.log(range.getA1Notation().match(/([A-Z]+)/)[0]); // Logs "A"

Tomi Heiskanen
fuente
6

En javascript:

X = (n) => (a=Math.floor(n/26)) >= 0 ? X(a-1) + String.fromCharCode(65+(n%26)) : '';
console.assert (X(0) == 'A')
console.assert (X(25) == 'Z')
console.assert (X(26) == 'AA')
console.assert (X(51) == 'AZ')
console.assert (X(52) == 'BA')
Pascal DeMilly
fuente
Ojalá funcionara en los scripts de Google, pero un pequeño fragmento de código increíble.
Giampaolo Ferradini
1
@Giam Funciona en el script de aplicaciones. Esta debería ser la respuesta aceptada
TheMaster
3

Agregando a la respuesta de @ SauloAlessandre, esto funcionará para columnas desde A-ZZ.

=if(column() >26,char(64+(column()-1)/26),) & char(65 + mod(column()-1,26))

Me gustan las respuestas de @wronex y @Ondra Žižka. Sin embargo, me gusta mucho la simplicidad de la respuesta de @ SauloAlessandre.

Entonces, acabo de agregar el código obvio para permitir que la respuesta de @ SauloAlessandre funcione para hojas de cálculo más amplias.

Como @Dave mencionó en su comentario, ayuda tener experiencia en programación, particularmente uno en C donde agregamos el valor hexadecimal de 'A' a un número para obtener la enésima letra del alfabeto como patrón estándar.

Respuesta actualizada para detectar el error señalado por @Sangbok Lee. ¡Gracias!

Jardinero
fuente
1
Da en @lugar de Zcuando se usa en Zcolumna.
Sangbok Lee
1
¡@Sangbok tiene razón! Esto se ha actualizado y probado para las columnas Z, AA, AZ, BB. Creo que funcionará a través de ZZ.
Jardinero
2

También estaba buscando una versión de Python aquí, la mía, que se probó en Python 3.6

def columnToLetter(column):
    character = chr(ord('A') + column % 26)
    remainder = column // 26
    if column >= 26:
        return columnToLetter(remainder-1) + character
    else:
        return character
hum3
fuente
1
X=lambda n:~n and X(n/26-1)+chr(65+n%26)or''
Ondra Žižka
De todos modos, si no me equivoco, esto es base26. Difícil: junto a Zdebería estar AA. Esto le da a BA.
Ondra Žižka
1
Tu versión es casi correcta, creo que debería ser: X=lambda n:~int(n) and X(int(n/26)-1)+chr(65+n%26)or''
hum3
Mierda, esa fue una función lambda increíble que obtuviste allí, hum3. ¡Gracias!
ViggoTW
Gracias, pero solo estaba depurando la solución de Ondra.
hum3
2

Estaba buscando una solución en PHP. Quizás esto ayude a alguien.

<?php

$numberToLetter = function(int $number)
{
    if ($number <= 0) return null;

    $temp; $letter = '';
    while ($number > 0) {
        $temp = ($number - 1) % 26;
        $letter = chr($temp + 65) . $letter;
        $number = ($number - $temp - 1) / 26;
    }
    return $letter;
};

$letterToNumber = function(string $letters) {
    $letters = strtoupper($letters);
    $letters = preg_replace("/[^A-Z]/", '', $letters);

    $column = 0; 
    $length = strlen($letters);
    for ($i = 0; $i < $length; $i++) {
        $column += (ord($letters[$i]) - 64) * pow(26, $length - $i - 1);
    }
    return $column;
};

var_dump($numberToLetter(-1));
var_dump($numberToLetter(26));
var_dump($numberToLetter(27));
var_dump($numberToLetter(30));

var_dump($letterToNumber('-1A!'));
var_dump($letterToNumber('A'));
var_dump($letterToNumber('B'));
var_dump($letterToNumber('Y'));
var_dump($letterToNumber('Z'));
var_dump($letterToNumber('AA'));
var_dump($letterToNumber('AB'));

Salida:

NULL
string(1) "Z"
string(2) "AA"
string(2) "AD"
int(1)
int(1)
int(2)
int(25)
int(26)
int(27)
int(28)
Fred
fuente
1

Un comentario sobre mi respuesta dice que querías una función de script para ello. Muy bien, aquí vamos:

function excelize(colNum) {
    var order = 1, sub = 0, divTmp = colNum;
    do {
        divTmp -= order; sub += order; order *= 26;
        divTmp = (divTmp - (divTmp % 26)) / 26;
    } while(divTmp > 0);

    var symbols = "0123456789abcdefghijklmnopqrstuvwxyz";
    var tr = c => symbols[symbols.indexOf(c)+10];
    return Number(colNum-sub).toString(26).split('').map(c=>tr(c)).join('');
}

Esto puede manejar cualquier número que JS pueda manejar, creo.

Explicación:

Dado que esto no es base26, necesitamos restar el orden de tiempos base para cada símbolo adicional ("dígito"). Entonces, primero contamos el orden del número resultante y, al mismo tiempo, contamos el número a restar. Y luego lo convertimos a base 26 y restamos eso, y luego cambiamos los símbolos a en A-Zlugar de0-P .

De todos modos, esta pregunta se está convirtiendo en un código de golf :)

Ondra Žižka
fuente
0

PDI de Java Apache

String columnLetter = CellReference.convertNumToColString(columnNumber);
CelinHC
fuente
0

Esto lo cubrirá hasta la columna AZ:

=iferror(if(match(A2,$A$1:$AZ$1,0)<27,char(64+(match(A2,$A$1:$AZ$1,0))),concatenate("A",char(38+(match(A2,$A$1:$AZ$1,0))))),"No match")
Christian Swanson
fuente
0

Aquí hay una versión general escrita en Scala. Es para un índice de columna que comienza en 0 (es simple de modificar para un índice que comienza en 1):

def indexToColumnBase(n: Int, base: Int): String = {
  require(n >= 0, s"Index is non-negative, n = $n")
  require(2 <= base && base <= 26, s"Base in range 2...26, base = $base")

  def digitFromZeroToLetter(n: BigInt): String =
    ('A' + n.toInt).toChar.toString

  def digitFromOneToLetter(n: BigInt): String =
    ('A' - 1 + n.toInt).toChar.toString

  def lhsConvert(n: Int): String = {
    val q0: Int = n / base
    val r0: Int = n % base

    val q1 = if (r0 == 0) (n - base) / base else q0
    val r1 = if (r0 == 0) base else r0

    if (q1 == 0)
      digitFromOneToLetter(r1)
    else
      lhsConvert(q1) + digitFromOneToLetter(r1)
  }

  val q: Int = n / base
  val r: Int = n % base

  if (q == 0)
    digitFromZeroToLetter(r)
  else
    lhsConvert(q) + digitFromZeroToLetter(r)
}

def indexToColumnAtoZ(n: Int): String = {
  val AtoZBase = 26
  indexToColumnBase(n, AtoZBase)
}
Ian Elliott
fuente
0

Manera simple a través de las funciones de Google Sheet, de la A a la Z.

=column(B2) : value is 2
=address(1, column(B2)) : value is $B$1
=mid(address(1, column(B2)),2,1) : value is B

Es una forma complicada de pasar por las funciones de Google Sheet, pero también es más que AA.

=mid(address(1, column(AB3)),2,len(address(1, column(AB3)))-3) : value is AB
redlasha
fuente
0

Una función para convertir un índice de columna en combinaciones de letras, de forma recursiva:

function lettersFromIndex(index, curResult, i) {

  if (i == undefined) i = 11; //enough for Number.MAX_SAFE_INTEGER
  if (curResult == undefined) curResult = "";

  var factor = Math.floor(index / Math.pow(26, i)); //for the order of magnitude 26^i

  if (factor > 0 && i > 0) {
    curResult += String.fromCharCode(64 + factor);
    curResult = lettersFromIndex(index - Math.pow(26, i) * factor, curResult, i - 1);

  } else if (factor == 0 && i > 0) {
    curResult = lettersFromIndex(index, curResult, i - 1);

  } else {
    curResult += String.fromCharCode(64 + index % 26);

  }
  return curResult;
}

jim_kastrin
fuente
-1

En PowerShell:

function convert-IndexToColumn
{
    Param
    (
        [Parameter(Mandatory)]
        [int]$col
    )
    "$(if($col -gt 26){[char][int][math]::Floor(64+($col-1)/26)})$([char](65 + (($col-1) % 26)))"
}

Mike Shaw
fuente
-2

Aquí hay una versión con índice cero (en Python):

letters = []
while column >= 0:
    letters.append(string.ascii_uppercase[column % 26])
    column = column // 26 - 1
return ''.join(reversed(letters))
blais
fuente
No es esto. La pregunta no es base26. También me atrajeron originalmente a eso :)
Ondra Žižka