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

130

我需要将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开始,不过概念应该是清楚的。

我在gas文档中没有找到关于此事的任何信息.. 我瞎了吗?有什么想法吗?

谢谢


41
这为什么没有内置? - Cyril Duchon-Doris
2
请实现类似于 A、B、C、AA、AB、AAA 这样的编号方案,类似于将数字转换为 Excel 中的列名称。 - Ondra Žižka
2
X = (n) => (a=Math.floor(n/26)) >= 0 ? X(a-1) + String.fromCharCode(65+(n%26)) : ''; - Pascal DeMilly
@PascalDeMilly,你能解释一下如何使用吗?X接收字符串吗?列索引放在哪里? - Robert M.
24个回答

1

我也在寻找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

2
X=lambda n:~n and X(n/26-1)+chr(65+n%26)or'' - Ondra Žižka
无论如何,如果我没记错的话,这是26进制。棘手的是:在“Z”的旁边应该是“AA”。这就得到了BA。 - Ondra Žižka
1
你的版本几乎正确,我认为应该是:`X=lambda n:~int(n) and X(int(n/26)-1)+chr(65+n%26)or''` - hum3

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能处理的数字。

解释:

由于这不是基于26进制,我们需要对每个附加符号(“数字”)减去基数乘以顺序。因此,首先我们计算结果数字的顺序,并同时计算要减去的数字。然后将其转换为26进制并进行减法运算,然后将符号移位到A-Z而不是0-P

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


好主意。但是顺序错了。27 应该是 A,而不是 AA。703 应该是 BAA,而不是 AAA。 - Jehong Ahn
我的回答怎么样? :) - Jehong Ahn

0

简单的typescript函数式方法

const integerToColumn = (integer: number): string => {
  const base26 = (x: number): string =>
    x < 26
      ? String.fromCharCode(65 + x)
      : base26((x / 26) - 1) + String.fromCharCode(65 + x % 26)
  return base26(integer)
}

console.log(integerToColumn(0)) // "A"
console.log(integerToColumn(1)) // "B"
console.log(integerToColumn(2)) // "C"

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

=Address(1,4)

我将行号保持为1,以简化操作。
上述公式返回$D$1,这不是您想要的结果。
通过稍微修改公式,我们可以消除单元格引用中的美元符号。
=Address(1,4,4)

将四添加为第三个参数告诉公式我们不是在寻找绝对单元格引用。 现在返回值为:D1

因此,如果需要获取列字母,您只需要删除数字1,例如:

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

返回D


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

Java Apache POI

String columnLetter = CellReference.convertNumToColString(columnNumber);

0

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

=mmult(ArrayFormula(ifna(vlookup(substitute(mid(rept(" ",3-len(filter(A:A,A:A<>"")))&filter(A:A,A:A<>""),sequence(1,3),1)," ",""),{char(64+sequence(26)),sequence(26)},2,0),0)*{676,26,1}),sequence(3,1,1,0))

Google表格截图


0
不要使用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; }


迄今为止最好的 - Mike Steelson
1
很不错,我希望它能解决问题,但不幸的是它在“IZ”之后无法工作。在“IZ”之后的下一列应该是“JA”,但它返回“qA”,“qB”,“qC”等等... - inki
1
谢谢@inki。我已经修复了错误。26进制 - toString(26) - 不是一个好主意。AdamL的代码看起来很不错。 - Jehong Ahn

0

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

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>


这会返回A@而不是索引为26Z - ngr900

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接