Существует хорошая библиотека для Java Apache POI - the Java API for Microsoft Documents http://poi.apache.org/, которая позволяет работать с документами Microsoft. Была создана портация этой библиотеки на C# и называется она NPOI http://npoi.codeplex.com/. В данной заметке будет описан пример использования NPOI.
Теперь напишем код по выгрузке данных в Excel файл.
Для получения библиотеки идём на сайт https://npoi.codeplex.com/ переходим в раздел Downloads и скачиваем последнюю версию, на момент написания заметки это 2.1.3.1. Разархивируем архив папку с библиотеками.
В архиве есть библиотеки для версии Net 4.0 и Net 2.0.
Теперь создаём тестовый проект в VisulaStudio. Назовём его к примеру TestNPOI.
Добавим на форму 2 текстовых окна для добавления файлов и две кнопки.
В Referens проекта добавим скачанные библиотеки, в моём случае я добавлял библиотеки для Net 4.0.
Напишем код для сохранения файла в Excel в формат xlsx. К нашему модулю нужно подключить стандартные модули и два модуля using NPOI.SS.UserModel; и NPOI NPOI.XSSF.UserModel:
using System.IO;
using System.Windows;
using System.Diagnostics;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
Теперь напишем код по выгрузке данных в Excel файл.
private void bSaveFile_Click(object sender, RoutedEventArgs e)
{
//Рабочая книга Excel
XSSFWorkbook wb;
//Лист в книге Excel
XSSFSheet sh;
//Создаем рабочую книгу
wb = new XSSFWorkbook();
//Создаём лист в книге
sh = (XSSFSheet)wb.CreateSheet("Лист 1");
//Количество заполняемых строк
int countRow = 3;
//Количество заполняемых столбцов
int countColumn = 3;
//Запускаем цыкл по строка
for (int i = 0; i < countRow; i++)
{
//Создаем строку
var currentRow = sh.CreateRow(i);
//Запускаем цикл по столбцам
for (int j = 0; j < countColumn; j++)
{
//в строке создаём ячеёку с указанием столбца
var currentCell = currentRow.CreateCell(j);
//в ячейку запишем информацию о текущем столбце и строке
currentCell.SetCellValue("Строка - "+(i+1).ToString()+"Столбец - "+(j+1).ToString());
//Выравним размер столбца по содержимому
sh.AutoSizeColumn(j);
}
}
// Удалим файл если он есть уже
if (!File.Exists(tbSaveFile.Text))
{
File.Delete(tbSaveFile.Text);
}
//запишем всё в файл
using (var fs = new FileStream(tbSaveFile.Text, FileMode.Create, FileAccess.Write))
{
wb.Write(fs);
}
//Откроем файл
Process.Start(tbSaveFile.Text);
}
В результате получи следующий файл
Теперь сохраним этот файл в TestLoad.xlsx и напишем код по чтению данных из файла.
private void bLoadFile_Click(object sender, RoutedEventArgs e)
{
//Книга Excel
XSSFWorkbook xssfwb;
//Открываем файл
using (FileStream file = new FileStream(tbLoadFile.Text, FileMode.Open, FileAccess.Read))
{
xssfwb = new XSSFWorkbook(file);
}
//Получаем первый лист книги
ISheet sheet = xssfwb.GetSheetAt(0);
//запускаем цикл по строкам
for (int row = 0; row <= sheet.LastRowNum; row++)
{
//получаем строку
var currentRow = sheet.GetRow(row);
if (currentRow != null) //null когда строка содержит только пустые ячейки
{
//запускаем цикл по столбцам
for (int column = 0; column < 3; column++)
{
//получаем значение яейки
var stringCellValue = currentRow.GetCell(column).StringCellValue;
//Выводим сообщение
MessageBox.Show(string.Format("Ячейка {0}-{1} значение:{2}", row,column,stringCellValue));
}
}
}
}
Этот код не скомпилится, если не сделать ещё три юзинга:
ОтветитьУдалитьusing System.IO;
using System.Diagnostics;
using NPOI.SS.UserModel;
Спасибо, поправил.
УдалитьДобавлю ещё: класс XSSF - это только один из классов в библиотеке (отвечает за формат xlsx, насколько я понял). Но вообще-то это может и не сработать, т.к. зависит от используемой версии офиса (тестировал на excel 2007 - работает через пень-колоду, на этой версии лучше работает HSSF).
ОтветитьУдалитьТак что рекомендую работать с интерфейсом ISheet, от которого унаследованы все эти классы, а полиморфизм всё сделает за нас.
А можно что то подобное для открытия файла xls?
ОтветитьУдалитьЛучше использовать интерфейс для работы как-то так
Удалить{
//Книга Excel
IWorkbook workbook;
//Открываем файл
using (FileStream file = new FileStream(tbLoadFile.Text, FileMode.Open, FileAccess.Read))
{
workbook = WorkbookFactory.Create(inputStream);
}
//Получаем первый лист книги
ISheet sheet = workbook.GetSheetAt(0);
//запускаем цикл по строкам
for (int row = 0; row <= sheet.LastRowNum; row++)
{
//получаем строку
var currentRow = sheet.GetRow(row);
if (currentRow != null) //null когда строка содержит только пустые ячейки
{
//запускаем цикл по столбцам
for (int column = 0; column < 3; column++)
{
//получаем значение яейки
var stringCellValue = currentRow.GetCell(column).StringCellValue;
//Выводим сообщение
MessageBox.Show(string.Format("Ячейка {0}-{1} значение:{2}", row,column,stringCellValue));
}
}
}
}
WorkbookFactory - сама разрулит какой формат файла подается на вход https://github.com/tonyqus/npoi/blob/master/ooxml/SS/UserModel/WorkbookFactory.cs
А где можно посмотреть описания свойств и методов библиотеки NPOI?
ОтветитьУдалитьА то, например, как задать стили границ ячеек, или цвет и толщину линий таблицы, форматы ячеек как устанавливать и прочие моменты форматирвоания пока не очень понятны...
На сколько я знаю NPOI порт java библиотеки POI доки по ней https://poi.apache.org/apidocs/index.html. Есть еще блог разработчика http://www.leniel.net/2014/01/npoi-2.0-major-features-enhancements-series-of-posts-scheduled.html, на кодеплексе http://npoi.codeplex.com/ и на гидхабе https://github.com/tonyqus/npoi и еще nuget https://www.nuget.org/packages/NPOI/2.0.6
УдалитьОго сколько сразу источников! Спасибо! Буду изучать.
УдалитьПривет, а не подскажете AutoSizeColumn() падает при 10 000 строк... Как сделать автосайз для большиого кол-во строк...?
ОтветитьУдалитьПривет, не сталкивался с таким, знаю AutoSizeColumn() он тормозной, там рассчитывается размер текста все зависит от шрифта, его нужно вызывать единожды после формирования всего документа. Возможно слишким долго просто выполняется.
УдалитьДобрый день! Так я пока и не разобрался как сделать, например, границы таблицы (и шапки таблицы) толще, и как в ячейках можно устанавливать жирный шрифт, или курсив, размер шрифта... Подскажите пожалуйста об этом, если работали с такими функциями в NPOI. Заранее спасибо!
ОтветитьУдалить//Рабочая книга Excel
ОтветитьУдалитьHSSFWorkbook wb;
//Создаем рабочую книгу
wb = new HSSFWorkbook();
//Лист в книге Excel
HSSFSheet sh;
//диапазон ячеек
CellRangeAddress cellRange;
//создаем столбец
HSSFRow currentRow = (HSSFRow)sh.CreateRow(currentRowNum);
//Создаем ячейку
HSSFCell currentCell = (HSSFCell)currentRow.CreateCell(i);
//задаем значение в ячейке
currentCell.SetCellValue("Hellow world");
//Свойства ячейки можно задать через CellStyle
//подробнее он описан
//https://github.com/tonyqus/npoi/blob/master/main/HSSF/UserModel/HSSFCellStyle.cs
//в данном случае устанавливаем перенос строк
currentCell.CellStyle.WrapText = true;
//Создаем диапазон, в данном случае из одной ячейки
cellRange = new CellRangeAddress(currentCell.RowIndex, currentCell.RowIndex, currentCell.ColumnIndex, currentCell.ColumnIndex);
//Задаем рамку ячейки в данном примере Thin это тонкая обводка
// все варианты границ https://github.com/tonyqus/npoi/blob/master/main/SS/UserModel/BorderStyle.cs HSSFRegionUtil.SetBorderBottom(NPOI.SS.UserModel.BorderStyle.Thin, cellRange, sh, wb);
HSSFRegionUtil.SetBorderTop(NPOI.SS.UserModel.BorderStyle.Thin, cellRange, sh, wb);
HSSFRegionUtil.SetBorderRight(NPOI.SS.UserModel.BorderStyle.Thin, cellRange, sh, wb);
HSSFRegionUtil.SetBorderLeft(NPOI.SS.UserModel.BorderStyle.Thin, cellRange, sh, wb);
Большое спасибо, помогло!
УдалитьВот только это работает для XLS, а для XLSX аналога HSSFRegionUtil я что-то не нашел. Аналогичного "XSSFRegionUtil" не существует. Не подскажите какая функция для xlsx в этом случае подходит?
Кстати, добавлю ещё один полезный ресурс по описанию функций библиотеки NPOI. Случайно сам наткнулся, в процессе поисков:
www.nudoq.org/#!/Packages/NPOI/NPOI/
По хорошему нужно перейти к интерфейсам из пакета npoi/main/SS/UserModel/ https://github.com/tonyqus/npoi/tree/master/main/SS/UserModel, как тут советовал анонимный в первых 2-х коментариях, а потом по аналогии с java кодом https://poi.apache.org/spreadsheet/quick-guide.html#Borders
УдалитьСпасибо! Буду разбираться.
УдалитьА я пока нашел другой способ, но там работа с каждой ячейкой, а не с диапазоном. Диапазон пока нашел, но в общем-то для моего случая установка стиля границ для всех (каждой) ячеек, даже лучше выглядит. Так, что ещё раз спасибо за ценную информацию!
Чувак, как добавить примечание к ячейке
ОтветитьУдалить