Как получить определенные элементы из существующего файла Excel, используя C # с Interop.Библиотека Excel?

#c# #.net #excel #office-interop

#c# #.net #excel #office-interop

Вопрос:

Мне нужно получить данные из файла Excel, чтобы распечатать их в HTML-таблице (используя MVC, без gridview) и в конечном итоге сохранить их в базе данных.

Сопоставление между table и Excel выглядит следующим образом:

Excel -> Таблица

Первая строка -> Заголовки таблицы

Другие ячейки -> Табличные данные

Я использую Interop.Библиотека Excel, предоставляющая методы для работы с файлами Excel в .NET.

С помощью этого кода я получаю в переменной lworkSheet N-й лист файла Excel:

 var lworkSheet = xlWorkBook.Worksheets.get_Item(N);
  

Давайте предположим, что файл Excel содержит только один лист (N = 1), я могу использовать специфические свойства листа для получения строк, столбцов, ячеек и диапазона. Эти свойства возвращают объекты типа Interop.Excel.Диапазон.

Проблема в том, что строки, столбцы и ячейки возвращают, соответственно, все строки, столбцы и ячейки в файле Excel, а не только те, которые заполнены данными. Поэтому, чтобы получить данные, которые я делаю (индекс элементов Excel основан на 1):

 var lheaders = xlWorkSheet.Rows.get_Item(1);
var lexcelItems = new Excel.Range[xlWorkSheet.Rows.Count, xlWorkSheet.Columns.Count];

for (var i=0; i < xlWorkSheet.Rows.Count; i  )
{
    for(var j=0; j < xlWorkSheet.Columns.Count; j  )
    {
        lexcelItems[i,j] = xlWorkSheet.Cells.get_Item(i 2, j 1);
    }
}
  

Помимо вычислительных затрат на циклирование всех строк и столбцов, это решение по-прежнему неприемлемо, поскольку метод get_Item() возвращает объекты диапазона!! Чтобы получить элемент в ячейке, я должен использовать метод get_Range(cell_start, cell_end) и указать ячейки в формате «A1», «A2» и т.д. …

ВОПРОСЫ:

1) Есть ли способ определить последний элемент в строке и столбце?

2) Есть ли способ получить значение в ячейке без указания диапазона?

3) Любая библиотека, которая реализует Excel.Увеличение диапазона? (т.Е. (A1 ) == A2 и т.д.).

4) Если ничего из вышеперечисленного не выполнимо, есть ли простой способ прочитать Excel с помощью OLEDB?

Спасибо

Франческо

Ответ №1:

Я не работал с этой библиотекой, поэтому я просто делаю обоснованное предположение из документации MSDN. Вы ищете Worksheet.UsedRange ?

http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel._worksheet.usedrange(v = office.11).aspx

После того, как у вас есть Range , похоже, что вы можете использовать Range.Cells свойство (аналогичное используемому вами Worksheet.Cells свойству), чтобы получить диапазон одной ячейки, а затем использовать свойство Range.Value or Range.Value2 для получения значения этой ячейки:

http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.range_properties(v=office.11).aspx

Чтобы указать ячейки внутри UsedRange на основе позиции, а не имен строк / столбцов, используйте Range.Offset :

http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel.range (v =office.11).aspx

Комментарии:

1. да, это может быть полезно, спасибо. Однако это не решает проблему работы с объектами диапазона. Как бы вы извлекли фактические значения из Excel?

2. Что ж, если вы используете свойства Value и Value2, вам все равно нужно указать диапазон: Range(«a1»).Value, чтобы получить значение в ячейке A1. Моя проблема в том, что я не могу выполнять цикл, если мне каждый раз приходится определять, как увеличивать столбцы на букву алфавита. Проблема возникает, когда после z приходится использовать 2 буквы (от AA до ZZ), затем 3 (от AAA до ZZZ) и так далее.

Ответ №2:

Использование OLEDB для доступа / обработки данных Excel лучше, чем перебор.Cells(); помещение (выбора) листа с одним оператором SQL в таблицу базы данных или .getString результирующий набор в виде HTML-таблицы без каких-либо Fors является привлекательным.

Проблема: если ваши данные содержат мусор, высокоуровневые средства ADO / OLEDB не дадут вам возможности вмешаться.

ДОБАВЛЕНО:

Проводя некоторые эксперименты с тем, что означает «все» для листа Excel, я наткнулся на интересный факт? о «$». Возможно, я не единственный, кто не знает об этом:

Это результат моего тестового скрипта VBScript:

 -------------------------------------------------------------------------------
SELECT * FROM [SakAct$]
-------------------------------------------------------------------------------
|actor_id|first_name|last_name|last_update         |
|       3|ED        |CHASE    |2/15/2006 4:34:33 AM|
|       4|JENNIFER  |DAVIS    |2/15/2006 4:34:33 AM|
|       1|PENELOPE  |GUINESS  |2/15/2006 4:34:33 AM|
|       2|NICK      |WAHLBERG |2/15/2006 4:34:33 AM|
|  <NULL>|ED        |CHASE    |2/15/2006 4:34:33 AM|
|       5|          |DAVIS    |2/15/2006 4:34:33 AM|
|       6|PENELOPE  |         |2/15/2006 4:34:33 AM|
|       7|NICK      |WAHLBERG |       <NULL>       |
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
SELECT * FROM [SakAct]
-------------------------------------------------------------------------------
|actor_id|first_name|last_name|last_update         |
|       3|ED        |CHASE    |2/15/2006 4:34:33 AM|
|       4|JENNIFER  |DAVIS    |2/15/2006 4:34:33 AM|
|       1|PENELOPE  |GUINESS  |2/15/2006 4:34:33 AM|
|       2|NICK      |WAHLBERG |2/15/2006 4:34:33 AM|
-------------------------------------------------------------------------------
  

Похоже, что [Sheet $] включает режим Excel Quirks, который будет учитывать больше строк, чем более строгий подход, поддерживаемый [Sheet].

Комментарии:

1. Спасибо за ваш ответ. Как бы вы, например, получили фактически используемые ячейки с рабочего листа? А первая строка?

2. @Francesco: Если вы выполните команду «ВЫБРАТЬ * ИЗ Sheet1 $», вы получите «все» строки. «Все» определяется поставщиком; вы можете не соглашаться. Но для получения приличных данных у меня никогда не было причин жаловаться. Что касается первой строки: коллекция полей возвращаемого набора записей предоставляет вам имена и типы полей.

3. Хорошо, я понимаю выражение, но откуда вы берете «Sheet1 $»? Что это за объект?

4. «Sheet1» — это имя листа; оно функционирует как имя таблицы в стандартном SQL; $ может потребоваться, а может и не понадобиться, в зависимости от поставщика.