C #: получение количества строк / столбцов с помощью ExcelPackage - PullRequest
34 голосов
/ 11 ноября 2009

Мне нужно читать и записывать данные из электронной таблицы Excel. Есть ли способ узнать, сколько строк / столбцов на определенном листе имеет ExcelPackage? У меня есть следующий код:

FileInfo newFile = new FileInfo(@"C:\example.xlsx");
using (ExcelPackage xlPackage = new ExcelPackage(newFile)) 
{
    ExcelWorksheet worksheet = xlPackage.Workbook.Worksheets[1];
}

Мне нужно перебрать каждую ячейку этой таблицы и разбить ее на довольно большую таблицу, но я не хочу выводить пустые ячейки или получать исключение Есть ли метод, напоминающий worksheet.rowNum или colNum?

Ответы [ 9 ]

41 голосов
/ 14 сентября 2012

Количество строк и столбцов можно получить с помощью ExcelPackage (EPPlus.dll версия 3.0.0.2), как показано ниже:

  var rowCnt = worksheet.Dimension.End.Row;
  var colCnt = worksheet.Dimension.End.Column;
11 голосов
/ 07 июня 2013

Вот что я делаю:

Чтобы получить массив значений в книге:

object[,] valueArray = sheet.Cells.GetValue<object[,]>();

, чтобы получить диапазон:

int rangeMaxRows = sheet.Dimension.End.Row; 
int rangeMaxColumns = sheet.Dimension.End.Column;
6 голосов
/ 11 ноября 2009

Я бы начал со свойства UsedRange, а затем для каждой ячейки в финальной строке UsedRange сделайте Cell.End (xlUp). Это должно получить окончательную ячейку для каждого столбца, ячейка с максимальным индексом строки является последней ячейкой в ​​вашем истинно используемом диапазоне.

Свойство UsedRange может отображаться неправильно, поскольку когда ячейки очищаются, но не удаляются, свойство UsedRange не обновляется. Чтобы снова сделать свойство UsedRange действительным, просто выделите все строки и столбцы после вашей последней ячейки (то есть все пустые ячейки) и перейдите в edit-> delete.

5 голосов
/ 11 октября 2012
int row = _excelSheet.Rows.CurrentRegion.EntireRow.Count;
int col = _excelSheet.Columns.CurrentRegion.EntireColumn.Count;
3 голосов
/ 15 ноября 2009

Я просто сделал следующий цикл, чтобы решить проблему. Это прекрасно работает, только если вы знаете, сколько столбцов будет заранее. В противном случае потребуется еще одна итерация цикла.

int totalCells = 0;
int totalRows = -1;

do
{
     totalRows++;
} while (worksheet.Cell(totalRows + 1, 1).Value != @"");
totalCells = totalRows * 12;
1 голос
/ 11 ноября 2009

Я просмотрел несколько сайтов, используя библиотеку ExcelPackage.
Также на странице codeplex есть вопрос - как узнать количество строк / столбцов?

Кажется, поддержки нет. Извините, документация также недоступна.
Вам нужно будет выполнить итерацию по строкам / столбцам (имея в виду максимальное количество строк / столбцов, которое может содержать таблица) и проверить, содержит ли ячейка какое-либо значение.

См. Эту ссылку - http://web.archive.org/web/20110123164144/http://nayyeri.net/use-excelpackage-to-manipulate-open-xml-excel-files (исходная ссылка не работает)

1 голос
/ 11 ноября 2009

Я использовал sheet.UsedRange сам по себе, но заметил, что некоторые ячейки в конце диапазона были пустыми, но все еще включены в диапазон.

Это работает, однако для эффективности вам, возможно, лучше начать с последней строки в диапазоне и отсчитывать назад, чтобы увидеть, где заканчиваются ваши данные (в отличие от этого фрагмента, начинающегося с первой строки!)

        int count = 0;
        E.Range excelRange = sheet.UsedRange;
        object[,] valueArray = (object[,])excelRange.get_Value(E.XlRangeValueDataType.xlRangeValueDefault);
        if (valueArray.GetUpperBound(0) > 1)
        {
            for (int i = 0; i < valueArray.GetUpperBound(0) + 2; i++)
            {
                if (valueArray[i + 2, 1] == null)
                    break;
                else
                    count++;
            }
        }
