Muszę przekonwertować indeks kolumn arkusza kalkulacyjnego Google na odpowiadające mu wartości literowe, na przykład mając arkusz kalkulacyjny:
Muszę to zrobić (ta funkcja oczywiście nie istnieje, to przykład):
getColumnLetterByIndex(4); // this should return "D"
getColumnLetterByIndex(1); // this should return "A"
getColumnLetterByIndex(6); // this should return "F"
Teraz nie pamiętam dokładnie, czy indeks zaczyna się od, 0
czy od 1
, w każdym razie koncepcja powinna być jasna.
Nie znalazłem nic na ten temat w dokumentacji gazu .. czy jestem ślepy? Dowolny pomysł?
Dziękuję Ci
Odpowiedzi:
Napisałem je jakiś czas temu w różnych celach (zwróci dwuliterowe nazwy kolumn dla numerów kolumn> 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; }
źródło
var column = letterToColumn(AA);
columnToLetter(column + 1);
. Może komuś pomóc.column += (letter.charCodeAt(i) - 64) * Math.pow(26, length - i - 1);
sięcolumn += (letter.toUpperCase().charCodeAt(i) - 64) * Math.pow(26, length - i - 1);
, aby to działało, jeśliletter
zawiera małe litery, inaczeja
to będzie wyjście33
zamiast1
String.fromCharCode
nie działa na Apps ScriptTo działa dobrze
=REGEXEXTRACT(ADDRESS(ROW(); COLUMN()); "[A-Z]+")
nawet dla kolumn poza Z.
Po prostu zastąp
COLUMN()
swoim numerem kolumny. WartośćROW()
nie ma znaczenia.źródło
=SUBSTITUTE(ADDRESS(1,COLUMN(),4), "1", "")
To zabiera twoją komórkę, pobiera jej adres np. C1 i usuwa "1".
Jak to działa
COLUMN()
podaje numer kolumny komórki.ADDRESS(1, ..., <format>)
podaje adres komórki w formacie określonym przez<format>
parametr.4
oznacza adres, który znasz - npC1
.1
.ADDRESS
dokumentacjęSUBSTITUTE(..., "1", "")
zastępuje1
w adresieC1
, więc zostajesz z literą kolumny.źródło
Działa to na zakresach
A-Z
źródło
Nie musisz wymyślać koła na nowo, zamiast tego użyj gamy 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"
źródło
W 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')
źródło
Dodając do odpowiedzi @ SauloAlessandre, będzie to działać dla kolumn od A do ZZ.
=if(column() >26,char(64+(column()-1)/26),) & char(65 + mod(column()-1,26))
Lubię odpowiedzi @wronex i @Ondra Žižka. Jednak naprawdę podoba mi się prostota odpowiedzi @ SauloAlessandre.
Dlatego właśnie dodałem oczywisty kod, aby odpowiedź @ SauloAlessandre działała dla szerszych arkuszy kalkulacyjnych.
Jak @Dave wspomniał w swoim komentarzu, dobrze jest mieć tło programistyczne, szczególnie takie w C, gdzie dodaliśmy szesnastkową wartość „A” do liczby, aby otrzymać n-tą literę alfabetu jako standardowy wzorzec.
Zaktualizowano odpowiedź, aby wychwycić błąd wskazany przez @Sangbok Lee. Dziękuję Ci!
źródło
@
zamiast,Z
gdy jest używany wZ
kolumnie.Szukałem również wersji Pythona tutaj jest moja, która była testowana na Pythonie 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
źródło
X=lambda n:~n and X(n/26-1)+chr(65+n%26)or''
Z
powinien byćAA
. To daje BA.X=lambda n:~int(n) and X(int(n/26)-1)+chr(65+n%26)or''
Szukałem rozwiązania w PHP. Może to komuś pomoże.
<?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'));
Wynik:
NULL string(1) "Z" string(2) "AA" string(2) "AD" int(1) int(1) int(2) int(25) int(26) int(27) int(28)
źródło
Komentarz do mojej odpowiedzi mówi, że chciałeś do tego funkcji skryptu. W porządku, zaczynamy:
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(''); }
Myślę, że to poradzi sobie z każdą liczbą, którą może obsłużyć JS.
Wyjaśnienie:
Ponieważ nie jest to podstawa26, musimy odjąć kolejność czasów bazowych dla każdego dodatkowego symbolu („cyfry”). Więc najpierw liczymy kolejność wynikowej liczby i jednocześnie liczymy liczbę do odjęcia. Następnie konwertujemy to na podstawę 26 i odejmujemy to, a następnie przenosimy symbole na
A-Z
zamiast0-P
.Zresztą to pytanie zamienia się w kod golfa :)
źródło
Java Apache POI
String columnLetter = CellReference.convertNumToColString(columnNumber);
źródło
To obejmie cię aż do kolumny 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")
źródło
Oto ogólna wersja napisana w Scali. Jest dla indeksu kolumny zaczynającego się od 0 (można go łatwo zmodyfikować, aby indeks zaczynał się od 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) }
źródło
Prosty sposób na funkcje Arkusza Google, od A do Z.
=column(B2) : value is 2 =address(1, column(B2)) : value is $B$1 =mid(address(1, column(B2)),2,1) : value is B
To skomplikowany sposób korzystania z funkcji Arkusza Google, ale to także coś więcej niż AA.
=mid(address(1, column(AB3)),2,len(address(1, column(AB3)))-3) : value is AB
źródło
Funkcja do rekurencyjnej konwersji indeksu kolumn na kombinacje liter:
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; }
Pokaż fragment kodu
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>
źródło
W Pythonie jest biblioteka gspread
import gspread column_letter = gspread.utils.rowcol_to_a1(1, <put your col number here>)[:-1]
Jeśli nie możesz użyć Pythona, sugeruję sprawdzenie kodu źródłowego rowcol_to_a1 () w https://github.com/burnash/gspread/blob/master/gspread/utils.py
źródło
W 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)))" }
źródło
Oto wersja indeksowana przez zero (w Pythonie):
letters = [] while column >= 0: letters.append(string.ascii_uppercase[column % 26]) column = column // 26 - 1 return ''.join(reversed(letters))
źródło