Получить индекс столбца ячейки в Excel с помощью OpenXML С#

Я уже некоторое время смотрю вокруг и не могу понять, как это сделать. У меня есть лист Excel, который я читаю с помощью OpenXML. Теперь нормальным было бы перебирать строки, а затем перебирать ячейки, чтобы получить значения, что хорошо. Но вместе со значениями мне нужно расположение ячейки, которая будет в формате (rowindex, ColumnIndex). Мне удалось получить rowIndex, но can not, кажется, выясняет получение индекса столбца.

Я действительно думал, что это будет легко, но, видимо, это не так.

Ответ 1

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

Чтобы получить индекс, вы можете использовать объект Cell которого есть свойство CellReference которое дает ссылку в формате A1, B1 и т.д. Вы можете использовать эту ссылку для извлечения номера столбца.

Как вы, вероятно, знаете, в Excel A = 1, B = 2 т.д. До Z = 26 в этот момент ячейки имеют префикс A чтобы дать AA = 27, AB = 28 и т.д. Обратите внимание, что в случае AA первый A имеет значение, в 26 раз превышающее второе; т.е. "стоит" 26 в то время как второй A "стоит" 1 дает в общей сложности 27.

Чтобы определить индекс столбца, вы можете поменять местами буквы, затем взять значение первой буквы и добавить его к промежуточной сумме. Затем возьмите значение второй буквы и умножьте его на 26, добавив сумму к первому числу. Для третьего вы умножаете это на 26 дважды и добавляете, для четвертого умножаете это на 26 в 3 раза и так далее.

Таким образом, для столбца ABC вы должны сделать:

C = 3
B = 2 * 26 = 52
A = 1 * 26 *26 = 676
3 + 52 + 676 = 731

В С# будет работать следующее:

private static int? GetColumnIndex(string cellReference)
{
    if (string.IsNullOrEmpty(cellReference))
    {
        return null;
    }

    //remove digits
    string columnReference = Regex.Replace(cellReference.ToUpper(), @"[\d]", string.Empty);

    int columnNumber = -1;
    int mulitplier = 1;

    //working from the end of the letters take the ASCII code less 64 (so A = 1, B =2...etc)
    //then multiply that number by our multiplier (which starts at 1)
    //multiply our multiplier by 26 as there are 26 letters
    foreach (char c in columnReference.ToCharArray().Reverse())
    {
        columnNumber += mulitplier * ((int)c - 64);

        mulitplier = mulitplier * 26;
    }

    //the result is zero based so return columnnumber + 1 for a 1 based answer
    //this will match Excel COLUMN function
    return columnNumber + 1;
}

Обратите внимание, что CellReference не гарантированно находится в XML (хотя я никогда не видел его там). В случае, когда CellReference равен нулю, ячейка помещается в CellReference доступную ячейку. RowIndex также не является обязательным в спецификации, поэтому он также может быть опущен, и в этом случае ячейка размещается в самой высокой доступной строке. Больше информации можно увидеть в этом вопросе. Ответ от @BCdotWEB - правильный подход в случаях, когда CellReference имеет значение null.

Ответ 2

Поскольку вы можете прокручивать ячейки строки с помощью Worksheet.Descendants<Cell>(), вы можете просто использовать for -loop для определения индекса ячейки.

Ответ 3

Маленький красив

int ColumnIndex(string reference)
{
  int ci=0;
  reference=reference.ToUpper();
  for (int ix = 0; ix < reference.Length && reference[ix] >= 'A';ix++ ) 
       ci = (ci * 26) + ((int)reference[ix] - 64);
  return ci;
}

Ответ 4

Чтобы начать отвечать, я приглашаю вас сначала посмотреть этот.

Как я уже сказал, есть NO простой способ извлечения строк и столбцов. Ближе всего вы получите извлечение CellReference ячейки, которая будет иметь форму A1, B2, которая является актуальной COLUMN_ROW.

Что вы можете сделать, это извлечь строки и столбцы из CellReference. Да, вам понадобится реализовать метод, в котором вам нужно проверить char на char для проверки чисел и строк.

Допустим, у вас есть A11, тогда, когда вам нужно индексировать столбец, вам нужно извлечь A, который будет отображаться как column 1. Да, это не так просто, но это единственный способ, если вы просто не захотите подсчитывать столбцы при сканировании/повторении через ячейки.

Снова просмотрите этот ответ на вопрос, который делает то же самое.

Ответ 5

    [TestCase( 1, 0, "A1" )]
    [TestCase( 2, 25, "Z2" )]
    [TestCase( 2, 38, "AM2" )]
    [TestCase( 2, (26 * 4) + 1, "DB2" )]
    [TestCase( 2, (26 * 26 * 26 * 18) + (26 * 26 * 1) + (26 * 26 * 1) + ( 26 * 1 ) + 2, "RBAC2" )]
    public void CanGetCorrectCellReference( int row, int column, string expected )
        => GetCellReference( (uint)row, (uint)column ).Value.ShouldEqual( expected );

    public static StringValue GetCellReference( uint row, uint column ) =>
        new StringValue($"{GetColumnName("",column)}{row}");

    static string GetColumnName( string prefix, uint column ) => 
        column < 26 ? $"{prefix}{(char)( 65 + column)}" : 
        GetColumnName( GetColumnName( prefix, ( column - column % 26 ) / 26 - 1 ), column % 26 );

Ответ 6

    Row row = worksheetPart.Worksheet.GetFirstChild<SheetData>().Elements<Row>().FirstOrDefault();
   var totalnumberOfColumns = 0;
    if (row != null)
        {
            var spans = row.Spans != null ? row.Spans.InnerText : "";
                if (spans != String.Empty)
                        {
                            //spans.Split(':')[1];
                            string[] columns = spans.Split(':');
                            startcolumnInuse = int.Parse(columns[0]);
                            endColumnInUse = int.Parse(columns[1]);
                            totalnumberOfColumns = int.Parse(columns[1]);
                        }
        }

, чтобы найти общее количество присутствующих/используемых столбцов введите описание изображения здесь

Ответ 7

<members>
    <member type="String" modifier="public" cellIndex="0">firstName</member>
    <member type="String" modifier="public"  cellIndex="1">lastName</member>
    <member type="int" modifier="public"  cellIndex="2">age</member>
    <member type="String" modifier="public"  cellIndex="3">gender</member>
    <member type="int" modifier="public"  cellIndex="4">marks</member>
</members>

Это XML-формат файла Excel, я хочу прочитать и повторить эти XML-данные и тем самым изменить столбец Excel с индексом ячейки.