Получить индекс столбца ячейки в 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 с индексом ячейки.