Chuyển đổi chỉ mục cột thành ký tự cột tương ứng


86

Tôi cần chuyển đổi chỉ mục cột Bảng tính của Google thành giá trị chữ cái tương ứng của nó, ví dụ: cho một bảng tính:

nhập mô tả hình ảnh ở đây

Tôi cần làm điều này (chức năng này rõ ràng không tồn tại, đó là một ví dụ):

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

Bây giờ, tôi không nhớ chính xác chỉ mục bắt đầu từ 0hay từ 1, dù sao thì khái niệm này cũng phải rõ ràng.

Tôi không tìm thấy bất cứ điều gì về điều này trên tài liệu khí đốt .. tôi bị mù? Bất kỳ ý tưởng?

Cảm ơn bạn


14
Tại sao đây không phải là nội trang ??
Cyril Duchon-Doris,



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

Câu trả lời:


155

Tôi đã viết những điều này một thời gian trở lại cho các mục đích khác nhau (sẽ trả về tên cột gồm hai chữ cái cho số cột> 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
Tối đa có nhỏ hơn ZZ không?
Old Geezer

1
Chỉ cần sử dụng này để số cột increment: var column = letterToColumn(AA); columnToLetter(column + 1);. Có thể hữu ích cho ai đó.
joshfindit

1
Tôi đề nghị phải thay đổi column += (letter.charCodeAt(i) - 64) * Math.pow(26, length - i - 1);để column += (letter.toUpperCase().charCodeAt(i) - 64) * Math.pow(26, length - i - 1);làm cho nó làm việc nếu lettercó chứa chữ thường, nếu không cho anó sẽ ra 33thay vì1
tukusejssirs

fwiw - đây là cuộc phỏng vấn Q dành cho tôi tại một trong những Cos lớn
Taylor Halliday

Tôi nghĩ String.fromCharCodekhông hoạt động trên Apps Script
c-an

69

Điều này hoạt động tốt

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

ngay cả đối với các cột ngoài Z.

Demo chức năng

Chỉ cần thay thế COLUMN()bằng số cột của bạn. Giá trị của ROW()không quan trọng.


4
bạn đang sử dụng công thức chứ không phải GAS
BeNdErR

11
Điều này thực sự hoạt động tốt. Mặc dù điều này không sử dụng GAS (với câu hỏi được gắn thẻ), các chức năng tích hợp hầu như luôn được ưu tiên hơn vì chúng không cần phải viết và theo kinh nghiệm của tôi, chạy nhanh hơn đáng kể.
kevinmicke

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

Thao tác này sẽ lấy ô của bạn, lấy địa chỉ của nó như C1, và loại bỏ "1".

nhập mô tả hình ảnh ở đây

Làm thế nào nó hoạt động

  • COLUMN() cho biết số cột của ô.
  • ADDRESS(1, ..., <format>)cung cấp địa chỉ của một ô, ở định dạng được phát biểu bằng <format>tham số. 4có nghĩa là địa chỉ mà bạn biết - ví dụ C1.
    • Hàng không quan trọng ở đây, vì vậy chúng tôi sử dụng 1.
    • Xem ADDRESStài liệu
  • Cuối cùng, SUBSTITUTE(..., "1", "")thay thế 1địa chỉ trong địa chỉ C1, vì vậy bạn chỉ còn lại ký tự cột.

3
Đây là một giải pháp thanh lịch - tôi thích nó nhất. Không chắc tại sao nó không có nhiều lượt ủng hộ hơn.
kỳ dị

1
Tôi nhận được điều này khi thử: screencast.com/t/Jmc8L9W5LB . Tôi đã tìm ra điều này. Tôi đã giải quyết nó bằng cách thay thế tất cả dấu phẩy bằng dấu chấm phẩy. Đây có thể là vấn đề bản địa hóa
David

@David, Nó phù hợp với tôi với dấu phẩy. Có thể là do cài đặt ngôn ngữ.
Ondra Žižka

1
Câu hỏi đặt ra là yêu cầu một hàm để sử dụng trong các tập lệnh trong khi giải pháp này đưa ra một công thức để sử dụng trong các ô.
markhep

Giải pháp thực sự thanh lịch.
Gabz

23

Điều này hoạt động trên phạm vi A-Z

=char(64+column())


3
Điều này khá phức tạp đối với những người không có nền tảng về lập trình và sẽ không làm việc trên các cột vượt quá "Z" (tức là "AA") nhưng tôi thích nó vì nó là phép tính ngắn nhất và nhanh nhất (ví dụ: bạn có thể có 1.000 s trong số này diễn ra ngay lập tức mà máy tính của bạn không bị đổ mồ hôi).
Dave

21

Không cần phải phát minh lại bánh xe ở đây, thay vào đó hãy sử dụng phạm vi 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

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

Ước gì nó hoạt động trong các tập lệnh google, nhưng đoạn mã nhỏ tuyệt vời.
Giampaolo Ferradini

1
@Giam Nó hoạt động trong tập lệnh ứng dụng. Đây phải là câu trả lời được chấp nhận
TheMaster


3

Thêm vào câu trả lời của @ SauloAlessandre, điều này sẽ hoạt động đối với các cột từ A-ZZ.

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

Tôi thích câu trả lời của @wronex và @Ondra Žižka. Tuy nhiên, tôi thực sự thích sự đơn giản trong câu trả lời của @ SauloAlessandre.

Vì vậy, tôi vừa thêm mã rõ ràng để cho phép câu trả lời của @ SauloAlessandre hoạt động cho các bảng tính rộng hơn.

Như @Dave đã đề cập trong nhận xét của anh ấy, việc có một nền tảng lập trình, đặc biệt là nền tảng C, nơi chúng tôi đã thêm giá trị hex của 'A' vào một số để lấy chữ cái thứ n của bảng chữ cái làm mẫu chuẩn sẽ rất hữu ích.

Đã cập nhật câu trả lời để tìm ra lỗi do @Sangbok Lee chỉ ra. Cảm ơn bạn!


1
Nó cho @thay vì Zkhi được sử dụng trong Zcột.
Sangbok Lee

1
@Sangbok là chính xác! Điều này đã được cập nhật và thử nghiệm cho các cột Z, AA, AZ, BB. Tôi tin rằng nó sẽ hoạt động thông qua ZZ.
Người làm vườn

2

Tôi cũng đang tìm kiếm một phiên bản Python, đây là phiên bản của tôi đã được thử nghiệm trên 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žka

Dù sao, nếu tôi không nhầm thì đây là base26. Tricky: bên cạnh Znên được AA. Điều này mang lại cho BA.
Ondra Žižka

1
Phiên bản của bạn là gần đúng, tôi nghĩ rằng nó phải được: X=lambda n:~int(n) and X(int(n/26)-1)+chr(65+n%26)or''
hum3

Khỉ thật, đó là một hàm lambda tuyệt vời mà bạn có ở đó, hum3. Cảm ơn!
ViggoTW

Cảm ơn nhưng tôi chỉ đang gỡ lỗi giải pháp của Ondra.
hum3

2

Tôi đang tìm kiếm một giải pháp trong PHP. Có thể điều này sẽ giúp một ai đó.

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

Đầu ra:

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

Nhận xét về câu trả lời của tôi nói rằng bạn muốn có một chức năng script cho nó. Được rồi, chúng ta đi thôi:

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

Điều này có thể xử lý bất kỳ số nào JS có thể xử lý, tôi nghĩ.

Giải trình:

Vì đây không phải là cơ số26, chúng ta cần trừ thứ tự thời gian cơ sở cho mỗi ký hiệu bổ sung ("chữ số"). Vì vậy, đầu tiên chúng ta đếm thứ tự của số kết quả, và đồng thời đếm số để trừ. Và sau đó chúng tôi chuyển nó sang cơ sở 26 và trừ đi đó, và sau đó chuyển các biểu tượng để A-Zthay vì0-P .

Dù sao, câu hỏi này đang biến thành một cuộc chơi gôn mã :)


0

Java Apache POI

String columnLetter = CellReference.convertNumToColString(columnNumber);

0

Điều này sẽ bao quát bạn đến tận cột 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

Đây là một phiên bản chung được viết bằng Scala. Nó dành cho chỉ mục cột bắt đầu từ 0 (thật đơn giản để sửa đổi cho chỉ mục bắt đầu từ 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

Cách đơn giản thông qua các chức năng của Google Trang tính, từ A đến Z.

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

Đó là một cách phức tạp thông qua các chức năng của Google Trang tính, nhưng nó cũng hơn AA.

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

0

Một hàm để chuyển đổi một chỉ mục cột thành các kết hợp chữ cái, một cách đệ quy:

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

Trong 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

Đây là phiên bản không được lập chỉ mục (bằng Python):

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

Đây không phải là nó. Câu hỏi không phải là cơ sở26. Ban đầu tôi cũng bị thu hút vào điều đó :)
Ondra Žižka
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.