0 голосов
/ 27 июня 2019

Лучший способ получить общее количество строк и столбцов с помощью этих методов:

int col = sheet.Dimension.Columns;
int row = sheet.Dimension.Rows;
0 голосов
/ 31 марта 2013

Epplus не имеет поддержки usedrange, но вы можете использовать его с помощью usedrange.cs Предполагая, что вы загрузили последний исходный код EPPlus, Внести изменения в Worksheet.cs: сделать исходный частичный . а затем создайте отдельный файл cs с именем UsedRange.cs, вставьте в него приведенный ниже код и скомпилируйте.

namespace OfficeOpenXml
{
   using System;
   using System.Collections.Generic;
   using System.Text;
   using OfficeOpenXml.Style;
   using System.Data;
/// <summary>
/// This class provides easy access to used range objects such as
/// UsedRows, UsedColumns, UsedCells, UsedRow, UsedColumn etc.
/// Authored by Mukesh Adhvaryu
/// </summary>
public sealed class UsedRange : ExcelRange,IEnumerable<UsedRange>
{
    #region local variables
    int elementIndex=-1, cursor=-1, position=-1;
    UsedRangeElement element, parentElement;
    public const long MaxCells =(long) ExcelPackage.MaxRows *  
(long)ExcelPackage.MaxColumns;
    #endregion

    #region constructors
    /// <summary>
    /// this constructor is private because its accessibility outside can cause mess
    /// </summary>
    /// <param name="sheet"></param>
    /// <param name="element"></param>
    /// <param name="elementIndex"></param>
    /// <param name="cursor"></param>
    UsedRange(ExcelWorksheet sheet, UsedRangeElement element, int elementIndex, int cursor)
        : base(sheet)
    {
        this.element = element;
        switch (element)
        {
            case UsedRangeElement.Rows:
            case UsedRangeElement.Columns:
            case UsedRangeElement.Cells:
                parentElement = UsedRangeElement.Range;
                break;
            case UsedRangeElement.Row:
                parentElement = UsedRangeElement.Rows;
                break;
            case UsedRangeElement.Column:
                parentElement = UsedRangeElement.Columns;
                break;
            case UsedRangeElement.Cell:
                parentElement = UsedRangeElement.Cells;
                break;
            case UsedRangeElement.RowCell:
                parentElement = UsedRangeElement.Row;
                break;
            case UsedRangeElement.ColumnCell:
                parentElement = UsedRangeElement.Column;
                break;
            default:
                parentElement = 0;
                break;
        }
        this.elementIndex = elementIndex;
        this.cursor = cursor;
        SetRange();
    }

    /// <summary>
    /// this constructor is private because its accessibility outside can cause mess
    /// </summary>
    /// <param name="sheet"></param>
    /// <param name="element"></param>
    /// <param name="elementIndex"></param>
    UsedRange(ExcelWorksheet sheet, UsedRangeElement element, int elementIndex)
        : this(sheet, element, elementIndex, -1) { }

    /// <summary>
    /// this constructor is private because its accessibility outside can cause mess
    /// </summary>
    /// <param name="sheet"></param>
    /// <param name="element"></param>
    UsedRange(ExcelWorksheet sheet, UsedRangeElement element)
        : this(sheet, element, -1, -1) { }

    /// <summary>
    /// this constructor used only to create cellcollection range
    /// since cellindex can be very large long value considering rows * columns =no of cells in worksheet
    /// this constructor is private because its accessibility outside can cause mess
    /// </summary>
    /// <param name="sheet"></param>
    /// <param name="cellIndex"></param>
    UsedRange(ExcelWorksheet sheet, long cellIndex)
        : base(sheet)
    {
        this.element = UsedRangeElement.Cell;
        this.parentElement = UsedRangeElement.Cells;
        CellToAddress(cellIndex);
        SetRange();
    }
    #endregion

