Converta o índice da coluna na letra da coluna correspondente

86

Preciso converter um índice de coluna da planilha do Google em seu valor de letra correspondente, por exemplo, em uma planilha:

insira a descrição da imagem aqui

Preciso fazer isso (essa função obviamente não existe, é um exemplo):

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

Agora, não me lembro exatamente se o índice começa 0ou a partir 1, de qualquer maneira o conceito deve estar claro.

Não encontrei nada sobre isso na documentação do gás .. sou cego? Qualquer ideia?

Obrigado

BeNdErR
fonte
14
Como é que isso não está embutido ??
Cyril Duchon-Doris
1
Duplicado: stackoverflow.com/questions/12699030/…
Ondra Žižka
1
Melhor resposta
Stephen M. Harris
1
X = (n) => (a = Math.floor (n / 26))> = 0? X (a-1) + String.fromCharCode (65+ (n% 26)): '';
Pascal DeMilly

Respostas:

154

Escrevi isso há algum tempo para vários fins (retornará os nomes das colunas com letras duplas para os números das colunas> 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
fonte
1
O máximo é menor que ZZ?
Old Geezer
1
Apenas usou isso para números das colunas de incremento: var column = letterToColumn(AA); columnToLetter(column + 1);. Pode ser útil para alguém.
joshfindit de
1
Eu sugiro mudar column += (letter.charCodeAt(i) - 64) * Math.pow(26, length - i - 1);para column += (letter.toUpperCase().charCodeAt(i) - 64) * Math.pow(26, length - i - 1);para fazê-lo funcionar se lettercontiver letras minúsculas, caso contrário, aele sairia em 33vez de1
tukusejssirs
fwiw - esta foi uma entrevista Q para mim em um dos grandes Cos
Taylor Halliday,
Acho String.fromCharCodeque não funciona no Apps Script
c-an
69

Isso funciona bem

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

mesmo para colunas além de Z.

Demonstração de função

Basta substituir COLUMN()pelo número da coluna. O valor de ROW()não importa.

Wronex
fonte
4
você está usando fórmulas, não GAS
BeNdErR
11
Isso funciona muito bem. Mesmo que isso não esteja usando GAS (com o qual a questão é marcada), as funções embutidas são quase sempre preferíveis, visto que elas não precisam ser escritas e, na minha experiência, são executadas significativamente mais rápido.
kevinmicke
36
=SUBSTITUTE(ADDRESS(1,COLUMN(),4), "1", "")

Isso pega sua célula, obtém seu endereço como, por exemplo, C1, e remove o "1".

insira a descrição da imagem aqui

Como funciona

  • COLUMN() dá o número da coluna da célula.
  • ADDRESS(1, ..., <format>)fornece o endereço de uma célula, no formato especificado por <format>parâmetro. 4significa que o endereço que você sabe - por exemplo C1.
  • Finalmente, SUBSTITUTE(..., "1", "")substitui o 1no endereço C1, então você fica com a letra da coluna.
Ondra Žižka
fonte
3
Esta é uma solução elegante - eu gosto mais dela. Não sei por que não tem mais votos positivos.
singularidade
1
Eu consegui isso ao tentar: screencast.com/t/Jmc8L9W5LB . Eu descobri isso. Eu resolvi isso substituindo todas as vírgulas por ponto-e-vírgula. Este é provavelmente um problema de localização
David
@David, funciona para mim com vírgulas. Talvez seja por causa das configurações de localidade.
Ondra Žižka
1
A questão é solicitar uma função para uso em scripts, enquanto esta solução fornece uma fórmula para uso em células.
markhep de
Solução realmente elegante.
Gabz
23

Isso funciona em intervalos A-Z

=char(64+column())

SauloAlessandre
fonte
3
Isso é bastante complicado para pessoas que não têm experiência em programação e não trabalharão em colunas além de "Z" (ou seja, "AA"), mas eu gosto mesmo assim porque é o cálculo mais curto e rápido (por exemplo, você poderia ter 1.000 vários deles indo ao mesmo tempo, sem que seu computador se esforce).
Dave
21

Não há necessidade de reinventar a roda aqui, use a linha GAS:

 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
fonte
6

Em 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
fonte
Gostaria que funcionasse nos scripts do Google, mas um pequeno pedaço de código incrível.
Giampaolo Ferradini de
1
@Giam Funciona no script de apps. Esta deve ser a resposta aceita
TheMaster
A partir daqui stackoverflow.com/questions/21229180/…
TheMaster
3

Somando-se à resposta de @SauloAlessandre, isso funcionará para colunas acima de A-ZZ.

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

Gosto das respostas de @wronex e @Ondra Žižka. No entanto, gosto muito da simplicidade da resposta de @SauloAlessandre.

Então, acabei de adicionar o código óbvio para permitir que a resposta de @SauloAlessandre funcione em planilhas mais amplas.

Como @Dave mencionou em seu comentário, é útil ter um background de programação, particularmente em C, onde adicionamos o valor hexadecimal de 'A' a um número para obter a enésima letra do alfabeto como um padrão padrão.

Resposta atualizada para detectar o erro apontado por @Sangbok Lee. Obrigado!

Jardineiro
fonte
1
Ele dá em @vez de Zquando usado na Zcoluna.
Sangbok Lee,
1
@Sangbok está correto! Isso foi atualizado e testado para as colunas Z, AA, AZ, BB. Acredito que funcionará através do ZZ.
Gardener de
2

Eu também estava procurando por uma versão Python aqui que foi testada em 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
fonte
1
X=lambda n:~n and X(n/26-1)+chr(65+n%26)or''
Ondra Žižka
Enfim, se não me engano, isso é base26. Complicado: próximo a Zdeveria ser AA. Isso dá BA.
Ondra Žižka
1
Sua versão está quase certa, acho que deveria ser: X=lambda n:~int(n) and X(int(n/26)-1)+chr(65+n%26)or''
hum3
Caramba, essa foi uma função lambda incrível que você tem aí, hum3. Obrigado!
ViggoTW
Obrigado, mas eu estava apenas depurando a solução do Ondra.
hum3
2

Estava procurando uma solução em PHP. Talvez isso ajude alguém.

<?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'));

Resultado:

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
fonte
1

Um comentário em minha resposta diz que você queria uma função de script para ele. Tudo bem, vamos lá:

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('');
}

