Привет.
Вопрос про смарт-теги в MS Office и их программирование на .NET.
Такая задача. Из отдела аналитики приходят документы: словарь терминов и набор техзаданий. Необходимо в наборе техзаданий автоматически, лучше с учетом падежей слов, выделять термины, добавляя действия по просмотрю соответствующего термину раздела словаря по нажатию на тег.
Расскажите пожалуйста, кто занимался подобной задачей, как это лучше реализовать. Может быть даже не пользоваться смарт-тегами, если есть более подходящий для этого инструмент в MS Office.
В организации используется MS Office 2010.
Здравствуйте, DmitryShm, Вы писали:
DS>Вопрос про смарт-теги в MS Office и их программирование на .NET.
DS>В организации используется MS Office 2010.
Я не занимался подобными задачами и пока с ходу не могу предложить хорошего решения. То, что я читал про Smart tags говорит, что это как раз механизм для решения подобных вашей задаче, однако
здесь пишут, что
Smart tags are deprecated in Excel 2010 and Word 2010. Although you can still use the related APIs in projects for Excel 2010 and Word 2010, these applications do not automatically recognize terms, and recognized terms are no longer underlined. Users must trigger recognition and view custom actions associated with text by right-clicking the text and clicking the Additional Actions on the context menu.
В общем, я бы начал искать какое-то иное решение.
Дмитрий, еще раз добрый день
Я поискал возможные альтернативы для вашей задачи и у меня получилось следующее (вам уж самому решать что приемлемо, а что нет):
1. Самым простым и надежным мне кажется следующий вариант: добавить словарь в документ ТЗ (можно не все статьи, а только те термины, которые используются в документе). А из текста сделать гиперссылки для перехода к этим статьям.
Почему мне этот вариант нравится больше всего:
Используются базовые возможности Office, а значит не нужно иметь расширение на каждой машине — меньше проблем с деплоем и обновлением.
Документ формируется единожды, а значит можно всю подготовку сделать на сервере, используфя, например Open ХML SDK (и не привлекать Word API)
2. Если вариант с переходом по ссылке почем-то не устраивает, а хочется поведения именно как в случае со smart tags, то могу предложить только вариант с использованием
Word Host Controls — они позволяют создать контрол, привязанный к элементу текста и, например, вызывать событие при щелчке на этот элемент/область текста.
К сожалению, из тех трех типов Host Controls, которые перечисляются в статье, можно спокойно использовать только
Content Controls и
Bookmark Control. С XMLNode(s) есть проблема при использовании его на территории USA, т.к. это ничто иное как часть мханизма Custom XML, который был
запрещен судом по иску от i4i, но вроде как запрет каснулся только USA...
В общем, при использовании одного из механизмов, вы можете поступить одним из следующих способов:
Заранее размечаете документ (выделяете термины в тексте) с помощью bookmarks/content controls/custom xml (как-то явно выделяя среди них нужные вам — например, с помощью специальной системы именования). Затем при открытии документа срабатывает ваш Add-in, который находит все ваши элементы и создаете для них контролы, в которых подписываетесь на событие щелчка (или аналог).
Аналогично предыдущему, но поиск терминов и создание контролов (а значит и разметки в тексте) делается "на лету" при открытии документа. Правда, при таком поведении будет меняться содержимое документа и пользователя при закрытии будут спрашивать о необходимости сохранить документ.
Из этих 2-х мне больше всего нравится первый. Вот простейший пример add-in, который при открытии любого документа "вешает" событие двойного клика на абсолютно все bookmarks, которые есть в документе (есть и просто одиночный клик) и показывает message box при таком клике.
using Microsoft.Office.Tools.Word;
using System.Windows.Forms;
using Word = Microsoft.Office.Interop.Word;
namespace BookmarkTestAddin
{
public partial class ThisAddIn
{
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
this.Application.DocumentOpen += Application_DocumentOpen;
}
void Application_DocumentOpen(Word.Document doc)
{
Document vstoDocument = Globals.Factory.GetVstoObject(doc);
foreach (Word.Bookmark nativeBookmark in doc.Bookmarks)
{
var bookmark = vstoDocument.Controls.AddBookmark(nativeBookmark, nativeBookmark.Name);
bookmark.BeforeDoubleClick += bookmark_BeforeDoubleClick;
}
}
void bookmark_BeforeDoubleClick(object sender, ClickEventArgs e)
{
MessageBox.Show("!!!!");
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
#region VSTO generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
#endregion
}
}
3. Совместить первые два: добавить словарь и сделать гиперссылки, которые будут отрабатывать при отсутсвии Add-in, а если на машине Add-in установлен, будет показаваться термин во всплывающем окне.
К сожалению, все перечисленные мною варианты предполагают статический анализ документа, что радикально отличает их от smart tags (которые, как я помню, работали в фоне, и позволяли парсить и размечать текст "на лету").
Что касается получения терминов с учетом морфологии, то к сожалению стандартных средств для этого я не знаю. Конечно, в Windows Search есть интерфейс
IStemmer, но похоже, что реализации его для разных языков не найти.
Поэтому, единственным вариантом видится использование сторонних библиотек, благо морфологический анализ — вещь достаточно проработанная. Можно посмотреть имеюшие инструменты с поддержкой русского/английского языков на
NLPub.
Правда конкретно с поддержкой .Net я там отыскал только вот
эту, которая не бесплатна для коммерческого использования (что-то порядка 3000$), но наверняка можно будет подключить и другие.
Здравствуйте, Михаил Романов, Вы писали:
МР>1. Самым простым и надежным мне кажется следующий вариант: добавить словарь в документ ТЗ (можно не все статьи, а только те термины, которые используются в документе). А из текста сделать гиперссылки для перехода к этим статьям.
МР>Почему мне этот вариант нравится больше всего:
МР>
МР>Используются базовые возможности Office, а значит не нужно иметь расширение на каждой машине — меньше проблем с деплоем и обновлением.
МР>Документ формируется единожды, а значит можно всю подготовку сделать на сервере, используфя, например Open ХML SDK (и не привлекать Word API)
МР>
Идея в том, чтобы словарь терминов был отдельно периодически обновляемым документом. Если мы раскопируем словарь по техзаданиям, то поддерживать все это в целостности будет проблематично.
Здравствуйте, DmitryShm, Вы писали:
DS>Идея в том, чтобы словарь терминов был отдельно периодически обновляемым документом. Если мы раскопируем словарь по техзаданиям, то поддерживать все это в целостности будет проблематично.
Понятно.
В принципе, при централизованном хранении (shared folders, SharePoint sites или какая-то ECM) проблема обновления должна практически нивелироваться), но на сколько реально такое хранение обеспечить в вашем случае?
Еще вопрос — а реально ли необходимо в самих ТЗ поддерживать именно последнюю актуальную версию словаря? Может быть достаточно будет версии, актуальной на момент выпуска документа?
Собственно, почему я так настаиваюименно на централизованном обновлении документов (не обязательно серверном и автоматическом — но это самы предпочтительный вариант)... Как я понимаю smart tags работали в фоне, возможно инкрементально (т.е. только по той части текста, которая отображалась пользователю), а самое главное — разметка документа не изменялась (а значит пользователю не выдавалось каждый раз сообщение о необходимости сохранить измененный документ, хотя он его и не менял).
Как получить схожее поведение на текущих оставшихся воможностях я слабо представляю:
Чтобы иметь актуальную версию нужно сканировать документ при открытии или в фоне, а в идеале еще и при правке документа. Первое будет тормозить открытие (на сколько существенно, правда, не скажу), второе чревато вылетами (по крайней мере своего механизма работы add-in в фоне я не знаю, а опыт работы с API Office из многопоточных приложений говорит, что это не работает).
Все API, которое манипулирует текстом (например, выделяет подчеркиванием), о котором я знаю, меняет разметку документа. Значит, при каждом открытии пользователям будут сообщать, что они поменяли документ, хотя они этого не делали (ну или как-то хитро эти изменения перед сохранением откатывать) — имхо, не самое логичное поведение.
Впрочем, может и есть другие варианты, о которых просто я не в курсе.