แปลงดัชนีคอลัมน์เป็นตัวอักษรคอลัมน์ที่สอดคล้องกัน


88

ฉันต้องการแปลงดัชนีคอลัมน์สเปรดชีตของ Google เป็นค่าตัวอักษรที่สอดคล้องกันตัวอย่างเช่นให้สเปรดชีต:

ป้อนคำอธิบายภาพที่นี่

ฉันต้องทำสิ่งนี้ (ฟังก์ชั่นนี้ไม่มีอยู่จริงเป็นตัวอย่าง):

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

ตอนนี้ฉันจำไม่ได้ว่าดัชนีเริ่มต้นจาก0หรือจาก1อย่างไรก็ตามแนวคิดควรจะชัดเจน

ฉันไม่พบอะไรเกี่ยวกับเรื่องนี้ในเอกสารเกี่ยวกับก๊าซ .. ฉันตาบอดหรือเปล่า? ความคิดใด ๆ ?

ขอขอบคุณ


17
ทำไมถึงไม่ได้บิวอิน ??
Cyril Duchon-Doris


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

คำตอบ:


158

ฉันเขียนสิ่งเหล่านี้ในขณะที่กลับมาเพื่อวัตถุประสงค์ต่างๆ (จะส่งคืนชื่อคอลัมน์ตัวอักษรคู่สำหรับหมายเลขคอลัมน์> 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 หรือไม่?
Old Geezer

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

fwiw - นี่คือบทสัมภาษณ์ Q สำหรับฉันที่หนึ่งในคอสใหญ่
Taylor Halliday

ฉันคิดว่าใช้String.fromCharCodeไม่ได้กับ Apps Script
c-an

70

ทำงานได้ดี

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

แม้แต่คอลัมน์ที่อยู่นอกเหนือ Z

การสาธิตฟังก์ชัน

เพียงแทนที่COLUMN()ด้วยหมายเลขคอลัมน์ของคุณ คุณค่าของROW()ไม่สำคัญ


4
คุณกำลังใช้สูตรไม่ใช่ GAS
BeNdErR

11
นี่ใช้งานได้ดีจริงๆ แม้ว่าจะไม่ได้ใช้ GAS (ซึ่งมีการติดแท็กคำถาม) แต่ฟังก์ชันในตัวมักจะเป็นที่ต้องการเนื่องจากไม่จำเป็นต้องเขียนเลยและจากประสบการณ์ของฉันฉันทำงานได้เร็วขึ้นมาก
kevinmicke

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

สิ่งนี้จะนำเซลล์ของคุณรับที่อยู่เป็นเช่น C1 และลบ "1"

ป้อนคำอธิบายภาพที่นี่

มันทำงานอย่างไร

  • COLUMN() ให้จำนวนคอลัมน์ของเซลล์
  • ADDRESS(1, ..., <format>)ให้ที่อยู่ของเซลล์ในรูปแบบที่ระบุโดย<format>พารามิเตอร์ 4หมายถึงที่อยู่ที่คุณรู้ - C1เช่น
    • 1แถวที่ไม่ได้เรื่องที่นี่เพื่อให้เราใช้
    • ดูADDRESSเอกสาร
  • สุดท้ายSUBSTITUTE(..., "1", "")แทนที่1ในที่อยู่C1ดังนั้นคุณจะเหลือตัวอักษรคอลัมน์

3
นี่เป็นวิธีการแก้ปัญหาที่สวยงาม - ฉันชอบที่สุด ไม่แน่ใจว่าทำไมจึงไม่มีการโหวตเพิ่มขึ้น
เอกพจน์

1
ผมได้รับนี้เมื่อพยายาม: screencast.com/t/Jmc8L9W5LB ฉันคิดออกแล้ว ฉันแก้ไขได้โดยแทนที่เครื่องหมายจุลภาคทั้งหมดด้วยเครื่องหมายกึ่งโคลอน นี่อาจเป็นปัญหาการแปล
David

@ เดวิดมันใช้ได้กับฉันด้วยเครื่องหมายจุลภาค อาจเป็นเพราะการตั้งค่าโลแคล
Ondra Žižka

1
คำถามกำลังถามหาฟังก์ชันสำหรับใช้ในสคริปต์ในขณะที่โซลูชันนี้ให้สูตรสำหรับใช้ในเซลล์
Markshep

โซลูชันที่หรูหราจริงๆ
Gabz

23

สิ่งนี้ใช้ได้กับช่วง A-Z

=char(64+column())


4
สิ่งนี้ค่อนข้างยุ่งยากสำหรับผู้ที่ไม่ได้มาจากพื้นฐานการเขียนโปรแกรมและจะไม่ทำงานในคอลัมน์ที่เกิน "Z" (เช่น "AA") แต่ฉันก็ชอบอยู่ดีเพราะเป็นการคำนวณที่สั้นและเร็วที่สุด (เช่นคุณอาจมี 1,000 สิ่งเหล่านี้จะเกิดขึ้นพร้อมกันโดยที่คอมพิวเตอร์ของคุณไม่ต้องเสียเหงื่อ)
Dave

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"



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 ที่เราเพิ่มค่าฐานสิบหกของ 'A' ลงในตัวเลขเพื่อให้ได้ตัวอักษรที่ n เป็นรูปแบบมาตรฐาน

คำตอบที่อัปเดตเพื่อตรวจจับข้อผิดพลาดที่แจ้งโดย @Sangbok Lee ขอขอบคุณ!


1
ให้@แทนZเมื่อใช้ในZคอลัมน์
Sangbok Lee

1
@ แสงบกถูกต้อง! สิ่งนี้ได้รับการอัปเดตและทดสอบสำหรับคอลัมน์ Z, AA, AZ, BB ฉันเชื่อว่ามันจะทำงานผ่าน ZZ
สวน

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

ฉันกำลังมองหาเวอร์ชัน 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žka

อย่างไรก็ตามถ้าผมจำไม่ผิดนี่คือ base26 หากิน: ต่อไปควรจะเป็นZ AAนี้ให้ BA
Ondra Žižka

1
เวอร์ชันของคุณเกือบถูกต้องฉันคิดว่าควรจะเป็น: X=lambda n:~int(n) and X(int(n/26)-1)+chr(65+n%26)or''
hum3

อึศักดิ์สิทธิ์นั่นเป็นฟังก์ชั่นแลมด้าที่น่าทึ่งที่คุณไปถึงที่นั่น hum3. ขอบคุณ!
ViggoTW

ขอบคุณ แต่ฉันเพิ่งแก้ไขข้อบกพร่องของโซลูชันของ Ondra
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-Z0-P

อย่างไรก็ตามคำถามนี้กลายเป็น code golf :)



0

วิธีง่ายๆผ่านฟังก์ชั่น Google Sheet 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

นี่คือเวอร์ชันทั่วไปที่เขียนด้วย 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)
}


-2

นี่คือเวอร์ชันที่ไม่มีดัชนี (ใน Python):

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

นี่ไม่ใช่เลย คำถามไม่ใช่ฐาน 26 แต่เดิมฉันก็ถูกล่อเข้าไปเช่นกัน :)
Ondra Žižka
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.