понедельник, 16 марта 2015 г.

NPOI пример использования

Существует хорошая библиотека для Java Apache POI - the Java API for Microsoft Documents http://poi.apache.org/, которая позволяет работать с документами Microsoft. Была создана портация этой библиотеки на C# и называется она NPOI http://npoi.codeplex.com/. В данной заметке будет описан пример использования NPOI.
Для получения библиотеки идём на сайт 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));
                    }
                }
            }
        }




16 комментариев:

  1. Этот код не скомпилится, если не сделать ещё три юзинга:
    using System.IO;
    using System.Diagnostics;
    using NPOI.SS.UserModel;

    ОтветитьУдалить
  2. Добавлю ещё: класс XSSF - это только один из классов в библиотеке (отвечает за формат xlsx, насколько я понял). Но вообще-то это может и не сработать, т.к. зависит от используемой версии офиса (тестировал на excel 2007 - работает через пень-колоду, на этой версии лучше работает HSSF).
    Так что рекомендую работать с интерфейсом ISheet, от которого унаследованы все эти классы, а полиморфизм всё сделает за нас.

    ОтветитьУдалить
  3. А можно что то подобное для открытия файла xls?

    ОтветитьУдалить
    Ответы
    1. Лучше использовать интерфейс для работы как-то так
      {
      //Книга 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

      Удалить
  4. А где можно посмотреть описания свойств и методов библиотеки NPOI?
    А то, например, как задать стили границ ячеек, или цвет и толщину линий таблицы, форматы ячеек как устанавливать и прочие моменты форматирвоания пока не очень понятны...

    ОтветитьУдалить
    Ответы
    1. На сколько я знаю 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

      Удалить
    2. Ого сколько сразу источников! Спасибо! Буду изучать.

      Удалить
  5. Привет, а не подскажете AutoSizeColumn() падает при 10 000 строк... Как сделать автосайз для большиого кол-во строк...?

    ОтветитьУдалить
    Ответы
    1. Привет, не сталкивался с таким, знаю AutoSizeColumn() он тормозной, там рассчитывается размер текста все зависит от шрифта, его нужно вызывать единожды после формирования всего документа. Возможно слишким долго просто выполняется.

      Удалить
  6. Добрый день! Так я пока и не разобрался как сделать, например, границы таблицы (и шапки таблицы) толще, и как в ячейках можно устанавливать жирный шрифт, или курсив, размер шрифта... Подскажите пожалуйста об этом, если работали с такими функциями в NPOI. Заранее спасибо!

    ОтветитьУдалить
  7. //Рабочая книга 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);

    ОтветитьУдалить
    Ответы
    1. Большое спасибо, помогло!
      Вот только это работает для XLS, а для XLSX аналога HSSFRegionUtil я что-то не нашел. Аналогичного "XSSFRegionUtil" не существует. Не подскажите какая функция для xlsx в этом случае подходит?

      Кстати, добавлю ещё один полезный ресурс по описанию функций библиотеки NPOI. Случайно сам наткнулся, в процессе поисков:
      www.nudoq.org/#!/Packages/NPOI/NPOI/

      Удалить
    2. По хорошему нужно перейти к интерфейсам из пакета 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

      Удалить
    3. Спасибо! Буду разбираться.
      А я пока нашел другой способ, но там работа с каждой ячейкой, а не с диапазоном. Диапазон пока нашел, но в общем-то для моего случая установка стиля границ для всех (каждой) ячеек, даже лучше выглядит. Так, что ещё раз спасибо за ценную информацию!

      Удалить
  8. Чувак, как добавить примечание к ячейке

    ОтветитьУдалить