    #region indexers & properties
    /// <summary>
    /// Returns element at a given index 
    /// </summary>
    /// <param name="index"></param>
    /// <returns></returns>
    public UsedRange this[int index]
    {
        get
        {
            if (index >= Count || index < 0) throw new IndexOutOfRangeException();
            switch (element)
            {
                case UsedRangeElement.Rows:
                    ValidateRow(index);
                    return new UsedRange(_worksheet, UsedRangeElement.Row, index);
                case UsedRangeElement.Columns:
                    ValidateCol(index);
                    return new UsedRange(_worksheet, UsedRangeElement.Column, index);
                case UsedRangeElement.Cells:
                    ValidateCell(index);
                    return new UsedRange(_worksheet, index);
                case UsedRangeElement.Row:
                    return new UsedRange(_worksheet, UsedRangeElement.RowCell, elementIndex, index);
                case UsedRangeElement.Column:
                    return new UsedRange(_worksheet, UsedRangeElement.ColumnCell, elementIndex, index);
                default:
                    return this;
            }
        }
    }

    /// <summary>
    /// Returns particular Cell at a given index
    /// </summary>
    /// <param name="index"></param>
    /// <returns></returns>
    public UsedRange this[long index]
    {
        get
        {
            ValidateCell(index);
            return new UsedRange(_worksheet, index);
        }
    }

    /// <summary>
    /// Returns count of elements in this collection
    /// </summary>
    public int Count
    {
        get
        {
            switch (element)
            {
                case UsedRangeElement.Rows:
                case UsedRangeElement.Column:
                    return _toRow - _fromRow + 1;
                case UsedRangeElement.Columns:
                case UsedRangeElement.Row:
                    return _toCol - _fromCol + 1;
                case UsedRangeElement.Cells:
                case UsedRangeElement.Range:
                    return (_toRow - _fromRow + 1) * (_toCol - _fromCol + 1);
                default:
                    return 1;
            }
        }
    }

    /// <summary>
    /// Returns type of this element collection
    /// </summary>
    public UsedRangeElement Element
    {
        get { return element; }
    }

    /// <summary>
    /// Returns parent type of element this collection
    /// </summary>
    public UsedRangeElement ParentElement
    {
        get { return parentElement; }
    }
    #endregion

    #region private methods
    /// <summary>
    /// Validates row index for row collection
    /// added by mukesh
    /// </summary>
    /// <param name="Row"></param>
    private void ValidateRow(int Row)
    {
        if (Row < 0 || Row > ExcelPackage.MaxRows)
        {
            throw (new ArgumentException("Row out of range"));
        }
    }

    /// <summary>
    /// Validates column index for column collection
    /// added by mukesh
    /// </summary>
    /// <param name="Col"></param>
    private void ValidateCol(int Col)
    {
        if (Col < 0 || Col > ExcelPackage.MaxColumns)
        {
            throw (new ArgumentException("Column out of range"));
        }
    }

    /// <summary>
    /// Validates cell index for cell collection
    /// added by mukesh
    /// </summary>
    /// <param name="Cell"></param>
    private void ValidateCell(long Cell)
    {
        if (Cell <0 || Cell > UsedRange.MaxCells)
        {
            throw (new ArgumentException("Cell out of range"));
        }

    }

    /// <summary>
    /// converts cell index into a point consists of row and column index.
    /// added by mukesh
    /// </summary>
    /// <param name="Cell"></param>
    private void CellToAddress(long Cell)
    {
        long rc = ((_worksheet._cells[_worksheet._cells.Count - 1] as ExcelCell).Row
                    - (_worksheet._cells[0] as ExcelCell).Row) + 1;
        long cc = _worksheet._maxCol - _worksheet._minCol + 1;
        elementIndex = (int)(Cell / cc) + 1;
        cursor = (int)(Cell % cc) + 1;
    }

