Задача: вывести данные в таблицу Excel с красивым оформлением и открыть ее, чтобы пользователь мог напечатать или сохранить средствами самого Excel. Необходимо поддерживать все версии Office, начиная с 97, то есть вывод в новые xml-форматы Office 2007 и выше невозможен
Самая сложная часть - работа с оформлением, так как во-первых интерфейс Excel крайне неочевиден, запутан и плохо документирован, во-вторых оформление Excel таблицы из кода работает достаточно медленно. В связи с этим в большинстве случаев подойдет вариант с использованием шаблонов .xlt. Так как мы выводим файл для просмотра и печати, без расчета на сложные вычисления, диаграммы и прочие прелести жизни, мы можем привести формат всех ячеек к тексту и забыть про различные типы данных.
Таким образом задача сводится к следующему:
1) Подготовить файлы шаблонов для разных типов выборок (шапка, размер шрифта, перенос по словам, ширина столбцов)
2) Взять данные из программы и вывести их в нужное место шаблона (как правило это прямоугольный массив ячеек соответствующий DataTable)
3) Подключить к проекту dll-библиотеку Excel Microsoft.Office.Interop.Excel в раздел references и проставить параметр копирования библиотеки к скомпилированным файлами CopyLocal в True.
4) Написать класс для работы с Excel и вывести через него данные из таблицы
При такой постановки задачи "Но это же неэстетично! - Зато дешево, надежно и практично" сам класс работы с Excel получается достаточно простым, но превосходно выполняет поставленную задачу
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Excel = Microsoft.Office.Interop.Excel; namespace TestProject { // Класс документа Excel скрывает подробности работы с эксел, требует добавления в References библиотеки Microsoft.Office.Interop.Excel public class ExcelDocument { private Excel.Application _application = null; private Excel.Workbook _workBook = null; private Excel.Worksheet _workSheet = null; private object _missingObj = System.Reflection.Missing.Value; //КОНСТРУКТОР public ExcelDocument() { _application = new Excel.ApplicationClass(); _workBook = _application.Workbooks.Add(_missingObj); _workSheet = (Excel.Worksheet)_workBook.Worksheets.get_Item(1); } public ExcelDocument(string pathToTemplate) { object pathToTemplateObj = pathToTemplate; _application = new Excel.ApplicationClass(); _workBook = _application.Workbooks.Add(pathToTemplateObj); _workSheet = (Excel.Worksheet)_workBook.Worksheets.get_Item(1); } // ВИДИМОСТЬ ДОКУМЕНТА public bool Visible { get { return _application.Visible; } set { _application.Visible = value; } } // ВСТАВКА ЗНАЧЕНИЯ В ЯЧЕЙКУ public void SetCellValue(string cellValue, int rowIndex, int columnIndex) { _workSheet.Cells[rowIndex, columnIndex] = cellValue; } public void Close() { _workBook.Close(false, _missingObj, _missingObj); _application.Quit(); System.Runtime.InteropServices.Marshal. ReleaseComObject(_application); _application = null; _workBook = null; _workSheet = null; System.GC.Collect(); } } }
У класса есть одна особенность - он работает с неуправляемым ресурсом - приложением Excel. То есть мы создаем невидимый процесс Excel, заполняем его данными из шаблона и программ и только после этого отображаем на экран. В случае ошибок никакой сборщик мусора не приберет за нами грязь, так что закрытие документа в случае ошибки придется делать в ручную. Собственноручное изменение деструктора тоже работает весьма своеобразно с COM-интерфейсом.
В простейшем случае получим код вида
ExcelDocument excelDoc = new ExcelDocument(Application.StartupPath + "\\" + "templateFileName.xlt"); int rowIndex = 1; try { // так и просится в отдельный метод foreach (DataRow currRow in someDataTable.Rows) { string valueCol1 = currRow["COLUMN1"].ToString(); string valueCol2 = currRow["COLUMN2"].ToString(); excelDoc.SetCellValue(valueCol1, rowIndex, 1); excelDoc.SetCellValue(valueCol2, rowIndex, 2); rowIndex++; } } catch(Exception error) { excelDoc.Close(); // обрабатываем саму ошибку } excelDoc.Visible = true;
Само собой ничто не мешает в дальнейшем расширить этот класс методами для работы с оформлением, вроде
public void SetColumnWidth(int columnIndex, int colWidth) { ((Excel.Range)_workSheet.Columns[columnIndex, Type.Missing]).EntireColumn.ColumnWidth = colWidth; }
Такой метод вряд ли подойдет для больших и сложных корпоративных систем, разрабатываемых высокооплачиваемыми профессионалами, но может спасти программиста-новичка в случае требования начальства "сделать ВЧЕРА вывод отчета в excel в соответствии с требования клиента по оформлению".
Excel- Вставка строк и изменение границ ячеек в Excel Interop из C#
- Excel 2010, Windows 7, два монитора и "ошибка при направлении команды приложению"
- Как прочитать db3/dbf/dbase из C#
- Работа с Excel из C# через COM Interop, часть 3, чтение данных
- Как полностью закрыть Excel, вызванный из C# Interop
- Работа с Excel из C# через COM Interop, часть 1, открываем документ и выводим данные
Не надо сгущать краски. Работать с Excel также просто (или сложно), как и с чем-то другим. Разные варианты загрузки данных из Excel с учетом преобразования данных требуют разное операционное время, поэтому нужно выбирать нужный для конкретного случая.
Я, наверно, буду голосом большинства когда спрошу. ГДЕ ССЫЛКА НА ВТОРУЮ ЧАСТЬ ?
Необходимо поддерживать все версии Office, начиная с 97, то есть вывод в новые xml-форматы Office 2007 и выше невозможен
И где же решение данной части задачи?
Официальное трудоустройство, работа через интернет.
Официальная работа на дому
Bobs or vagana whatever will it be?