将列索引转换为相应的列字母


86

我需要将Google Spreadsheet列索引转换为其相应的字母值,例如,给定一个电子表格:

在此处输入图片说明

我需要这样做(此功能显然不存在,这是一个示例):

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

现在,我不记得确切的索引是从0还是从开始1,无论如何概念应该很清楚。

我在加油站的文档中没找到关于此的任何信息。任何的想法?

谢谢


14
为什么这不是内置的?
西里尔·杜尚·多丽丝



1
X =(n)=>(a = Math.floor(n / 26))> = 0?X(a-1)+ String.fromCharCode(65+(n%26)):'';
Pascal DeMilly

Answers:


154

我前些时候出于各种目的写了这些(将为列号> 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;
}

1
最大值小于ZZ吗?
老盖泽

1
只是用于增加列号:var column = letterToColumn(AA); columnToLetter(column + 1);。可能对某人有帮助。
joshfindit

1
我建议更改column += (letter.charCodeAt(i) - 64) * Math.pow(26, length - i - 1);column += (letter.toUpperCase().charCodeAt(i) - 64) * Math.pow(26, length - i - 1);使其在letter包含小写字母的情况下起作用,否则a它将输出33而不是1
tukusejssirs

首先-这是我在其中一个大型Cos上接受的采访Q
Taylor Halliday

我认为String.fromCharCode这不适用于Apps Script
c-an

69

这很好

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

即使对于Z以外的列。

功能演示

只需COLUMN()用您的列号替换即可。的值ROW()无关紧要。


4
您使用的是公式,而不是气体
-BeNdErR 2014年

11
这真的很好。即使这没有使用GAS(带有问题的标签),但内置函数几乎总是可取的,因为它们根本不需要编写,并且根据我的经验,运行速度明显更快。
kevinmicke '16

36
=SUBSTITUTE(ADDRESS(1,COLUMN(),4), "1", "")

这将获取您的单元格,获取其地址,例如C1,然后删除“ 1”。

在此处输入图片说明

这个怎么运作

  • COLUMN() 给出单元格的列号。
  • ADDRESS(1, ..., <format>)<format>参数指定的格式给出单元格的地址。4表示您知道的地址-例如C1
    • 该行在这里无关紧要,因此我们使用1
    • 查看ADDRESS文件
  • 最后,SUBSTITUTE(..., "1", "")替换1address中的C1,因此您将剩下列字母。

3
这是一个优雅的解决方案-我最喜欢它。不知道为什么它没有更多的投票。
奇点,2016年

1
我在尝试时得到了这个:screencast.com/t/Jmc8L9W5LB。我想通了。我通过用分号替换所有逗号来解决它。这可能是一个本地化问题
David

@David,它对我有用逗号。也许是因为区域设置。
OndraŽižka'16

1
问题是要求在脚本中使用一个函数,而此解决方案给出了在单元格中使用的公式。
markhep

真正优雅的解决方案。
加布兹

23

这适用于范围 A-Z

=char(64+column())


3
对于那些不是来自编程背景并且不会在“ Z”(即“ AA”)以外的列上工作的人来说,这是非常棘手的,但是无论如何我都喜欢它,因为它是最短和最快的计算(例如,您可以拥有1,000无需计算机耗费大量精力即可立即完成这些操作)。
戴夫

21

无需在这里重新发明轮子,而是使用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"


6

在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')

希望它能在Google脚本中正常工作,但是却能完成很少的代码。
Giampaolo Ferradini

1
@Giam在应用程序脚本中有效。这应该是公认的答案
TheMaster


3

添加到@SauloAlessandre的答案中,这将适用于A-ZZ以后的列。

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

我喜欢@wronex和@OndraŽižka的答案。但是,我非常喜欢@SauloAlessandre的答案的简单性。

因此,我只添加了显而易见的代码,以允许@SauloAlessandre的答案适用于更广泛的电子表格。

正如@Dave在他的评论中提到的那样,它确实有助于编程背景,尤其是C语言中的背景,我们在数字C中添加了十六进制值“ A”,以使字母的第n个字母成为标准模式。

更新了答案,以捕获@Sangbok Lee指出的错误。谢谢!


1
它给出@而不是ZZ列中使用时。
李尚福'18

1
@尚福是正确的!已针对Z,AA,AZ,BB列进行了更新和测试。我相信它将通过ZZ起作用。
园丁

2

我也在寻找Python版本,这是我的版本,该版本已在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

1
X=lambda n:~n and X(n/26-1)+chr(65+n%26)or''
OndraŽižka17年

无论如何,如果我没记错的话,这就是base26。整rick:旁边Z应该是AA。这给了BA。
OndraŽižka17年

1
您的版本几乎是正确的,我认为应该是: X=lambda n:~int(n) and X(int(n/26)-1)+chr(65+n%26)or''
hum3

哎呀,这真是令人惊奇的lambda函数,hum3。谢谢!
ViggoTW

谢谢,但是我只是调试Ondra的解决方案。
hum3

2

我一直在寻找PHP中的解决方案。也许这会帮助某人。

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

输出:

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

1

关于我的答案的评论说,您想要一个脚本功能。好吧,我们开始:

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

我认为这可以处理JS可以处理的任何数字。

说明:

由于这不是base26,因此我们需要减去每个附加符号(“数字”)的基本时间顺序。因此,首先我们计算得出的数字的顺序,同时计算要减去的数字。然后将其转换为26底并减去,然后将符号移动到A-Z而不是0-P

无论如何,这个问题正在变成一个代码高尔夫:)


0

Java Apache POI

String columnLetter = CellReference.convertNumToColString(columnNumber);

0

这将覆盖到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")

0

这是用Scala编写的通用版本。它用于从0开始的列索引(对于从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)
}

0

通过Google表格功能(从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

这是使用Google Sheet函数的复杂方法,但它不仅限于AA。

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

0

递归将列索引转换为字母组合的函数:

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



-1

在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)))"
}


-2

这是零索引版本(在Python中):

letters = []
while column >= 0:
    letters.append(string.ascii_uppercase[column % 26])
    column = column // 26 - 1
return ''.join(reversed(letters))

不是吗 问题不是base26。我最初也很喜欢它:)
OndraŽižka17年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.