    /// <summary>
    /// This method is added by mukesh
    /// </summary>
    /// <returns>
    /// Excel Range Object
    /// </returns>
    ExcelRange SetRange()
    {
        switch (element)
        {
            case UsedRangeElement.Rows:
            case UsedRangeElement.Columns:
            case UsedRangeElement.Cells:
                return this[(_worksheet._cells[0] as ExcelCell).Row, _worksheet._minCol,
                (this._worksheet._cells[_worksheet._cells.Count - 1] as ExcelCell).Row,
                _worksheet._maxCol];

            case UsedRangeElement.Row:
                return this[elementIndex + 1, _worksheet._minCol, elementIndex + 1, _worksheet._maxCol];

            case UsedRangeElement.Column:
                return this[(_worksheet._cells[0] as ExcelCell).Row, elementIndex + 1,
                (_worksheet._cells[_worksheet._cells.Count - 1] as ExcelCell).Row, elementIndex + 1];
            case UsedRangeElement.RowCell:
            case UsedRangeElement.Cell:
                return this[elementIndex + 1, cursor + 1];
            case UsedRangeElement.ColumnCell:
                return this[cursor + 1, elementIndex + 1];
            default:
                return this;
        }
    }
    #endregion

    #region internal static methods
    /// <summary>
    /// these static methods will be used to return row collection from worksheet
    /// added by mukesh
    /// </summary>
    /// <param name="sheet"></param>
    /// <returns></returns>
    internal static UsedRange RowCollection(ExcelWorksheet sheet)
    {
        return new UsedRange(sheet, UsedRangeElement.Rows);
    }

    /// <summary>
    /// these static methods will be used to return column collection from worksheet
    /// added by mukesh
    /// </summary>
    /// <param name="sheet"></param>
    /// <returns></returns>
    internal static UsedRange ColumnCollection(ExcelWorksheet sheet)
    {
        return new UsedRange(sheet, UsedRangeElement.Columns);
    }

    /// <summary>
    /// these static methods will be used to return cell collection from worksheet
    /// added by mukesh
    /// </summary>
    /// <param name="sheet"></param>
    /// <returns></returns>
    internal static UsedRange CellCollection(ExcelWorksheet sheet)
    {
        return new UsedRange(sheet, UsedRangeElement.Cells);
    }
    #endregion

    #region ienumerable implementation
    public new IEnumerator<UsedRange> GetEnumerator()
    {
        position = -1;
        for (int i = 0; i < Count; i++)
        {
            ++position;
            yield return this[i];
        }
    }
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }
    #endregion

    /// <summary>
    /// Determine Type of Used range element. 
    /// Being used to return RowCollection, ColumnCollection, CellCollection or single Row, Column or Cell
    /// added by mukesh
    /// </summary>
    public enum UsedRangeElement
    {
        Range, Rows, Columns, Cells,
        Row, Column, Cell, RowCell, ColumnCell
    }
}

public sealed partial class ExcelWorksheet : XmlHelper
{
    /// <summary>
    /// Provides access to a range of used rows
    /// </summary>  
    public UsedRange UsedRows
    {
        get
        {
            return UsedRange.RowCollection(this);
        }
    }
    /// <summary>
    /// Provides access to a range of used columns. added by mukesh
    /// </summary>  
    public UsedRange UsedColumns
    {
        get
        {
            return UsedRange.ColumnCollection(this);
        }
    }
    /// <summary>
    /// Provides access to a range of used cells. added by mukesh
    /// </summary>  
    public UsedRange UsedCells
    {
        get
        {
            return UsedRange.CellCollection(this);
        }
    }
    /// <summary>
    /// UsedRange object of the worksheet. added by mukesh
    /// this range contains used Top left cell to Bottom right.
    /// If the worksheet has no cells, null is returned
    /// </summary>
}
}
...