将列索引转换为相应的列号

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

enter image description here

我需要这样做(这个函数显然不存在,这是一个例子) :

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

现在,我不记得指数究竟是从 0开始还是从 1开始,无论如何,这个概念应该很清楚。

我在煤气文件里没找到任何关于这个的东西. . 我瞎了吗? 有什么想法吗?

谢谢你

105168 次浏览

我之前为了不同的目的编写了这些代码(将返回列号 > 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;
}

效果不错

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

even for columns beyond Z.

Demo of function

只需将 COLUMN()替换为您的列号。 ROW()的值并不重要。

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

这会获取您的单元格,获取它的地址,例如 C1,并删除“1”。

enter image description here

它是如何工作的

  • COLUMN()给出单元格的列号。
  • ADDRESS(1, ..., <format>)给出一个单元格的地址,格式由 <format>参数指定。4表示你知道的地址,例如 C1
    • 行在这里并不重要,所以我们使用 1
    • ADDRESS文件
  • 最后,SUBSTITUTE(..., "1", "")替换地址 C1中的 1,因此只剩下列字母。

This works on ranges A-Z

公式 =char(64+column())

Js String.fromCharCode(64+colno)

基于@Gardener 的 google 电子表格应用程序代码如下:

function columnName(index) {
var cname = String.fromCharCode(65 + ((index - 1) % 26));
if (index > 26)
cname = String.fromCharCode(64 + (index - 1) / 26) + cname;
return cname;
}

下面是一个零索引版本(在 Python 中) :

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

Java Apache POI

String columnLetter = CellReference.convertNumToColString(columnNumber);

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

我也在这里寻找一个 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

No need to reinvent the wheel here, use the GAS range instead:

 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"

添加到@SauloAlessandre 的回答中,这将适用于从 A-ZZ 开始的专栏。

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

我喜欢@wronex 和@Ondra i ka 的回答,但是,我真的很喜欢@SauloAlessandre 简洁的回答。

So, I just added the obvious code to allow @SauloAlessandre's answer to work for wider spreadsheets.

正如@Dave 在他的评论中提到的,有一个编程背景的确很有帮助,特别是在 C 语言中,我们将‘ A’的十六进制值添加到一个数字中,以获得字母表中的第 n 个字母作为标准模式。

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

下面是用 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)
}

我的回答中有一条评论说你需要一个脚本函数,好了,开始吧:

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

不管怎样,这个问题正在变成一个高尔夫密码:)

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

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


通过谷歌工作表函数的简单方法,从 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

这是一个复杂的方式通过谷歌工作表的功能,但它也超过 AA。

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

我正在寻找一个 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)

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

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

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


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


document.getElementById("result1").innerHTML = lettersFromIndex(32);
document.getElementById("result2").innerHTML = lettersFromIndex(6800);
document.getElementById("result3").innerHTML = lettersFromIndex(9007199254740991);
32 --> <span id="result1"></span><br> 6800 --> <span id="result2"></span><br> 9007199254740991 --> <span id="result3"></span>

In python, there is the gspread library

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

如果不能使用 python,我建议在 https://github.com/burnash/gspread/blob/master/gspread/utils.py中查看 rowcol _ to _ a1()的源代码

下面是一个使用递归在 ZZ 之外工作的两行程序:

巨蟒

def col_to_letter(n):
l = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
return col_to_letter((n-1)//26) + col_to_letter(n%26) if n > 26 else l[n-1]

Javascript

function colToLetter(n) {
l = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
return n > 26 ? colToLetter(Math.floor((n-1)/26)) + colToLetter(n%26) : l[n-1]
}

不要使用26基数。像下面这样。

const n2c = n => {
if (!n) return '';
  

// Column number to 26 radix. From 0 to p.
// Column number starts from 1. Subtract 1.
return [...(n-1).toString(26)]
// to ascii number
.map(c=>c.charCodeAt())
.map((c,i,arr)=> {
// last digit
if (i===arr.length-1) return c;
// 10 -> p
else if (arr.length - i > 2 && arr[i+1]===48) return c===49 ? null : c-2;
// 0 -> p
else if (c===48) return 112;
// a-1 -> 9
else if (c===97) return 57;
// Subtract 1 except last digit.
// Look at 10. This should be AA not BA.
else return c-1;
})
.filter(c=>c!==null)
// Convert with the ascii table. [0-9]->[A-J] and [a-p]->[K-Z]
.map(a=>a>96?a-22:a+17)
// to char
.map(a=>String.fromCharCode(a))
.join('');
};




const table = document.createElement('table');
table.border = 1;
table.cellPadding = 3;
for(let i=0, row; i<1380; i++) {
if (i%5===0) row = table.insertRow();
row.insertCell().textContent = i;
row.insertCell().textContent = n2c(i);
}
document.body.append(table);
td:nth-child(odd) { background: gray; color: white; }
td:nth-child(even) { background: silver; }

下面是一个没有最大值的0索引 JavaScript 函数,因为它使用了 while 循环:

function indexesToA1Notation(row, col) {
const letterCount = 'Z'.charCodeAt() - 'A'.charCodeAt() + 1;
row += 1
let colName = ''
while (col >= 0) {
let rem = col % letterCount
colName = String.fromCharCode('A'.charCodeAt() + rem)
col -= rem
col /= letterCount
}
return `${colName}${row}`
}


//Test runs:
console.log(indexesToA1Notation(0,0)) //A1
console.log(indexesToA1Notation(37,9)) //J38
console.log(indexesToA1Notation(5,747)) //ABT6

I wrote it for a web-app, so I'm not 100% sure it works in Google Apps Script, but it is normal JavaScript, so I assume it will.

由于某种原因,我无法让代码片段显示其输出,但是如果您愿意,可以将代码复制到某个在线操场

如果你需要一个直接在表格中的版本,这里有一个解决方案: 对于4号通道,我们可以使用:

=Address(1,4)

为了简单起见,我将行号保持为1。 上面的公式返回 $1,这不是你想要的。

通过稍微修改一下公式,我们可以删除单元格引用中的美元符号。

=Address(1,4,4)

添加4作为第三个参数告诉公式我们不需要绝对单元格引用。 Now the returns is : D1

因此,如果需要,只需删除1就可以得到柱头字母,例如:

=Substitute(Address(1,4,4),"1","")

返回 D

这是一种将列字母转换为列号的方法。

= mmult (数组公式(ifna (vlookup)(替换(mid (rept (“”,3-len (filter (A: A: A: A < >”))) & filter (A: A,A: A < > “”)) ,序列(1,3) ,1) ,“”,“”) ,{ char (64 + 数组(26)) ,序列(26)} ,2,0) ,0) * {676,26,1}) ,序列(3,1,1,0)))

谷歌工作表的屏幕截图