2009-05-11 10 views

Respuesta

50

Esta función debería funcionar para un nombre de columna de longitud arbitraria.

public static int GetColumnNumber(string name) 
{ 
    int number = 0; 
    int pow = 1; 
    for (int i = name.Length - 1; i >= 0; i--) 
    { 
     number += (name[i] - 'A' + 1) * pow; 
     pow *= 26; 
    } 

    return number; 
} 
+1

nice! ! –

+0

realmente bueno, hombre. Lo estaba haciendo, pero el método era mucho más grande que esta simple solución. –

+0

Gracias. Y sí, creo que esto parece bastante simple, aunque no dude en sugerir cualquier optimización ... – Noldorin

14

Tuve que lidiar con esto hace unos meses. El índice de columna inversa al nombre de la columna también es divertido y se vuelve realmente desordenado si intentas resolverlo con un índice basado en cero sin reconocer que esto complica las cosas. Podría ser tan simple si fuera un sistema normal de numeración polídica ...

Aquí hay una versión simplificada de mi solución como método de extensión sin manejo de errores y todo eso.

public static Int32 ToOneBasedIndex(this String name) 
{ 
    return name.ToUpper(). 
     Aggregate(0, (column, letter) => 26 * column + letter - 'A' + 1); 
} 
+2

Hombre, eso es ajustado. +1 – wcm

+0

Esto es puro arte :) +1 –

+0

Excelente solución .... –

2

He estado trabajando con esto durante un tiempo, y encontré que esto funcione realmente bueno para las columnas que van más allá de AZ, o incluso más allá de AA-ZZ ... Se logra romperse cada carácter de la cadena y recursivamente llamando a derivar el valor DEC del carácter ASCII (menos 64), luego multiplicándolo por 26^n. Se utilizó un valor de retorno de largo para superar una limitación potencial cuando n> 4.

public long columnNumber(String columnName) 
    { 
     char[] chars = columnName.ToUpper().ToCharArray(); 

     return (long)(Math.Pow(26, chars.Count() - 1)) * 
      (System.Convert.ToInt32(chars[0]) - 64) + 
      ((chars.Count() > 2) ? columnNumber(columnName.Substring(1, columnName.Length - 1)) : 
      ((chars.Count() == 2) ? (System.Convert.ToInt32(chars[chars.Count() - 1]) - 64) : 0)); 
    } 

Además, si desea obtener la inversa (es decir pase en el ColumnNumber y obtener el columnName, aquí hay un código que trabaja para eso.

public String columnName(long columnNumber) 
    { 
     StringBuilder retVal = new StringBuilder(); 
     int x = 0; 

     for (int n = (int)(Math.Log(25*(columnNumber + 1))/Math.Log(26)) - 1; n >= 0; n--) 
     { 
      x = (int)((Math.Pow(26,(n + 1)) - 1)/25 - 1); 
      if (columnNumber > x) 
       retVal.Append(System.Convert.ToChar((int)(((columnNumber - x - 1)/Math.Pow(26, n)) % 26 + 65))); 
     } 

     return retVal.ToString(); 
    } 
0

tratar mi código

espacio de nombres XLS {

/// <summary> 
/// Represents a single cell in a excell sheet 
/// </summary> 
public struct Cell 
{ 
    private long row; 
    private long column; 
    private string columnAddress; 
    private string address; 
    private bool dataChange; 

    /// <summary> 
    /// Initializes a new instance of the XLS.Cell 
    /// class with the specified row and column of excel worksheet 
    /// </summary> 
    /// <param name="row">The row index of a cell</param> 
    /// <param name="column">The column index of a cell</param> 
    public Cell(long row, long column) 
    { 
     this.row = row; 
     this.column = column; 
     dataChange = true; 
     address = string.Empty; 
     columnAddress = string.Empty; 
    } 

    /// <summary> 
    /// Initializes a new instance of the XLS.Cell 
    /// class with the specified address of excel worksheet 
    /// </summary> 
    /// <param name="address">The adress of a cell</param> 
    public Cell(string address) 
    { 
     this.address = address; 
     dataChange = false; 
     row = GetRow(address); 
     columnAddress = GetColumnAddress(address); 
     column = GetColumn(columnAddress); 
    } 

    /// <summary> 
    /// Gets or sets the row of this XLS.Cell 
    /// </summary> 
    public long Row 
    { 
     get { return row <= 0 ? 1 : row; } 
     set { row = value; dataChange = true; } 
    } 

    /// <summary> 
    /// Gets or sets the column of this XLS.Cell 
    /// </summary> 
    public long Column 
    { 
     get { return column <= 0 ? 1 : column; } 
     set { column = value; dataChange = true; } 
    } 

    /// <summary> 
    /// Gets or sets the address of this XLS.Cell 
    /// </summary> 
    public string Address 
    { 
     get { return dataChange ? ToAddress() : address; } 
     set 
     { 
      address = value; 
      row = GetRow(address); 
      column = GetColumn(address); 
     } 
    } 

    /// <summary> 
    /// Gets the column address of this XLS.Cell 
    /// </summary> 
    public string ColumnAddress 
    { 
     get { return GetColumnAddress(Address); } 
     private set { columnAddress = value; } 
    } 

    #region Private Methods 

    private static long GetRow(string address) 
    { 
     return long.Parse(address.Substring(GetStartIndex(address))); 
    } 

    private static string GetColumnAddress(string address) 
    { 
     return address.Substring(0, GetStartIndex(address)).ToUpperInvariant(); 
    } 

    private static long GetColumn(string columnAddress) 
    { 
     char[] characters = columnAddress.ToCharArray(); 
     int sum = 0; 
     for (int i = 0; i < characters.Length; i++) 
     { 
      sum *= 26; 
      sum += (characters[i] - 'A' + 1); 
     } 

     return (long)sum; 
    } 

    private static int GetStartIndex(string address) 
    { 
     return address.IndexOfAny("123456789".ToCharArray()); 
    } 

    private string ToAddress() 
    { 
     string indexToString = string.Empty; 

     if (Column > 26) 
     { 
      indexToString = ((char)(65 + (int)((Column - 1)/26) - 1)).ToString(); 
     } 

     indexToString += (char)(65 + ((Column - 1) % 26)); 

     dataChange = false; 
     return indexToString + Row; 
    } 

    #endregion 
} 

}

0

O24 tiene un número de columna y desea un nombre:

= LEFT (DERECHA (DIRECCIÓN (1, O24), LEN (DIRECCIÓN (1, O24)) - 1), FIND (" $", DERECHA ((DIRECCIÓN (1, O24)), LEN (DIRECCIÓN (1, O24)) - 1)) - 1)

O37 tiene un nombre de columna y se desea un número:

= COLUMNA (INDIRECTA (O37 & 1))

0
public static string GetColumnName(int index) 
{ 
    const string letters = "ZABCDEFGHIJKLMNOPQRSTUVWXY"; 

    int NextPos = (index/26); 
    int LastPos = (index % 26); 
    if (LastPos == 0) NextPos--; 

    if (index > 26) 
     return GetColumnName(NextPos) + letters[LastPos]; 
    else 
     return letters[LastPos] + ""; 
} 
Cuestiones relacionadas