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

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

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

Ответы [ 48 ]

2 голосов
/ 18 апреля 2012

В perl, для входа 1 (A), 27 (AA) и т. Д.

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;
}
2 голосов
/ 21 февраля 2014

Другой способ VBA

Public Function GetColumnName(TargetCell As Range) As String
    GetColumnName = Split(CStr(TargetCell.Address), "$")(1)
End Function
2 голосов
/ 03 октября 2013

Решение JavaScript

/**
 * 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;
};
1 голос
/ 24 февраля 2012

Я пытаюсь сделать то же самое в Java ... Я написал следующий код:

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

Теперь, когда я запустил его с columnNumber = 29, он дает мне результат = "CA" (вместо "AC") какие-либо комментарии, что я пропускаю? Я знаю, что могу изменить это с помощью StringBuilder .... Но, глядя на ответ Грэма, я немного растерялся ....

1 голос
/ 10 апреля 2015

Это мои коды для преобразования определенного числа (индекс начинается с 1) в столбец Excel.

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

Мой юнит-тест:

    [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));
    }
1 голос
/ 12 августа 2018

Это версия javascript в соответствии с кодом Грэма

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;
};
1 голос
/ 02 мая 2013

Вот моя супер поздняя реализация в PHP. Этот рекурсивный. Я написал это как раз перед тем, как нашел этот пост. Я хотел посмотреть, решили ли уже эту проблему другие ...

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;
}
1 голос
/ 18 августа 2016

Хотя я опаздываю к игре, Ответ Грэма далеко не оптимален. В частности, вам не нужно использовать modulo, звонить ToString() и применять (int) приведение. Учитывая, что в большинстве случаев в мире C # вы начинаете нумерацию с 0, вот моя ревизия:

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;
}
1 голос
/ 22 марта 2017

Это вопрос, который перенаправляют все остальные, а также Google, поэтому я публикую это здесь.

Многие из этих ответов верны, но слишком громоздки для простых ситуаций, например, когда у вас нет более 26 столбцов. Если у вас есть какие-либо сомнения в том, что вы можете перейти в двухбуквенные столбцы, тогда проигнорируйте этот ответ, но если вы уверены, что не будете, то вы можете сделать это так же просто, как это в 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);
}

Черт, если вы уверены в том, что вы передаете, вы можете даже удалить проверку и использовать эту строку:

(char)('A' + index)

Это будет очень похоже на многие языки, поэтому вы можете адаптировать его по мере необходимости.

Опять же, используйте это, только если вы на 100% уверены, что у вас не будет более 26 столбцов .

1 голос
/ 05 ноября 2017

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

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

Пройдены следующие тестовые случаи:

  • Номер столбца: 494286 => ABCDZ
  • Номер столбца: 27 => AA
  • Номер столбца: 52 => AZ
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...