Get the Column Index of a Cell in Excel using OpenXML C#

前端 未结 8 1800
北恋
北恋 2020-12-03 17:32

I\'ve been looking around for a while now and cannot seem to find out how to do this. I\'ve got an excel sheet, which I\'m reading using OpenXML. Now the normal thing would

相关标签:
8条回答
  • 2020-12-03 18:00

    Slightly modified GetColumnIndex function in the @petelids answer. Result will be zero-based index. If need add 1 for a one-based Index.

    private static int CellReferenceToIndex(string reference)
    {
        foreach (char ch in reference)
        {
            if (Char.IsLetter(ch))
            {
                int value = (int)ch - (int)'A';
                index = (index == 0) ? value : ((index + 1) * 26) + value;
            }
            else
                return index;
        }
        return index;
    }
    
    0 讨论(0)
  • 2020-12-03 18:02
        [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 );
    
    0 讨论(0)
  • 2020-12-03 18:07

    Small is beautifull

    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;
    }
    
    0 讨论(0)
  • 2020-12-03 18:10
        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]);
                            }
            }
    

    this is to find the total number of columns present/used

    0 讨论(0)
  • 2020-12-03 18:10
        public static void CellReferenceToIndex(string reference, out int row_index, out int col_index)
        {
            row_index = 0;
            col_index = 0;
    
            foreach(char c in reference)
            {
                if (c >= '0' && c <= '9')
                {
                    row_index = row_index * 10 + (c - '0');
                }
                if (c >= 'A' && c <= 'Z')
                {
                    col_index = col_index * ('Z' - 'A' + 1) + (c - 'A' + 1);
                }
            }
        }
    
    0 讨论(0)
  • 2020-12-03 18:12

    This is slightly trickier than you might imagine because the schema allows for empty cells to be omitted.

    To get the index you can use the Cell object wihch has a CellReference property that gives the reference in the format A1, B1 etc. You can use that reference to extract the column number.

    As you probably know, in Excel A = 1, B = 2 etc up to Z = 26 at which point the cells are prefixed with A to give AA = 27, AB = 28 etc. Note that in the case of AA the first A has a value of 26 times the second; i.e. it is "worth" 26 whilst the second A is "worth" 1 giving a total of 27.

    To work out the column index you can reverse the letters then take the value of the first letter and add it to a running total. Then take the value of the second letter and multiply it by 26, adding the total to the first number. For the third you multiply it by 26 twice and add it, for the fourth multiply it by 26 3 times and so on.

    So for column ABC you would do:

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

    In C# the following will work:

    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's COLUMN function
        return columnNumber + 1;
    }
    

    Note that the CellReference is not guaranteed to be in the XML either (although I've never seen it not there). In the case where the CellReference is null the cell is placed in the leftmost available cell. The RowIndex is also not mandatory in the spec so it too can be omitted in which case the cell is placed in the highest row available. More information can be seen in this question. The answer from @BCdotWEB is correct approach in cases where the CellReference is null.

    0 讨论(0)
提交回复
热议问题