Задача: вывести данные в таблицу 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?