Foxby — это библиотека для работы с Word документами в формате OpenXml. Предназначена для генерации документов по шаблону и внесения изменений в существующие документы. С помощью неё вы сможете отказаться от работы с COM+ или редактирования OpenXML-дерева через OpenXML SDK и перейти к механизму построения структуры документа из метаэлементов в декларативном виде.
В классе решаемых задач: создание параграфов, создание и заполнение таблиц, списков, работа с изображениями, форматирование и т.п. Фактически библиотека является оберткой над OpenXML SDK с API в виде Fluent-интерфейса.
Преимущества использования
Мы сами используем эту библиотеку уже в двух проектах. Первая версия была написана Тимуром и зарождалась, как часть подсистемы проекта по работе с Word-документами, но в дальнейшем была вынесена в самостоятельный проект.
Можно выделить следующие преимущества:
- На сервере, где работает ваше приложение, не требуется установка Microsoft Office
- Нет проблемы с зависшими процессами Word
- Работает гораздо быстрее, чем COM+
- Создание и изменение документов не требует записи на жесткий диск, всё происходит в оперативной памяти
- Удобный Fluent API для работы с объектами Word
- Возможность построения своего метаязыка разметки документа
Установка
Последнюю версию можно установить через NuGet:
Исходный код и лицензия
Исходный код написан на .NET 4.0/C# и выложен на Google Code:fluent-openxml компанией IndyCode под лицензией LGPL.
Примеры использования
Ниже приведены примеры, с помощью которых можно будет начать работать с библиотекой.
Пример №1 - Hello Word!
private static void Main() { using (var docxDocument = new DocxDocument(SimpleTemplate.EmptyWordFile)) { var builder = new DocxDocumentBuilder(docxDocument); builder .Tag(SimpleTemplate.ContentTagName, x => x.Center.Paragraph(z => z.Bold.Text("Hello Word!"))); File.WriteAllBytes(string.Format(@"D:\Word.docx"), docxDocument.ToArray()); } }
SimpleTemplate.EmptyWordFile это шаблон, который встроен в саму библиотеку. В шаблоне ничего нет, кроме тэгов для верхнего колонтитула, контента и нижнего колонтитула. Этот шаблон отлично подойдет для тестовых целей и генерации простых документов.
Вместо File.WriteAllBytes, который записывает файл на диск, массив байт можно передавать как FileResult, чтобы пользователь сразу получал сгенерированный документ.
Иерархия вложения должна помочь понять идеологию работы с библиотекой:
Пример №2 - Создадим договор
Очень часто требуется создать договор или счет-фактуру. Этот пример показывает типичный сценарий создания документа. Для простоты переменные берутся не из базы данных, а определяются переменными.
private static void Main() { string customerName = "Иванов И.В."; string orderNumber = "4"; string itemName1 = "Табуретка"; string itemSumm1 = "5 000"; string itemName2 = "Кран погрузочный"; string itemSumm2 = "6 342"; string summ = "11 342"; using (var docxDocument = new DocxDocument(SimpleTemplate.EmptyWordFile)) { var builder = new DocxDocumentBuilder(docxDocument); builder .Tag(SimpleTemplate.ContentTagName, x => x .Center.Paragraph(z => z.Bold.Text(string.Format("Договор №{0}", orderNumber))) .Right.Paragraph(string.Format("от {0} г.", DateTime.Now.ToString("dd MMMM yyyy"))) .Left.Paragraph(string.Format("Я, {0}, покупаю:", customerName)) .Table(t => t.Column("Товар", 70).Column("Цена, руб.", 30), r => r.Row(itemName1, itemSumm1) .Row(itemName2, itemSumm2) .Row(w => w.Right.Bold.Text("Итого:"), w => w.Center.Bold.Underlined.Text(summ)) )); File.WriteAllBytes(string.Format(@"D:\Word.docx"), docxDocument.ToArray()); } }
Пример №3 - Изменяем созданный документ
Сценарий:
- Создаем документ за подписью Иванова К.И.
- Отправляем документ на согласование
- Электронный документ возвращают и говорят, что подписывать должен Петров А.И.
- Меняем подписывающего в документе
private static void Main() { using (var docxDocument = new DocxDocument(SimpleTemplate.EmptyWordFile)) { var builder = new DocxDocumentBuilder(docxDocument); builder .Tag(SimpleTemplate.ContentTagName, x => x.Left.Paragraph("Договор на оказание услуг...") .Right.Paragraph(z => z.Placeholder("SIGNER_NAME", "Иванов К.И."))); File.WriteAllBytes(string.Format(@"D:\Word.docx"), docxDocument.ToArray()); } using (var docxDocument = new DocxDocument(File.ReadAllBytes(@"D:\Word.docx"))) { var builder = new DocxDocumentBuilder(docxDocument); builder .Placeholder("SIGNER_NAME", x => x.Text("Петров А.И.")); File.WriteAllBytes(string.Format(@"D:\Word.docx"), docxDocument.ToArray()); } }
Пример №4 - Создаем документ "с нуля"
private static void Main() { using (var docxDocument = new DocxDocument()) { docxDocument.AddOpenCloseTag("CONTENT"); var builder = new DocxDocumentBuilder(docxDocument); builder .Tag("CONTENT", x => x.Left.Paragraph("Договор на оказание услуг...")); File.WriteAllBytes(string.Format(@"D:\Word.docx"), docxDocument.ToArray()); } }
Пример №5 - Модульные тесты
К библиотеке написано довольно много модульных тестов, с помощью которых вы сможете еще лучше понять сценарии работы системы. Скачать исходный код с тестами можно с Google Code:fluent-openxml.
Плюшки
Александр Зайцев поразвлекался и сделал довольно интересную реализацию:
builder .Tag("CONTENT", x => x.Paragraph("Жирный ".Bold() + "Курсив ".Italic() + "Подчеркнутый ".Underlined() + "Нормальный"));
Такой способ можно использовать для текста, как альтернативу свойства Bold.
Обратная связь
Эта библиотека может быть лучше и работать различными специфическими ситуациями, если вы дадите нам обратную связь.
Ссылки
Видео и слайды с конференции DotNetConf: Анонс OpenSource библиотеки для создания и изменения документов в формате OpenXml через Fluent-интерфейс
Очень интересная библиотека. Возьму на заметку.
ОтветитьУдалитьПрактически все преимущества принадлежат OpenXML, а сюда просто скопированы?
Почему не Open XML SDK (http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=5124)
ОтветитьУдалить> Почему не Open XML SDK?
ОтветитьУдалитьНаверное из-за её "мощности" :) Сам написал небольшую обертку над этой библиотекой, чтобы было проще работать. А у этих ребят свой подход к упрощению. Глянем!
@Мурадов Мурад @orsol
ОтветитьУдалитьРаботать с OpenXML SDK напрямую очень сложно. Попробуйте сделать примеры из статьи на OpenXML SDK и сравните по читаемости кода и сложности реализации.
@ShurikEv
ОтветитьУдалитьМожно ваше решение где-нибудь глянуть?
@Александр
ОтветитьУдалитьК сожалению, его нет в открытом доступе. Да и оно скорее всего "часть подсистемы проекта по работе с Word-документами", точнее с документами Office и решает только узкий спектр задач, которого вполне достаточно. Конечно хочется вывести библиотеку на новый уровень, да хвастаться пока не чем :)
@ShurikEv
ОтветитьУдалитьЕсли выложите, то напишите мне пожалуйста, будет интересно посмотреть :)
А что делать, если требуется сохранение файлов в формат .doc (бинарный формат) ? есть ли способ не использовать COM ?
ОтветитьУдалить@Дмитрий
ОтветитьУдалитьК сожалению, нет. Возможно есть платные библиотеки, которые разобрали внутренний формат DOC-файлов, но я таких не видел.
Спасибо за статью! Очень полезная вещь, особо радует работа с таблицами
ОтветитьУдалитьCOM+?
ОтветитьУдалить@Nikita Govorov
ОтветитьУдалить> COM+?
Это кому вопрос? :)
@Александр
ОтветитьУдалитьВам.
@Nikita Govorov
ОтветитьУдалитьРазверните, пожалуйста, вопрос.
Я боюсь, что технология COM+ мало имеет отношения к генерации документов.
ОтветитьУдалить@Nikita Govorov
ОтветитьУдалитьА вы как работаете с DOC-файлами?
COM?
ОтветитьУдалить@Nikita Govorov
ОтветитьУдалитьНу да. А какие еще есть варианты?
Вы очень немногословны :)
Я хотел намекнуть, о то что COM+ это не то что вы имели ввиду. :)
ОтветитьУдалить@Nikita Govorov
ОтветитьУдалитьА в чем ошибка? Видимо я не в теме.
http://ru.wikipedia.org/wiki/COM%2B#COM.2B
ОтветитьУдалить@Дмитрий
ОтветитьУдалитьhttp://bytescout.com/products/developer/documentsdk/index.html
@Nikita Govorov
ОтветитьУдалитьЯ правильно понял, что Microsoft.Office.Interop это COM объекты, а не COM+?
Bingo.
ОтветитьУдалить@Nikita Govorov
ОтветитьУдалитьВы бы сэкономили 12 комментариев, если написали это первым предложением.
Удалите их, пожалуйста.
ОтветитьУдалить@Nikita Govorov
ОтветитьУдалитьНе охота :)
Два вопроса:
ОтветитьУдалить1) Что вы будете делать, если понадобится генерировать файлы именно в старом, бинарном формате (.doc) ?
2) Не реализовывали ли вы подобный функционал для Excel ? если да, то хочется посмотреть исходники
1) Формат .doc признан самим Microsoft устаревшим, он неудобен, не является открытым четким стандартом и кроме того, даже в таком старичке как MS Word 2003 проблема просмотра и редактирования документов в формате .docx решается установкой SP3 и т.н. Compatibility Pack, поэтому задача генерации документов в формате .doc в принципе не стоит.
ОтветитьУдалить2) В текущей версии Foxby реализована поддержка Excel, но при этом она весьма ограничена, т.к. продиктована возникшей перед нами необходимостью. Соответственно если у вас есть feature request по конкретным вопросам работы с .xlsx-файлами, то вы можете написать нам в github'овский раздел issues: https://github.com/IndyCode/Foxby/issues
в болге оч нехватает кнопчки "твитнуть статейку" ((
ОтветитьУдалитьсори, нашел.. очень спратанная...
ОтветитьУдалитьДобавил большие кнопки для расшаривания. Спасибо!
ОтветитьУдалитьПрикрутите ещё ODF, здорово будет :)
ОтветитьУдалить