Как преобразовать номер столбца (например, 127) в столбец Excel (например, AA) - PullRequest
429 голосов
/ 08 октября 2008

Как преобразовать числовое число в имя столбца Excel в C # без автоматизации, получая значение непосредственно из Excel.

В Excel 2007 возможный диапазон от 1 до 16384, то есть число поддерживаемых столбцов. Результирующие значения должны быть в форме имен столбцов Excel, например, A, AA, AAA и т. Д.

Ответы [ 48 ]

836 голосов
/ 08 октября 2008

Вот как я это делаю:

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;
}
56 голосов
/ 30 января 2009

Если кому-то нужно сделать это в Excel без VBA, вот способ:

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

где colNum - номер столбца

А в 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
19 голосов
/ 08 октября 2008

Извините, это Python вместо C #, но по крайней мере результаты верны:

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))
17 голосов
/ 16 апреля 2010

Может потребоваться преобразование в обоих направлениях, например, из столбца Excel, например AAZ, в целое число и из любого целого числа в Excel. Два метода ниже сделают именно это. При условии индексации на основе 1, первым элементом в ваших «массивах» является элемент номер 1. Здесь нет ограничений по размеру, поэтому вы можете использовать адреса, такие как ОШИБКА, и это будет номер столбца 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;
}
13 голосов
/ 10 августа 2010

Я обнаружил ошибку в своем первом посте, поэтому я решил сесть и посчитать. Я обнаружил, что система счисления, используемая для идентификации столбцов Excel, не является системой 26, как написал другой человек. Рассмотрите следующее в базе 10. Вы также можете сделать это с буквами алфавита.

Пробел: ......................... S1, S2, S3: S1, S2, S3
.................................... 0, 00, 000: .. A, AA, AAA
.................................... 1, 01, 001: .. B, AB, AAB
....................................…,…,…: ..…,…,…
.................................... 9, 99, 999: .. Z, ZZ, ZZZ
Всего состояний в космосе: 10, 100, 1000: 26, 676, 17576
Всего штатов: ............... 1110 ................ 18278

Столбцы чисел Excel в отдельных алфавитных пространствах с использованием базы 26. Как вы можете видеть, в общем случае прогрессия пространства состояний представляет собой a, a ^ 2, a ^ 3,… для некоторой базы a, а общее число состояний равно а + а ^ 2 + а ^ 3 +….

Предположим, вы хотите найти общее количество состояний A в первых N пробелах. Формула для этого есть A = (a) (a ^ N - 1) / (a-1). Это важно, потому что нам нужно найти пространство N, которое соответствует нашему индексу K. Если я хочу выяснить, где K лежит в системе счисления, мне нужно заменить A на K и решить для N. Решение N = log { основание a} (A (a-1) / a +1). Если я использую пример a = 10 и K = 192, я знаю, что N = 2.23804…. Это говорит мне о том, что K лежит в начале третьего пространства, так как оно немного больше двух.

Следующий шаг - точно определить, как далеко мы находимся в текущем пространстве. Чтобы найти это, вычтите из K A, сгенерированное с использованием пола N. В этом примере, пол N равен двум. Итак, A = (10) (10 ^ 2 - 1) / (10-1) = 110, как ожидается, когда вы объединяете состояния первых двух пространств. Это нужно вычесть из K, потому что эти первые 110 состояний уже были бы учтены в первых двух пространствах. Это оставляет нас с 82 государствами. Итак, в этой системе счисления представление 192 в базе 10 равно 082.

Код C #, использующий нулевой индекс базы, равен

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

// Старый пост

Решение на основе нуля в 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;
    }
10 голосов
/ 08 октября 2008

Легко с рекурсией.

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) );
}
10 голосов
/ 08 октября 2008
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;

Обновление : Peter Комментарий правильный. Вот что я получаю за написание кода в браузере. :-) Мое решение не компилировалось, оно пропускало крайнюю левую букву и строило строку в обратном порядке - все теперь исправлено.

Помимо ошибок, алгоритм в основном конвертирует число из базы 10 в базу 26.

Обновление 2 : Джоэл Кехорн прав: приведенный выше код вернет AB для 27. Если бы это было действительное число с основанием 26, AA было бы равно A и следующему после Z будет 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;
8 голосов
/ 28 марта 2013

Этот ответ в 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;
}
8 голосов
/ 08 февраля 2013

Я удивлен, что все решения до сих пор содержат итерацию или рекурсию.

Вот мое решение, которое работает в постоянное время (без циклов). Это решение работает для всех возможных столбцов Excel и проверяет возможность преобразования входных данных в столбец Excel. Возможные столбцы находятся в диапазоне [A, XFD] или [1, 16384]. (Это зависит от вашей версии 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);
    }
}
7 голосов
/ 24 января 2017

Просто добавьте простую двухстрочную реализацию C # с использованием рекурсии, потому что все ответы здесь кажутся гораздо более сложными, чем необходимо.

/// <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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...