Isso pode lidar com qualquer número que JS pode lidar, eu acho.

Explicação:

Como não é a base 26, precisamos subtrair a ordem dos tempos base para cada símbolo adicional ("dígito"). Portanto, primeiro contamos a ordem do número resultante e, ao mesmo tempo, contamos o número a ser subtraído. E então nós o convertemos para a base 26 e subtraímos isso, e então mudamos os símbolos para em A-Zvez de0-P .

De qualquer forma, essa questão está se transformando em um golfe de código :)

Ondra Žižka
fonte
0

Java Apache POI

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

Isso o cobrirá até a coluna 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
fonte
0

Aqui está uma versão geral escrita em Scala. É para um índice de coluna começar em 0 (é simples de modificar para um índice que começa em 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
fonte
0

Maneira simples por meio das funções do Google Sheet, de A a Z.

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

É uma maneira complicada de usar as funções do Planilhas Google, mas também é mais do que AA.

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

Uma função para converter um índice de coluna em combinações de letras, recursivamente:

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

Em python, existe a biblioteca gspread

import gspread
column_letter = gspread.utils.rowcol_to_a1(1, <put your col number here>)[:-1]

Se você não pode usar python, sugiro procurar o código-fonte de rowcol_to_a1 () em https://github.com/burnash/gspread/blob/master/gspread/utils.py

George C
fonte
-1

No 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
fonte
-2

Esta é uma versão com índice zero (em Python):

letters = []
while column >= 0:
    letters.append(string.ascii_uppercase[column % 26])
    column = column // 26 - 1
return ''.join(reversed(letters))
blas
fonte
Não é isso. A questão não é de base26. Eu também fui atraído originalmente :)
Ondra Žižka