Hvordan konvertere et kolonnenummer (f.eks. 127) i en excel-kolonne (f.eks. AA)

stemmer
402

Hvordan konverterer du en numerisk nummer en Excel-kolonnenavn i C # til uten å bruke automatisering får verdien direkte fra Excel.

Excel 2007 har en mulig spekter av 1-16384, som er antall kolonner som støttes. De resulterende verdier bør være i form av Excel kolonnenavnene, f.eks A, AA, AAA etc.

Publisert på 08/10/2008 klokken 04:55
kilden bruker
På andre språk...                            


53 svar

stemmer
9
int nCol = 127;
string sChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string sCol = "";
while (nCol >= 26)
{
    int nChar = nCol % 26;
    nCol = (nCol - nChar) / 26;
    // You could do some trick with using nChar as offset from 'A', but I am lazy to do it right now.
    sCol = sChars[nChar] + sCol;
}
sCol = sChars[nCol] + sCol;

Oppdatering : Peter 's kommentar er rett. Det er hva jeg får for å skrive kode i nettleseren. :-) Min løsning ikke ble kompilering, var det mangler lengst til venstre brev, og det var å bygge strengen i motsatt rekkefølge - alle nå fikset.

Insekter side er algoritmen som i utgangspunktet å konvertere et tall fra basis 10 til basedelen 26.

Oppdater 2 : Joel Coehoorn er rett - koden ovenfor vil returnere AB for 27. Hvis det var ekte basen 26 tall, ville AA være lik A og neste nummer etter Z ville være BA.

int nCol = 127;
string sChars = "0ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string sCol = "";
while (nCol > 26)
{
    int nChar = nCol % 26;
    if (nChar == 0)
        nChar = 26;
    nCol = (nCol - nChar) / 26;
    sCol = sChars[nChar] + sCol;
}
if (nCol != 0)
    sCol = sChars[nCol] + sCol;
Svarte 08/10/2008 kl. 05:04
kilden bruker

stemmer
9

Easy med rekursjon.

public static string GetStandardExcelColumnName(int columnNumberOneBased)
{
  int baseValue = Convert.ToInt32('A');
  int columnNumberZeroBased = columnNumberOneBased - 1;

  string ret = "";

  if (columnNumberOneBased > 26)
  {
    ret = GetStandardExcelColumnName(columnNumberZeroBased / 26) ;
  }

  return ret + Convert.ToChar(baseValue + (columnNumberZeroBased % 26) );
}
Svarte 08/10/2008 kl. 06:24
kilden bruker

stemmer
20

Beklager, dette er Python i stedet for C #, men minst resultatene er riktige:

def ColIdxToXlName(idx):
    if idx < 1:
        raise ValueError("Index is too small")
    result = ""
    while True:
        if idx > 26:
            idx, r = divmod(idx - 1, 26)
            result = chr(r + ord('A')) + result
        else:
            return chr(idx + ord('A') - 1) + result


for i in xrange(1, 1024):
    print "%4d : %s" % (i, ColIdxToXlName(i))
Svarte 08/10/2008 kl. 08:09
kilden bruker

stemmer
777

Her er hvordan jeg gjør det:

private string GetExcelColumnName(int columnNumber)
{
    int dividend = columnNumber;
    string columnName = String.Empty;
    int modulo;

    while (dividend > 0)
    {
        modulo = (dividend - 1) % 26;
        columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
        dividend = (int)((dividend - modulo) / 26);
    } 

    return columnName;
}
Svarte 08/10/2008 kl. 12:01
kilden bruker

stemmer
3
private String getColumn(int c) {
    String s = "";
    do {
        s = (char)('A' + (c % 26)) + s;
        c /= 26;
    } while (c-- > 0);
    return s;
}

Det er ikke akkurat basen 26, er det ingen 0 i systemet. Hvis det var, ville 'Z' bli etterfulgt av 'BA' ikke med 'AA'.

Svarte 03/11/2008 kl. 21:00
kilden bruker

stemmer
0

Jeg bruker denne i VB.NET 2003, og det fungerer bra ...

Private Function GetExcelColumnName(ByVal aiColNumber As Integer) As String
    Dim BaseValue As Integer = Convert.ToInt32(("A").Chars(0)) - 1
    Dim lsReturn As String = String.Empty

    If (aiColNumber > 26) Then
        lsReturn = GetExcelColumnName(Convert.ToInt32((Format(aiColNumber / 26, "0.0").Split("."))(0)))
    End If

    GetExcelColumnName = lsReturn + Convert.ToChar(BaseValue + (aiColNumber Mod 26))
End Function
Svarte 04/11/2008 kl. 15:26
kilden bruker

stemmer
0

Hvis du ønsker å referere cellen progmatically så vil du få mye mer lesbar kode hvis du bruker Cells metoden av et ark. Det tar en rad og kolonne indeks i stedet for en Model cellereferanse. Det er svært lik den Offset metode.

Svarte 21/11/2008 kl. 20:28
kilden bruker

stemmer
53

Hvis noen trenger å gjøre dette i Excel uten VBA, her er en måte:

=SUBSTITUTE(ADDRESS(1;colNum;4);"1";"")

hvor colNum er kolonnenummeret

Og i VBA:

Function GetColumnName(colNum As Integer) As String
    Dim d As Integer
    Dim m As Integer
    Dim name As String
    d = colNum
    name = ""
    Do While (d > 0)
        m = (d - 1) Mod 26
        name = Chr(65 + m) + name
        d = Int((d - m) / 26)
    Loop
    GetColumnName = name
End Function
Svarte 30/01/2009 kl. 12:25
kilden bruker

stemmer
0

Ved hjelp av dette i VB.Net 2005:

