Перетворити індекс стовпця на відповідну букву стовпця


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 = Мат. Поверх (n / 26))> = 0? X (a-1) + String.fromCharCode (65+ (n% 26)): '';
Паскаль Деміллі

Відповіді:


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?
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 для мене в одному з великих Cos
Тейлор

Я думаю, що String.fromCharCodeце не працює над Apps Script
c-an

69

Це працює добре

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

навіть для стовпців поза Z.

Демо-функція

Просто замініть COLUMN()на номер стовпця. Значення значення ROW()не має значення.


4
ви використовуєте формули, а не ГАЗ
BeNdErR

11
Це працює дуже добре. Незважаючи на те, що тут не використовується ГАЗ (з яким позначено питання), вбудовані функції майже завжди є кращими, оскільки їх взагалі не потрібно писати і, на мій досвід, вони працюють значно швидше.
kevinmicke

36
=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
Питання полягає у питанні функції для використання в сценаріях, тоді як це рішення дає формулу для використання в клітинках.
markhep

Дійсно елегантне рішення.
Gabz

23

Це працює на діапазонах A-Z

=char(64+column())


3
Це досить складно для людей, які не походять з програмування і не працюватимуть над стовпцями понад "Z" (тобто "AA"), але мені це все одно подобається, оскільки це найкоротший і найшвидший розрахунок (наприклад, у вас може бути 1000 з них відбувається одразу, а ваш комп’ютер не потіє).
Дейв

21

Тут не потрібно винаходити колесо, замість цього використовуйте діапазон ГАЗ:

 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, але дивовижний шматочок коду.
Джампаоло Феррадіні,

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, де ми додали шістнадцяткове значення 'A' до числа, щоб отримати n-ту літеру алфавіту як стандартний шаблон.

Відповідь оновлено, щоб виявити помилку, на яку вказав @Sangbok Lee. Дякую!


1
Він дає @замість того, Zколи використовується у Zстовпці.
Сангбок Лі,

1
@Sangbok правильний! Це оновлено та перевірено для стовпців 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žka

У всякому разі, якщо я не помиляюся, це база26. Хитро: поруч Zмає бути AA. Це дає Б.А.
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

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

POI Java Apache

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

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

Це не так. Питання не є базовим26. Я також спочатку заманувся на це :)
Ondra Žižka
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.