使用OpenXML C#获取Excel单元格的列索引
我一直在寻找一段时间,似乎无法find如何做到这一点。 我有一个Excel表格,我正在使用OpenXML阅读。 现在正常的事情是循环行,然后循环通过单元格获取值,这很好。 但是,随着值我需要的单元格的位置,这将是格式(rowindex,ColumnIndex)。 我设法得到rowIndex,但似乎无法find列索引。
我其实觉得这很容易,但显然不是。
由于可以使用Worksheet.Descendants<Cell>()
循环访问一行的Worksheet.Descendants<Cell>()
,因此可以简单地使用for
-loop来确定单元格的索引。
我有点晚了,回答这个问题,但是如果在你感兴趣的行中有空单元格,那么接受的答案将不起作用,因为它们不能保证在XML中,模式允许空单元格被省略。
要获取索引,您可以使用Cell
对象,其中有一个CellReference
属性,以A1
, B1
等格式给出引用。您可以使用该引用来提取列号。
正如你可能知道的那样,在Excel A = 1
, B = 2
等中,直到Z = 26
在这个点上单元格前缀为A
,给出AA = 27
, AB = 28
等等。注意,在AA
的情况下,具有第二十六倍的价值; 即“值得”26,而第二个“值得”1,总共27。
要计算列索引,您可以反转字母,然后取第一个字母的值,并将其添加到正在运行的总数中。 然后取第二个字母的值并乘以26,将总和加到第一个数字上。 第三,你乘以26乘以两次,第四次乘以26三次,依此类推。
所以对于列ABC
你会这样做:
C = 3 B = 2 * 26 = 52 A = 1 * 26 *26 = 676 3 + 52 + 676 = 731
在C#中,以下内容将起作用:
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; }
请注意, CellReference
不保证在XML中(尽pipe我从来没有见过它)。 在CellReference
为空的情况下,该单元被放置在最左边的可用单元中。 RowIndex
在规范中也不是强制性的,所以在这种情况下,单元格可以放在最高的行中。 更多的信息可以在这个问题中看到。 在CellReference
为null
情况下, CellReference
的答案是正确的。
小是美丽的
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; }
要开始回答,我请你先看看这个 。
正如我所解释的, 没有简单的方法来提取行和列。 你得到的最接近的是提取一个单元格的CellReference
,其格式为A1
, B2
,实际上是COLUMN_ROW
格式。
你可以做的是从CellReference
提取Row和Column。 是的,这将需要你实现一个方法,你需要通过char
检查char
来validation数字和string。
比方说,你有A11
,那么当你需要索引列时,你需要提取A
,这将列为column 1
。 是的,这并不容易,但是除非您在扫描/遍历单元格时只是select计算列数,否则这是唯一的方法。
再次看看这个问题的答案是做同样的事情。
[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 );