Private Function ColumnName(ByVal ColumnIndex As Integer) As String

   Dim Name As String = ""

   Name = (New Microsoft.Office.Interop.Owc11.Spreadsheet).Columns.Item(ColumnIndex).Address(False, False, Microsoft.Office.Interop.Owc11.XlReferenceStyle.xlA1)
   Name = Split(Name, ":")(0)

   Return Name

End Function
Svarte 11/06/2009 kl. 12:55
kilden bruker

stemmer
2

Avgrense den opprinnelige løsningen (i C #):

public static class ExcelHelper
{
    private static Dictionary<UInt16, String> l_DictionaryOfColumns;

    public static ExcelHelper() {
        l_DictionaryOfColumns = new Dictionary<ushort, string>(256);
    }

    public static String GetExcelColumnName(UInt16 l_Column)
    {
        UInt16 l_ColumnCopy = l_Column;
        String l_Chars = "0ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        String l_rVal = "";
        UInt16 l_Char;


        if (l_DictionaryOfColumns.ContainsKey(l_Column) == true)
        {
            l_rVal = l_DictionaryOfColumns[l_Column];
        }
        else
        {
            while (l_ColumnCopy > 26)
            {
                l_Char = l_ColumnCopy % 26;
                if (l_Char == 0)
                    l_Char = 26;

                l_ColumnCopy = (l_ColumnCopy - l_Char) / 26;
                l_rVal = l_Chars[l_Char] + l_rVal;
            }
            if (l_ColumnCopy != 0)
                l_rVal = l_Chars[l_ColumnCopy] + l_rVal;

            l_DictionaryOfColumns.ContainsKey(l_Column) = l_rVal;
        }

        return l_rVal;
    }
}
Svarte 27/07/2009 kl. 13:20
kilden bruker

stemmer
0

En annen løsning:

private void Foo()
{
   l_ExcelApp = new Excel.ApplicationClass();
   l_ExcelApp.ReferenceStyle = Excel.XlReferenceStyle.xlR1C1;
   // ... now reference by R[row]C[column], Ex. A1 <==> R1C1, C6 <==> R3C6, ...
}

se mer her - Cell referanser i Excel for alle! av Dr Nitin Paranjape

Svarte 27/07/2009 kl. 13:35
kilden bruker

stemmer
6

..Og konvertert til php:

function GetExcelColumnName($columnNumber) {
    $columnName = '';
    while ($columnNumber > 0) {
        $modulo = ($columnNumber - 1) % 26;
        $columnName = chr(65 + $modulo) . $columnName;
        $columnNumber = (int)(($columnNumber - $modulo) / 26);
    }
    return $columnName;
}
Svarte 17/12/2009 kl. 20:17
kilden bruker

stemmer
0
public static string ConvertToAlphaColumnReferenceFromInteger(int columnReference)
    {
        int baseValue = ((int)('A')) - 1 ;
        string lsReturn = String.Empty; 

        if (columnReference > 26) 
        {
            lsReturn = ConvertToAlphaColumnReferenceFromInteger(Convert.ToInt32(Convert.ToDouble(columnReference / 26).ToString().Split('.')[0]));
        } 

        return lsReturn + Convert.ToChar(baseValue + (columnReference % 26));            
    }
Svarte 18/03/2010 kl. 16:17
kilden bruker

stemmer
2

Her er et Actionscript versjon:

private var columnNumbers:Array = ['A', 'B', 'C', 'D', 'E', 'F' , 'G', 'H', 'I', 'J', 'K' ,'L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];

    private function getExcelColumnName(columnNumber:int) : String{
        var dividend:int = columnNumber;
        var columnName:String = "";
        var modulo:int;

        while (dividend > 0)
        {
            modulo = (dividend - 1) % 26;
            columnName = columnNumbers[modulo] + columnName;
            dividend = int((dividend - modulo) / 26);
        } 

        return columnName;
    }
Svarte 29/03/2010 kl. 12:37
kilden bruker

stemmer
15

Du må kanskje konvertering begge veier, for eksempel fra Excel kolonne adresse som AAZ til heltall og fra alle heltall til Excel. De to metodene nedenfor vil gjøre nettopp det. Forutsetter en basert indeksering, første elementet i din "arrays" er element nummer 1. Ingen begrensninger på størrelsen her, så du kan bruke adresser som ERROR og det ville være kolonnenummer 2613824 ...

public static string ColumnAdress(int col)
{
  if (col <= 26) { 
    return Convert.ToChar(col + 64).ToString();
  }
  int div = col / 26;
  int mod = col % 26;
  if (mod == 0) {mod = 26;div--;}
  return ColumnAdress(div) + ColumnAdress(mod);
}

public static int ColumnNumber(string colAdress)
{
  int[] digits = new int[colAdress.Length];
  for (int i = 0; i < colAdress.Length; ++i)
  {
    digits[i] = Convert.ToInt32(colAdress[i]) - 64;
  }
  int mul=1;int res=0;
  for (int pos = digits.Length - 1; pos >= 0; --pos)
  {
    res += digits[pos] * mul;
    mul *= 26;
  }
  return res;
}
Svarte 16/04/2010 kl. 10:25
kilden bruker

stemmer
13

Jeg oppdaget en feil i mitt første innlegg, så jeg bestemte meg for å sitte ned og gjøre regnestykket. Hva jeg fant er at tallsystemet brukes til å identifisere Excel kolonner er ikke en base 26 system, som en annen person postet. Vurdere følgende i basen 10. Du kan også gjøre dette med bokstavene i alfabetet.

Space: ......................... S1, S2, S3: S1, S2, S3
............ ........................ 0, 00, 000: .. A, AA, AAA
............. ....................... 1, 01, 001: .. B, AB, AAB
.............. ...................... ..., ..., ...: .. ... ... ...
............... ..................... 9, 99, 999: .. Z, ZZ, ZZZ
Total tilstander i rommet: 10, 100, 1000: 26, 676, 17 576
totalt States: ............... 1110 ................ 18 278

Excel tall kolonner i de enkelte alfabetiske mellomrom ved hjelp av foten 26. Du kan se at i alminnelighet er tilstandsrom progresjon a, a ^ 2, a ^ 3, ... annen basis en, og det totale antall av tilstander er en + a ^ 2 + a ^ 3 + ....

Tenk deg at du ønsker å finne det totale antallet tilstander A i de første N mellomrom. Formelen for å gjøre så er A = (a) (a ^ n - 1) / (a-1). Dette er viktig fordi vi trenger å finne plass N som tilsvarer indeksen vår K. Hvis jeg ønsker å finne ut hvor K ligger i det tallsystemet jeg trenger å erstatte A med K og løse for N. Løsningen er N = log { basen a} (A (a-1) / a 1). Hvis jeg bruker eksemplet med en = 10 og K = 192, jeg vet at N = 2,23804 .... Dette forteller meg at K ligger ved begynnelsen av det tredje rommet siden det er litt større enn to.

Det neste trinnet er å finne nøyaktig hvor langt i inneværende plassen vi er. For å finne denne, trekke fra K A generert ved hjelp av gulvet i N. I dette eksemplet, er gulvet av N to. Så, A = (10) (10 ^ 2 - 1) / (10-1) = 110, som er forventet når man kombinerer tilstander av de to første plasser. Dette må trekkes fra K fordi disse første 110 statene ville ha allerede tatt hensyn til i de to første plasser. Dette etterlater oss med 82 stater. Så, i dette tallsystem, representasjon av 192 i basen 10 er 082.

C # kode ved hjelp av en basisindeks på null er

    private string ExcelColumnIndexToName(int Index)
    {
        string range = string.Empty;
        if (Index < 0 ) return range;
        int a = 26;
        int x = (int)Math.Floor(Math.Log((Index) * (a - 1) / a + 1, a));
        Index -= (int)(Math.Pow(a, x) - 1) * a / (a - 1);
        for (int i = x+1; Index + i > 0; i--)
        {
            range = ((char)(65 + Index % a)).ToString() + range;
            Index /= a;
        }
        return range;
    }

// Old Post

En nullbasert løsning i C #.

    private string ExcelColumnIndexToName(int Index)
    {
        string range = "";
        if (Index < 0 ) return range;
        for(int i=1;Index + i > 0;i=0)
        {
            range = ((char)(65 + Index % 26)).ToString() + range;
            Index /= 26;
        }
        if (range.Length > 1) range = ((char)((int)range[0] - 1)).ToString() + range.Substring(1);
        return range;
    }
Svarte 09/08/2010 kl. 19:16
kilden bruker

stemmer
4

hvis du bare vil det for en celleformel uten kode, her er en formel for det:

IF(COLUMN()>=26,CHAR(ROUND(COLUMN()/26,1)+64)&CHAR(MOD(COLUMN(),26)+64),CHAR(COLUMN()+64))
Svarte 23/08/2010 kl. 15:23
kilden bruker

stemmer
-4
    public string ToBase26(int number)
    {
        if (number < 0) return String.Empty;

        int remainder = number % 26;
        int value = number / 26;

        return value == 0 ?
            String.Format("{0}", Convert.ToChar(65 + remainder)) :
            String.Format("{0}{1}", ToBase26(value - 1), Convert.ToChar(65 + remainder));
    }
Svarte 12/11/2010 kl. 01:13
kilden bruker

stemmer
6

Samme implementaion i Java

public String getExcelColumnName (int columnNumber) 
    {     
        int dividend = columnNumber;   
        int i;
        String columnName = "";     
        int modulo;     
        while (dividend > 0)     
        {        
            modulo = (dividend - 1) % 26;         
            i = 65 + modulo;
            columnName = new Character((char)i).toString() + columnName;        
            dividend = (int)((dividend - modulo) / 26);    
        }       
        return columnName; 
    }  
Svarte 10/12/2010 kl. 03:45
kilden bruker

stemmer
4

I Delphi (Pascal):

function GetExcelColumnName(columnNumber: integer): string;
var
  dividend, modulo: integer;
begin
  Result := '';
  dividend := columnNumber;
  while dividend > 0 do begin
    modulo := (dividend - 1) mod 26;
    Result := Chr(65 + modulo) + Result;
    dividend := (dividend - modulo) div 26;
  end;
end;
Svarte 24/08/2011 kl. 14:01
kilden bruker

stemmer
0

Her er hvordan jeg ville gjøre det i Python. Algoritmen er forklart nedenfor:

alph = ('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z')
def labelrec(n, res):
    if n<26:
        return alph[n]+res
    else:
        rem = n%26
        res = alph[rem]+res
        n = n/26-1
        return labelrec(n, res)

Funksjonen labelrec kan kalles med nummeret og en tom streng som:

print labelrec(16383, '')

Her er grunnen til at det fungerer: Hvis desimaltall ble skrevet på samme måte som Excel ark kolonner, ville antallet 0-9 skrives normalt, men 10 ville bli '00' og deretter 20 ville bli '10' og så videre. Kartlegging noen tall:

0-0

9-9

10-00

20-10

100-90

110-000

1110 - 0000

Så, er mønsteret klart. Starter på enhetens sted, hvis et tall er mindre enn 10, det er representasjon er samme antall som i seg selv, annet du trenger å justere de resterende nummer ved å trekke den av en og recurse. Du kan stoppe når antallet er mindre enn 10.

Den samme logikken brukes for antall basedelen 26 i ovennevnte oppløsning.

PS Hvis du vil tallene for å begynne fra en, ringe samme funksjon på inngang nummer etter mink det ved en.

Svarte 11/10/2011 kl. 13:45
kilden bruker

stemmer
5

Etter å se på alle de medfølgende versjoner her, jeg descided å gjøre en selv, ved hjelp av rekursjon.

Her er min vb.net versjon:

Function CL(ByVal x As Integer) As String
    If x >= 1 And x <= 26 Then
        CL = Chr(x + 64)
    Else
        CL = CL((x - x Mod 26) / 26) & Chr((x Mod 26) + 1 + 64)
    End If
End Function
Svarte 13/10/2011 kl. 06:09
kilden bruker

stemmer
5

Litt sent til spillet, men her er koden jeg bruker (i C #):

private static readonly string _Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static int ColumnNameParse(string value)
{
    // assumes value.Length is [1,3]
    // assumes value is uppercase
    var digits = value.PadLeft(3).Select(x => _Alphabet.IndexOf(x));
    return digits.Aggregate(0, (current, index) => (current * 26) + (index + 1));
}
Svarte 05/01/2012 kl. 04:38
kilden bruker

stemmer
1

Jeg prøver å gjøre det samme i Java ... Jeg har skrevet følgende kode:

private String getExcelColumnName(int columnNumber) {

    int dividend = columnNumber;
    String columnName = "";
    int modulo;

    while (dividend > 0)
    {
        modulo = (dividend - 1) % 26;

        char val = Character.valueOf((char)(65 + modulo));

        columnName += val;

        dividend = (int)((dividend - modulo) / 26);
    } 

    return columnName;
}

Nå når jeg kjørte den med columnNumber = 29, det gir meg et resultat = "Oslo" (i stedet for "AC") noen kommentarer hva jeg mangler? Jeg vet jeg kan reversere den ved Stringbuilder .... Men se på Graham svar, jeg er litt forvirret ....

Svarte 24/02/2012 kl. 11:45
kilden bruker

stemmer
2

I perl, til en inngang av en (A), 27 (AA), etc.

sub excel_colname {
  my ($idx) = @_;       # one-based column number
  --$idx;               # zero-based column index
  my $name = "";
  while ($idx >= 0) {
    $name .= chr(ord("A") + ($idx % 26));
    $idx   = int($idx / 26) - 1;
  }
  return scalar reverse $name;
}
Svarte 17/04/2012 kl. 23:42
kilden bruker

stemmer
7

Jeg er overrasket over alle løsningene så langt inneholder enten gjentakelse eller rekursjon.

Her er min løsning som kjører i konstant tid (ingen løkker). Denne løsningen fungerer for alle mulige Excel kolonner og kontroller at inngangen kan gjøres om til en Excel-kolonne. Mulige kolonner er i området [A, XFD] eller [1, 16384]. (Dette er avhengig av din versjon av Excel)

private static string Turn(uint col)
{
    if (col < 1 || col > 16384) //Excel columns are one-based (one = 'A')
        throw new ArgumentException("col must be >= 1 and <= 16384");

    if (col <= 26) //one character
        return ((char)(col + 'A' - 1)).ToString();

    else if (col <= 702) //two characters
    {
        char firstChar = (char)((int)((col - 1) / 26) + 'A' - 1);
        char secondChar = (char)(col % 26 + 'A' - 1);

        if (secondChar == '@') //Excel is one-based, but modulo operations are zero-based
            secondChar = 'Z'; //convert one-based to zero-based

        return string.Format("{0}{1}", firstChar, secondChar);
    }

    else //three characters
    {
        char firstChar = (char)((int)((col - 1) / 702) + 'A' - 1);
        char secondChar = (char)((col - 1) / 26 % 26 + 'A' - 1);
        char thirdChar = (char)(col % 26 + 'A' - 1);

        if (thirdChar == '@') //Excel is one-based, but modulo operations are zero-based
            thirdChar = 'Z'; //convert one-based to zero-based

        return string.Format("{0}{1}{2}", firstChar, secondChar, thirdChar);
    }
}
Svarte 08/02/2013 kl. 16:36
kilden bruker

stemmer
8

Dette svaret er i Javascript:

function getCharFromNumber(columnNumber){
    var dividend = columnNumber;
    var columnName = "";
    var modulo;

    while (dividend > 0)
    {
        modulo = (dividend - 1) % 26;
        columnName = String.fromCharCode(65 + modulo).toString() + columnName;
        dividend = parseInt((dividend - modulo) / 26);
    } 
    return  columnName;
}
Svarte 28/03/2013 kl. 07:06
kilden bruker

stemmer
1

Her er min super sent implementering i PHP. Denne er rekursiv. Jeg skrev det like før jeg fant dette innlegget. Jeg ønsket å se om andre hadde løst dette problemet allerede ...

public function GetColumn($intNumber, $strCol = null) {

    if ($intNumber > 0) {
        $intRem = ($intNumber - 1) % 26;
        $strCol = $this->GetColumn(intval(($intNumber - $intRem) / 26), sprintf('%s%s', chr(65 + $intRem), $strCol));
    }

    return $strCol;
}
Svarte 01/05/2013 kl. 20:44
kilden bruker

stemmer
2

Javascript Solution

/**
 * Calculate the column letter abbreviation from a 1 based index
 * @param {Number} value
 * @returns {string}
 */
getColumnFromIndex = function (value) {
    var base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
    var remainder, result = "";
    do {
        remainder = value % 26;
        result = base[(remainder || 26) - 1] + result;
        value = Math.floor(value / 26);
    } while (value > 0);
    return result;
};
Svarte 03/10/2013 kl. 07:43
kilden bruker

stemmer
0

(Jeg innser at spørsmålet gjelder C #, men hvis noen leser behov for å gjøre det samme med Java deretter følgende kan være nyttig)

Det viser seg at dette kan enkelt gjøres ved hjelp av den "CellReference" klasse i Jakarta POI . Dessuten kan konverteringen gjøres begge veier.

// Convert row and column numbers (0-based) to an Excel cell reference
CellReference numbers = new CellReference(3, 28);
System.out.println(numbers.formatAsString());

// Convert an Excel cell reference back into digits
CellReference reference = new CellReference("AC4");
System.out.println(reference.getRow() + ", " + reference.getCol());
Svarte 24/01/2014 kl. 07:21
kilden bruker

stemmer
1

En annen VBA måte

Public Function GetColumnName(TargetCell As Range) As String
    GetColumnName = Split(CStr(TargetCell.Address), "$")(1)
End Function
Svarte 20/02/2014 kl. 23:29
kilden bruker

stemmer
4

Jeg ønsket å kaste i min statisk klasse jeg bruker, for interoping mellom col indeksen og col etikett. Jeg bruker en modifisert akseptert svar for min ColumnLabel Method

public static class Extensions
{
    public static string ColumnLabel(this int col)
    {
        var dividend = col;
        var columnLabel = string.Empty;
        int modulo;

        while (dividend > 0)
        {
            modulo = (dividend - 1) % 26;
            columnLabel = Convert.ToChar(65 + modulo).ToString() + columnLabel;
            dividend = (int)((dividend - modulo) / 26);
        } 

        return columnLabel;
    }
    public static int ColumnIndex(this string colLabel)
    {
        // "AD" (1 * 26^1) + (4 * 26^0) ...
        var colIndex = 0;
        for(int ind = 0, pow = colLabel.Count()-1; ind < colLabel.Count(); ++ind, --pow)
        {
            var cVal = Convert.ToInt32(colLabel[ind]) - 64; //col A is index 1
            colIndex += cVal * ((int)Math.Pow(26, pow));
        }
        return colIndex;
    }
}

Bruk dette som ...

30.ColumnLabel(); // "AD"
"AD".ColumnIndex(); // 30
Svarte 26/09/2014 kl. 13:33
kilden bruker

stemmer
1

Disse mine koder for å konvertere bestemt antall (indeks start fra 1) til Excel Column.

    public static string NumberToExcelColumn(uint number)
    {
        uint originalNumber = number;

        uint numChars = 1;
        while (Math.Pow(26, numChars) < number)
        {
            numChars++;

            if (Math.Pow(26, numChars) + 26 >= number)
            {
                break;
            }               
        }

        string toRet = "";
        uint lastValue = 0;

        do
        {
            number -= lastValue;

            double powerVal = Math.Pow(26, numChars - 1);
            byte thisCharIdx = (byte)Math.Truncate((columnNumber - 1) / powerVal);
            lastValue = (int)powerVal * thisCharIdx;

            if (numChars - 2 >= 0)
            {
                double powerVal_next = Math.Pow(26, numChars - 2);
                byte thisCharIdx_next = (byte)Math.Truncate((columnNumber - lastValue - 1) / powerVal_next);
                int lastValue_next = (int)Math.Pow(26, numChars - 2) * thisCharIdx_next;

                if (thisCharIdx_next == 0 && lastValue_next == 0 && powerVal_next == 26)
                {
                    thisCharIdx--;
                    lastValue = (int)powerVal * thisCharIdx;
                }
            }

            toRet += (char)((byte)'A' + thisCharIdx + ((numChars > 1) ? -1 : 0));

            numChars--;
        } while (numChars > 0);

        return toRet;
    }

Min Unit Test:

    [TestMethod]
    public void Test()
    {
        Assert.AreEqual("A", NumberToExcelColumn(1));
        Assert.AreEqual("Z", NumberToExcelColumn(26));
        Assert.AreEqual("AA", NumberToExcelColumn(27));
        Assert.AreEqual("AO", NumberToExcelColumn(41));
        Assert.AreEqual("AZ", NumberToExcelColumn(52));
        Assert.AreEqual("BA", NumberToExcelColumn(53));
        Assert.AreEqual("ZZ", NumberToExcelColumn(702));
        Assert.AreEqual("AAA", NumberToExcelColumn(703));
        Assert.AreEqual("ABC", NumberToExcelColumn(731));
        Assert.AreEqual("ACQ", NumberToExcelColumn(771));
        Assert.AreEqual("AYZ", NumberToExcelColumn(1352));
        Assert.AreEqual("AZA", NumberToExcelColumn(1353));
        Assert.AreEqual("AZB", NumberToExcelColumn(1354));
        Assert.AreEqual("BAA", NumberToExcelColumn(1379));
        Assert.AreEqual("CNU", NumberToExcelColumn(2413));
        Assert.AreEqual("GCM", NumberToExcelColumn(4823));
        Assert.AreEqual("MSR", NumberToExcelColumn(9300));
        Assert.AreEqual("OMB", NumberToExcelColumn(10480));
        Assert.AreEqual("ULV", NumberToExcelColumn(14530));
        Assert.AreEqual("XFD", NumberToExcelColumn(16384));
    }
Svarte 09/04/2015 kl. 21:35
kilden bruker

stemmer
0

Coincise og elegant Ruby versjon:

def col_name(col_idx)
    name = ""
    while col_idx>0
        mod     = (col_idx-1)%26
        name    = (65+mod).chr + name
        col_idx = ((col_idx-mod)/26).to_i
    end
    name
end
Svarte 24/04/2015 kl. 10:38
kilden bruker

stemmer
0

Jeg bare måtte gjøre dette arbeidet i dag, bruker gjennomføringen min rekursjon:

private static string GetColumnLetter(string colNumber)
{
    if (string.IsNullOrEmpty(colNumber))
    {
        throw new ArgumentNullException(colNumber);
    }

    string colName = String.Empty;

    try
    {
        var colNum = Convert.ToInt32(colNumber);
        var mod = colNum % 26;
        var div = Math.Floor((double)(colNum)/26);
        colName = ((div > 0) ? GetColumnLetter((div - 1).ToString()) : String.Empty) + Convert.ToChar(mod + 65);
    }
    finally
    {
        colName = colName == String.Empty ? "A" : colName;
    }

    return colName;
}

Dette tar hensyn til tall som kommer som en streng på den samme måte og med tallene starte i "0" (A = 0)

Svarte 18/06/2015 kl. 09:51
kilden bruker

stemmer
0

Objective-C Gjennomføring:

-(NSString*)getColumnName:(int)n {
     NSString *name = @"";
     while (n>0) {
     n--;
     char c = (char)('A' + n%26);
     name = [NSString stringWithFormat:@"%c%@",c,name];
     n = n/26;
  }    
     return name;

}

SWIFT Gjennomføring:

func getColumnName(n:Int)->String{
 var columnName = ""
 var index = n
 while index>0 {
     index--
     let char = Character(UnicodeScalar(65 + index%26))
     columnName = "\(char)\(columnName)"
     index = index / 26
 }
 return columnName

}

Svaret er basert på: https://stackoverflow.com/a/4532562/2231118

Svarte 31/07/2015 kl. 23:33
kilden bruker

stemmer
0

NodeJS implementering:

/**
* getColumnFromIndex
* Helper that returns a column value (A-XFD) for an index value (integer).
* The column follows the Common Spreadsheet Format e.g., A, AA, AAA.
* See https://stackoverflow.com/questions/181596/how-to-convert-a-column-number-eg-127-into-an-excel-column-eg-aa/3444285#3444285
* @param numVal: Integer
* @return String
*/
getColumnFromIndex: function(numVal){
   var dividend = parseInt(numVal);
   var columnName = '';
   var modulo;
   while (dividend > 0) {
      modulo = (dividend - 1) % 26;
      columnName = String.fromCharCode(65 + modulo) + columnName;
      dividend = parseInt((dividend - modulo) / 26);
   }
   return columnName;
},

Takket være konvertere Excel kolonne alfabetet (f.eks AA) til nummer (for eksempel 25) . Og omvendt:

/**
* getIndexFromColumn
* Helper that returns an index value (integer) for a column value (A-XFD).
* The column follows the Common Spreadsheet Format e.g., A, AA, AAA.
* See https://stackoverflow.com/questions/9905533/convert-excel-column-alphabet-e-g-aa-to-number-e-g-25
* @param strVal: String
* @return Integer
*/
getIndexFromColumn: function(val){
   var base = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', i, j, result = 0;
   for (i = 0, j = val.length - 1; i < val.length; i += 1, j -= 1) {
      result += Math.pow(base.length, j) * (base.indexOf(val[i]) + 1);
   }
   return result;
}
Svarte 09/08/2015 kl. 00:44
kilden bruker

stemmer
0

Så en annen VBA svaret - dette kan gjøres i med en 1 linje UDF:

Function GetColLetter(ByVal colID As Integer) As String
    GetColLetter = Split(Cells(1, colID).Address, "$")(1)
End Function
Svarte 13/11/2015 kl. 20:45
kilden bruker

stemmer
0

Selv om jeg er sent til spillet, Graham svar er langt fra optimal. Spesielt, trenger du ikke å bruke den modulo, kan du ringe ToString()og bruke (int)cast. Tatt i betraktning at i de fleste tilfeller i C # verden ville du starte nummereringen fra 0, her er min versjon:

public static string GetColumnName(int index) // zero-based
{
    const byte BASE = 'Z' - 'A' + 1;
    string name = String.Empty;

    do
    {
        name = Convert.ToChar('A' + index % BASE) + name;
        index = index / BASE - 1;
    }
    while (index >= 0);

    return name;
}
Svarte 18/08/2016 kl. 11:34
kilden bruker

stemmer
-1

Microsoft Excel Miniature, Quick-and-Dirty formel.

Hei,

Her er én måte å få Excel karakter-kolonne-heading fra en rekke ....

I laget en formel for en Excel-celle.

(Dvs. jeg tok tilnærming av å ikke bruke VBA programmering.)

Formelen ser på en celle som har et nummer i det og forteller deg hva kolonnen er - i bokstaver.

I det vedlagte bildet:

  • Jeg satte 1,2,3 osv i den øverste raden helt ut til kolonne ABS.
  • Jeg limte min formel i den andre raden helt ut til ABS.
  • Min formel ser på rad 1 og konverterer nummeret til Excel kolonneoverskrift id.
  • Min formelen fungerer for alle tall ut til 702 (zz).
  • Jeg gjorde det på denne måten for å bevise at formelen fungerer slik at du kan se på resultatet fra formelen og se på kolonneoverskriften over og enkelt visuelt kontrollere at formelen fungerer. :-)

    = CONCATENATE (MID ( "_ abcdefghijklmnopqrstuvwxyz", (IF (MOD (K1,26)> 0, INT (K1 / 26) 1, (INT (K1 / 26)))), 1), MID ( "abcdefghijklmnopqrstuvwxyz", IF (MOD (K1,26) = 0,26, MOD (K1,26)), 1))

Understrek var der for debugging formål - å fortelle deg det var en faktisk plass og at det var fungerer riktig.

Med denne formelen ovenfor - uansett hva du putter i K1 - formelen vil fortelle deg hva kolonneoverskriften vil bli.

Formelen i sin nåværende form, bare går ut til 2 sifre (ZZ), men kan bli endret for å legge den tredje bokstaven (ZZZ).

skriv bildebeskrivelse her

Svarte 26/08/2016 kl. 14:54
kilden bruker

stemmer
0

F # versjon av hver vei

let rec getExcelColumnName x  = if x<26 then int 'A'+x|>char|>string else (x/26-1|>c)+ c(x%26)

tilgi minimering, jobbet på en bedre versjon av https://stackoverflow.com/a/4500043/57883


og i motsatt retning:

// return values start at 0
let getIndexFromExcelColumnName (x:string) =
    let a = int 'A'
    let fPow len i =
        Math.Pow(26., len - 1 - i |> float)
        |> int

    let getValue len i c = 
        int c - a + 1 * fPow len i
    let f i = getValue x.Length i x.[i]
    [0 .. x.Length - 1]
    |> Seq.map f
    |> Seq.sum
    |> fun x -> x - 1
Svarte 14/12/2016 kl. 15:42
kilden bruker

stemmer
4

Bare å kaste i en enkel to-linje C # implementering ved hjelp av rekursjon, fordi alle svarene her synes langt mer komplisert enn nødvendig.

/// <summary>
/// Gets the column letter(s) corresponding to the given column number.
/// </summary>
/// <param name="column">The one-based column index. Must be greater than zero.</param>
/// <returns>The desired column letter, or an empty string if the column number was invalid.</returns>
public static string GetColumnLetter(int column) {
    if (column < 1) return String.Empty;
    return GetColumnLetter((column - 1) / 26) + (char)('A' + (column - 1) % 26);
}
Svarte 23/01/2017 kl. 22:01
kilden bruker

stemmer
0

Dette er spørsmålet alle andre så vel som Google omdirigere til så jeg legger denne her.

Mange av disse svarene er korrekte, men for tungvint for enkle situasjoner som for eksempel når du ikke har over 26 kolonner. Hvis du er i tvil om du kan gå inn doble karakter kolonner deretter ignorere dette svaret, men hvis du er sikker på at du ikke vil, så du kan gjøre det så enkelt som dette i C #:

public static char ColIndexToLetter(short index)
{
    if (index < 0 || index > 25) throw new ArgumentException("Index must be between 0 and 25.");
    return (char)('A' + index);
}

Pokker, hvis du er trygg på hva du sender inn kan du selv fjerne validering og bruke denne inline:

(char)('A' + index)

Dette vil være svært like på mange språk, slik at du kan tilpasse den etter behov.

Igjen, bare bruke dette hvis du er 100% sikker på at du vil ikke ha mer enn 26 kolonner .

Svarte 22/03/2017 kl. 09:01
kilden bruker

stemmer
0

Takk for svarene her !! hjalp meg å komme opp med disse hjelpefunksjoner for noen interaksjon med Google Sheets API som jeg jobber med i Elixir / Phoenix

her er hva jeg kom opp med (sannsynligvis kunne bruke litt ekstra validering og feilhåndtering)

I Elixir:

def number_to_column(number) do
  cond do
    (number > 0 && number <= 26) ->
      to_string([(number + 64)])
    (number > 26) ->
      div_col = number_to_column(div(number - 1, 26))
      remainder = rem(number, 26)
      rem_col = cond do
        (remainder == 0) ->
          number_to_column(26)
        true ->
          number_to_column(remainder)
      end
      div_col <> rem_col
    true ->
      ""
  end
end

Og den inverse funksjon:

def column_to_number(column) do
  column
    |> to_charlist
    |> Enum.reverse
    |> Enum.with_index
    |> Enum.reduce(0, fn({char, idx}, acc) ->
      ((char - 64) * :math.pow(26,idx)) + acc
    end)
    |> round
end

Og noen tester:

describe "test excel functions" do
  @excelTestData [{"A", 1}, {"Z",26}, {"AA", 27}, {"AB", 28}, {"AZ", 52},{"BA", 53}, {"AAA", 703}]

  test "column to number" do
    Enum.each(@excelTestData, fn({input, expected_result}) ->
      actual_result = BulkOnboardingController.column_to_number(input)
      assert actual_result == expected_result
    end)
  end

  test "number to column" do
    Enum.each(@excelTestData, fn({expected_result, input}) ->
      actual_result = BulkOnboardingController.number_to_column(input)
      assert actual_result == expected_result
    end)
  end
end
Svarte 11/09/2017 kl. 21:52
kilden bruker

stemmer
1

Beklager, dette er Python i stedet for C #, men minst resultatene er riktige:

def excel_column_number_to_name(column_number):
    output = ""
    index = column_number-1
    while index >= 0:
        character = chr((index%26)+ord('A'))
        output = output + character
        index = index/26 - 1

    return output[::-1]


for i in xrange(1, 1024):
    print "%4d : %s" % (i, excel_column_number_to_name(i))

Bestått disse testtilfeller:

  • Kolonne Nummer: 494286 => ABCDZ
  • Kolonne nummer: 27 => AA
  • Kolonne nummer: 52 => AZ
Svarte 05/11/2017 kl. 16:04
kilden bruker

stemmer
0

Dette er en javascript versjon ifølge Graham kode

function (columnNumber) {
    var dividend = columnNumber;
    var columnName = "";
    var modulo;

    while (dividend > 0) {
        modulo = (dividend - 1) % 26;
        columnName = String.fromCharCode(65 + modulo) + columnName;
        dividend = parseInt((dividend - modulo) / 26);
    }

    return columnName;
};
Svarte 12/08/2018 kl. 02:30
kilden bruker

stemmer
0

For hva det er verdt, her er Graham kode i Powershell:

function ConvertTo-ExcelColumnID {
param (
    [parameter(Position = 0,
        HelpMessage = "A 1-based index to convert to an excel column ID. e.g. 2 => 'B', 29 => 'AC'",
        Mandatory = $true)]
    [int]$index
);

[string]$result = '';
if ($index -le 0 ) {
    return $result;
}

while ($index -gt 0) {
    [int]$modulo = ($index - 1) % 26;
    $character = [char]($modulo + [int][char]'A');
    $result = $character + $result;
    [int]$index = ($index - $modulo) / 26;
}

return $result;

}

Svarte 13/10/2018 kl. 05:14
kilden bruker

stemmer
0

De fleste av tidligere svarene er riktige. Her er enda en måte å konvertere kolonnenummer til å utmerke kolonner. Løsningen er ganske enkelt hvis vi tenker på dette som en base konvertering. Enkelt konvertere kolonnenummeret å basere 26 siden det er 26 bokstaver bare. Her er hvordan du kan gjøre dette:

trinn:

  • satt på kolonnen som en kvotient

  • trekke en fra kvotienten variabel (fra foregående trinn) fordi vi trenger å ende opp på ascii-bord med 97 å være en.

  • dividere med 26 og får det resterende.

  • legge 97 til resten og konvertere til forkulle (siden 97 er "en" i ASCII tabell)
  • kvotienten blir ny kvotient / 26 (siden vi kan gå over 26 kolonne)
  • fortsette å gjøre dette til kvotienten er større enn 0 og deretter returnere resultatet

her er koden som gjør dette :)

def convert_num_to_column(column_num):
    result = ""
    quotient = column_num
    remainder = 0
    while (quotient >0):
        quotient = quotient -1
        remainder = quotient%26
        result = chr(int(remainder)+97)+result
        quotient = int(quotient/26)
    return result

print("--",convert_num_to_column(1).upper())
Svarte 29/10/2018 kl. 03:26
kilden bruker

stemmer
0

Mer enn 30 løsninger allerede, men her er min én linje C # løsning ...

public string IntToExcelColumn(int i)
{
    return ((i<16926? "" : ((char)((((i/26)-1)%26)+65)).ToString()) + (i<2730? "" : ((char)((((i/26)-1)%26)+65)).ToString()) + (i<26? "" : ((char)((((i/26)-1)%26)+65)).ToString()) + ((char)((i%26)+65)));
}
Svarte 09/07/2019 kl. 21:08
kilden bruker

stemmer
0

Her er min løsning i python

import math

num = 3500
row_number = str(math.ceil(num / 702))
letters = ''
num = num - 702 * math.floor(num / 702)
while num:
    mod = (num - 1) % 26
    letters += chr(mod + 65)
    num = (num - 1) // 26
result = row_number + ("".join(reversed(letters)))
print(result)

Svarte 15/10/2019 kl. 05:02
kilden bruker

stemmer
0

Her er en Loggfila løsning:

function lengthToExcelColumn(len: number): string {

    let dividend: number = len;
    let columnName: string = '';
    let modulo: number = 0;

    while (dividend > 0) {
        modulo = (dividend - 1) % 26;
        columnName = String.fromCharCode(65 + modulo).toString() + columnName;
        dividend = Math.floor((dividend - modulo) / 26);
    }
    return columnName;
}
Svarte 15/01/2020 kl. 17:11
kilden bruker

stemmer
0

Virker som så mange svar er mye mer komplisert enn nødvendig. Her er en generisk Ruby svar basert på rekursjon beskrevet ovenfor:

En fin ting om dette svaret er at det ikke er begrenset til 26 tegn i engelsk alfabetet. Du kan definere perioden du vil ha i COLUMNSkonstant og det vil gjøre det rette.

  # vim: ft=ruby
  class Numeric
    COLUMNS = ('A'..'Z').to_a

    def to_excel_column(n = self)
      n < 1 ?  '' : begin
        base = COLUMNS.size
        to_excel_column((n - 1) / base) + COLUMNS[(n - 1) % base]
      end
    end
  end

  # verify:
  (1..52).each { |i| printf "%4d => %4s\n", i, i.to_excel_column }

Dette skriver følgende, f.eks:

   1 =>    A
   2 =>    B
   3 =>    C
  ....
  33 =>   AG
  34 =>   AH
  35 =>   AI
  36 =>   AJ
  37 =>   AK
  38 =>   AL
  39 =>   AM
  40 =>   AN
  41 =>   AO
  42 =>   AP
  43 =>   AQ
  44 =>   AR
  45 =>   AS
  46 =>   AT
  47 =>   AU
  48 =>   AV
  49 =>   AW
  50 =>   AX
  51 =>   AY
  52 =>   AZ
Svarte 15/02/2020 kl. 00:07
kilden bruker

stemmer
0

Dette er et vanlig spørsmål stilt i koding test. den har noen begrensninger: maks kolonner per rad = 702 utgang bør ha radnummer + kolonnenavnet, for eksempel for 703 Svaret er 2A. (Merk: Jeg har nettopp endret eksisterende kode fra et annet svar) her er koden for det samme:

    static string GetExcelColumnName(long columnNumber)
    {
        //max number of column per row
        const long maxColPerRow = 702;
        //find row number
        long rowNum = (columnNumber / maxColPerRow);
        //find tierable columns in the row.
        long dividend = columnNumber - (maxColPerRow * rowNum);

        string columnName = String.Empty;

        long modulo;

        while (dividend > 0)
        {
            modulo = (dividend - 1) % 26;
            columnName = Convert.ToChar(65 + modulo).ToString() + columnName;
            dividend = (int)((dividend - modulo) / 26);
        }

        return rowNum+1+ columnName;
    }
}
Svarte 20/02/2020 kl. 16:55
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more