- PVSM.RU - https://www.pvsm.ru -
В разговорах об Office Add-ins (надстройки Office) часто упоминается «продуктивность». Это логично, ведь главная цель разработчиков – повышение продуктивности в работе конечных пользователей. Но продуктивность важна и для самих разработчиков. Эта статья о продуктивности в разработке. Речь пойдёт о новом JavaScript API для Office [1]и о том, какие инструменты мы применяем для создания новых решений.
В декабре 2015 года меня пригласили поучаствовать в рабочей сессии по Office 365 [2] как консультанта по созданию надстроек Office. На мероприятии собрались команды, интересующиеся продвижением своих продуктов в Office Store. Цель – за два дня погрузиться в тонкости JavaScript API для Office, сформировать концепты будущих решений и реализовать прототипы.
На второй день в промежутках между ответами на вопросы участников у меня оставалось свободное время. Это позволило начать работу над новой идеей. В VSTO [3]-версии расширения XLTools для Excel есть популярная среди пользователей функция – календарь для ввода дат [4]. Мне давно хотелось реализовать её и для Office Store, но руки не доходили. А т.к. темой рабочей сессии была продуктивность, идея вписывалась как нельзя лучше, поскольку календарь в разы увеличивает скорость работы с документами, в которых требуется ввод дат.
Для примера возьмем стандартный шаблон для Excel из доступных онлайн – «Список дел»:
Чтобы создать такой документ, откройте в Excel меню Файл > Создать > Ввести в поле «Поиск шаблонов в сети» название шаблона «Список дел».
На экране выше видно, что в таблице присутствуют два поля с типом «Дата»: «Дата начала» и «Дата выполнения». Каждый, кому приходилось работать с датами в Excel, знает, что ввод дат сопряжён с некоторыми сложностями. Вот если бы можно было просто выбирать дату из календаря!
Так и родилась идея. Поразмыслив, я вывел следующий список требований:
Я использую Visual Studio. Подходят и другие инструменты, такие как Napa [5] или другой редактора кода, но с точки зрения производительности и удобства, Visual Studio [6] – лучший вариант, т.к. позволяет за минуту создать готовый к запуску и отладке проект надстройки Office. В Napa и других сторонних редакторах отладка Office Add-ins [7]пока не представляется возможной.
Открываем Visual Studio > File > New > Project > Templates > Office/SharePoint > Apps > Выбираем тип приложения «App for Office». Отмечу, что на момент написания статьи Microsoft заменила название «App» на «Add-in». Наверняка в будущем поменяется и название проекта.
Далее задаем тип приложения. Т.к. надстройка встраиваться в тело документа, выбираем тип «Content» – идеально подходит для решения поставленной задачи. Отличие типа Task pane от Content наглядно демонстрирует нижеприведённый рисунок.
На последнем шаге нам предлагается выбрать шаблон проекта (Basic App – базовый, Document Visualization App – посложнее) и набор поддерживаемых офисных программ: Access, Excel, PowerPoint. Выбираем Basic App и поддержку Excel. Нажимаем Finish. Проект создан и готов к запуску (F5) и отладке.
Давайте ещё раз пройдёмся по требованиям и подумаем, как реализовать каждое из них. Начать стоит с последнего – «встраивание». Тут кроется отличительная особенность нового типа Office Add-ins. По сравнению с традиционными VSTO [8] они не требуют установки дополнительных компонент. Т.е. если создать Excel-документ, добавить в него надстройку из Office Store и отправить документ коллегам, им не потребуется ничего дополнительно устанавливать для работы надстройки. Это ровно то, чего так не хватало пользователям VSTO [8]-версии календаря XLTools.
Календарь не предусматривает сложного UI. В интернете есть море свободно распространяемых JavaScript-библиотек, реализующих функционал отображения календаря. Я выбрал библиотеку Pikaday [9], удовлетворяющую остальным нашим требованиям на 100%. Библиотека позволяет:
Конечно, зачастую мы решаем более сложные задачи, требующие уникального дизайна. Здесь стоит обратить внимание на вышедший недавно фреймворк Office UI Fabric, предоставляющий набор CSS-классов и UI-компонентов, заранее стилизованных под офисные приложения. Стили и компоненты адаптированы для работы под все платформы, поддерживаемые Office: Mobile Apps, Web, Desktop. Использование Office UI Fabric [10] в разы упрощает проектирование и разработку UI. Это как Bootstrap, только специально для разработчиков Office Add-ins.
На UI ушло девять строк кода. Подключение CSS и JavaScript в файле Home.html:
<link href="pikaday.css" rel="stylesheet" type="text/css" />
<script src="pikaday.js" type="text/javascript"></script>
Инициализация календаря в методе Office.initialize в файле Home.js:
var calOptions = {
showWeekNumber: true, // календарь должен отображать номера недель
defaultDate: new Date() // по умолчанию выделяем в календаре текущую дату
};
var placeholder = $("body"); // в качестве «родительского элемента» берем body
var picker = new Pikaday(calOptions); // инициализируем объект календаря
placeholder.append(picker.el); // добавляем элемент календаря в body
Pikaday позволяет «навесить» обработчик на событие изменения даты в календаре. Получив дату, мы проставляем её в текущую выделенную ячейку, используя метод из Office API — setSelectedDataAsync:
calOptions.onSelect = function (date) { // задаем обработчик события изменения даты
date = getLocaleShortDateString(date); // преобразуем объект Date в строку
Office.context.document.setSelectedDataAsync(date, // передаем дату в виде строки
{
coercionType: Office.CoercionType.Text // тип значения – «Текст»
},
function (asyncResult) { // обработчик статуса изменения значения ячейки
if (asyncResult.status == "failed") {
app.showNotification("Failed", asyncResult.error.message, 'error');
}
}
);
};
В примере для работы с датой используется функция getLocaleShortDateString. Она необходима, т.к. Excel воспринимает даты как числа и отображает их в виде даты, только если у ячейки задан соответствующий формат. Проблема кроется в том, что число в ячейку мы записать можем, а вот изменить формат ячейки текущее JavaScript API [1] не позволяет. К счастью, нашёлся обходной способ. Чтобы получить в ячейке именно дату, нужно проставить её в виде текста, соблюдая выбранный у пользователя формат региона (локали). Функция getLocaleShortDateString как раз используется для преобразования объекта Date в текстовый локализованный формат. Узнать, какой именно региональный стандарт выбран у пользователя, можно через свойство объекта context – Office.context.displayLanguage.
function getLocaleShortDateString(d) {
var f = getLocaleDateString(),
y = d.getFullYear(),
m = d.getMonth() + 1,
d = d.getDate();
function z(s) {
s = '' + s; return s.length > 1 ? s : '0' + s;
}
f = f.replace(/yyyy/, y); f = f.replace(/yy/, String(y).substr(2));
f = f.replace(/MM/, z(m)); f = f.replace(/M/, m);
f = f.replace(/dd/, z(d)); f = f.replace(/d/, d);
return f;
}
function getLocaleDateString() {
var formats = {
"en-US": "M/d/yyyy",
"ru-RU": "dd.MM.yyyy",
... // еще более 200 форматов
};
return formats[Office.context.displayLanguage] || 'dd/MM/yyyy';
}
JavaScript API для Excel позволяет обрабатывать событие изменения выделенной области ячеек. Используем это, чтобы отследить изменение пользователем выделенной ячейки:
// обработчик изменения выделения
Office.context.document.addHandlerAsync(Office.EventType.DocumentSelectionChanged,
function (eventArgs) {
// запрашиваем значение выделенной ячейки
Office.context.document.getSelectedDataAsync(Office.CoercionType.Text,
{
// говорим, что нам необходимо фактическое значение (число)
valueFormat: Office.ValueFormat.Unformatted
}, function (ufResult) {
if (ufResult.status != "failed") {
var value = ufResult.value;
// если не число - ничего не делаем
if (isInt(value) && value > 0)
{
// переводим число в дату
var date = getJsDateFromExcel(value);
// работаем только с датами +-50 лет от текущей даты
if (new String(date) != "InvalidDate" &&
date.getYear() > new Date().getYear() - 50 &&
date.getYear() < new Date().getYear() + 50)
{
// подсвечиваем значение в календаре
picker.setDate(date, true);
}
}
}
});
});
«Поймав» момент выделения новой ячейки пользователем, проверяем, является ли выбранное значение датой. Чтобы получить значение из выделенной ячейки, используем функцию Office.context.document.getSelectedDataAsync, говорим ей, что вернуть нужно не отформатированное значение. В случае с датой, значением будет целое число (даты со временем не рассматриваем). Далее идут проверки на соответствие значения дате. Определить на 100%, является ли значение в ячейке датой, не представляется возможным. Так, если пользователь выберет ячейку с числом, соответствующим числовому представлению даты – алгоритм посчитает, что это и есть дата. Чтобы минимизировать количество ложных срабатываний на числа, задаём ограничение: проверка даты на +-50 лет от текущего года. Если значение подходит по всем критериям, используем для подсветки метод setDate календаря Pikaday.
Сейчас Office Store [11] поддерживает 40 языков. В примерах выше уже показано, как локализовать значение даты. Помимо даты, локализации требует также UI. В случае с календарем Pikaday всё просто:
var myLanguage = Office.context.displayLanguage.split("-")[0];
if (myLanguage == "ru") {
calOptions.firstDay = 1;
calOptions.i18n = {
previousMonth: 'Предыдущий месяц',
nextMonth: 'Следующий месяц',
months: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь',
'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'],
weekdays: ['Воскресенье', 'Понедельник', 'Вторник', 'Среда',
'Четверг', 'Пятница', 'Суббота'],
weekdaysShort: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб']
};
}
Для начала поддерживаем 2 языка: русский и английский. Pikaday по умолчанию англоязычный. Для перевода на русский проверяем текущий регион пользователя и подставляем новые значения для текстовых надписей, если язык интерфейса русский.
Меньше чем за один день мне удалось создать Office Add-in, готовый к публикации в Office Store [12]. Такая скорость возможна благодаря опыту и готовым решениям, накопленным годами в веб-разработке. Плюсом является простота JavaScript API для Office, так же как и наличие готового фреймворка Office UI Fabric [10] для построения UI.
Из сложностей можно отметить, что отладка надстроек на разных платформах – неординарная задача. Уже после отправки приложения на проверку в Office Store [12] мне пришлось побороться с отладкой, т.к. первая версия надстройки не прошла проверку из-за ошибок в работе на iPad и в Web-е. С проблемами отладки я справился и напишу об этом отдельную статью.
Недавно надстройка XLTools.net Calendar успешно прошла проверку и теперь доступна для скачивания в Office Store [13]. За две недели мы набрали 1832 скачивания, получили 1 отзыв и 4 максимальных оценки в Office Store. Много положительных отзывов и запросов на доработку функциональности пришло по email. В ближайшее время планируем выпустим усовершенствованный календарь с новыми опциями. Следите за обновлениями!
Петр Ляпин -Технический директор ООО «ВейвПоинт»
Более 10 лет опыта внедрения проектов по автоматизации
бизнес-процессов. Работал со множеством российских и
зарубежных компаний. Основатель проекта XLTools.net.
Автор: Microsoft
Источник [14]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/115621
Ссылки в тексте:
[1] JavaScript API для Office : https://dev.outlook.com/reference/add-ins/index.html
[2] Office 365: https://habrahabr.ru/company/microsoft/blog/242483
[3] VSTO: https://habrahabr.ru/company/microsoft/blog/270763/
[4] календарь для ввода дат: https://xltools.net/ru/excel-popup-calendar/
[5] Napa: https://www.napacloudapp.com/Getting-Started
[6] Visual Studio: https://www.visualstudio.com/en-us/products/vs-2015-product-editions.aspx
[7] Office Add-ins : http://dev.office.com/getting-started/addins
[8] VSTO: https://habrahabr.ru/company/microsoft/blog/270763
[9] Pikaday: https://github.com/dbushell/Pikaday
[10] Office UI Fabric: http://dev.office.com/fabric
[11] Office Store: https://msdn.microsoft.com/en-us/library/office/jj220037.aspx
[12] Office Store: https://store.office.com/
[13] доступна для скачивания в Office Store: https://store.office.com/xltools-net-calendar-WA104379895.aspx
[14] Источник: https://habrahabr.ru/post/279735/
Нажмите здесь для печати.