Решение без кода: вывод количества дней с момента последнего изменения элемента списка

Джастин Joyce (Justin Joyce), LANtek

Примечание

Эта статья входит в коллекцию записей, опубликованных за четыре года в блоге Get the Point для конечных пользователей SharePoint.

Обзор: создание собственных отчетов по срокам без программирования

Одной из часто запрашиваемых функций сайта SharePoint является отчет по срокам для задач и элементов списков. Другими словами, пользователям интересно знать, сколько дней и месяцев прошло с момента последнего изменения элемента списка.

На первый взгляд, этот запрос кажется очень простым. У нас есть даты создания и изменения элементов, а также возможность сохранять настраиваемые даты при определенных изменениях элементов с помощью приемников событий. Также существуют вычисляемые столбцы, которые могут включать формулы в стиле Excel для работы с информацией. На первый взгляд, все очень просто. Нужно выбрать поле даты, создать вычисляемый столбец, а затем ввести примерно такую формулу, как [DateField] – [Сегодня]. К сожалению, это не сработает. Любой, кто пытался решить эту "простую" задачу, знает, что попытка использовать что-то вроде [Сегодня] в вычисляемом столбце вызывает проблемы. Если попытаться вставить [Сегодня] в поле формулы вычисляемого столбца, появится сообщение об ошибке примерно такого содержания:

Сообщение об ошибке

Почему это происходит? Это связано с тем, как вычисляются столбцы .

Возьмем для примера простую формулу:

= ЕСЛИ( [Столбец1]<=[Столбец2], "ОК", "Не ОК")

Она означает, что если значение "Столбец1" не больше значения "Столбец2", нужно вывести "ОК", а в противном случае — "Неверно". Это типичная простая формула для вычисляемого столбца, которая предполагает следующее об элементе списка, содержащем эти столбцы: значения "Столбец1" и "Столбец2" никогда не смогут изменяться без обновления элемента списка.

Верно, вычисляемые столбцы пересчитываются только при обновлении (или создании) списка, так как предполагается, что вычисляемые сведения содержатся в самом элементе. Это создает проблему, когда вы пытаетесь использовать что-то, что изменяется независимо от полей элемента, например текущую дату.

Я не был на совещании, где они решили, что вычисляемые столбцы будут работать именно так, однако, если бы мне пришлось сделать обоснованное предположение, я бы предположил, что они работают таким образом для производительности. Представьте, что у вас есть список из нескольких тысяч элементов, каждый из которых содержит вычисляемый столбец, нуждающийся в «живом» обновлении. Это означает, что некий алгоритм, возможно, задание таймера, должен был бы регулярно выполнять итерацию по всем элементам с вычисляемыми столбцами и обновлять их значения. Это бы значительно ухудшило производительность, так как при крупных развертываниях это задание бы постоянно выполнялось и вносило изменения. Это всего лишь мое предположение, но это имеет довольно много смысла, если подумать.

В Интернете можно найти похожие решения, которые позволяют обмануть SharePoint и заставить его принять значение "Сегодня", создав столбец с именем "Сегодня, "добавив его в формулу, а затем удалив его. Это решение сработает, но не забывайте, что я говорил о том, когда обновляются вычисляемые столбцы. Это значение будет изменяться только при обновлении элемента и поэтому скоро станет неверным, особенно в случае вычисления дня.

Я видел, как другие используют умный JavaScript для записи значений на страницу. Это также сработает, но я категорически против использования клиентских сценариев, когда этого можно избежать.

Реализация:

Так что же делать? Вычисляемые столбцы не обсуждаются для так называемых "изменчивых" функций, таких как Today. Возможно, мы могли бы разработать какой-то пользовательский код, чтобы позаботиться об этом за нас, например, вычисляемый столбец, задание таймера или запланированный процесс, чтобы обновлять каждый элемент, который нуждается в этом расчете. Это возвращает нас к проблеме производительности, о которой я упоминал в последнем абзаце, и, кроме того, это хрупкое решение, которое будет очень специфичным для рассматриваемого сайта/списка/столбца. Помимо этих двух проблем, вам также нужно будет найти занудного парня, такого как я, который знает, как программировать, и убедить его разработать это решение для вас. Но есть более простой способ!

Если у вас есть права на создание полей и редактирование страниц на сайте, а также немного знаний о XSLT и создании представлений, вы можете создать шаблон XSL, добавить его в представление списка, и он будет вычислять значение при каждом запросе страницы. Этот сценарий устраняет нашу проблему с производительностью и не требует разработки и развертывания пользовательского кода с помощью решения.

Разве это не идеал? Так что же нужно сделать?

  1. Создайте или выберите поле, которое будет являться источником. Оно должно иметь тип даты.
  2. Создайте поле, которое будет являться заполнителем для вычисляемого значения.
  3. Добавьте оба поля в тип контента, а затем добавьте тип контента в список.
  4. Создайте представление этого списка, содержащее исходный столбец и столбец-заполнитель.
  5. Добавьте шаблон XSL в библиотеку стилей.
  6. Установите свойство "XSL Link" для веб-части представления списка с помощью пользовательского интерфейса.
  7. Готово!

Рассмотрим пример использования и рассмотрим реализацию. Нашему клиенту было нужно представление основного списка, в котором показывалось, как долго определенный элемент списка имел текущее состояние. Список включал данные пользовательского типа контента сайта, который был создан на основе типа "Элемент" и добавлен в список. Уже был установлен приемник событий, который фиксирует каждое изменение поля состояния в элементе списка и сохраняет эту дату в столбце с именем "Дата изменения состояния". Такие настройки не являются обязательными, и способ можно применять для ЛЮБОГО поля даты (в нашей реализации уже были такие настройки, но вы можете попробовать обойтись без них). По минимуму вам потребуются исходное поле даты и поле-заполнитель для хранения результатов вычисления (подробнее об этом в следующем абзаце), которые были добавлены в список, хотя я рекомендую использовать столбцы сайта и типы контента сайта, на случай если вы захотите повторно использовать это решение для других объектов на сайте.

Таким образом, у нас есть исходная дата, которую мы можем использовать в наших расчетах с сегодняшней датой. Теперь мы можем создать пользовательский столбец сайта, который будет использоваться в качестве контейнера для вычисленного значения. В этом случае я решил использовать вычисляемый столбец, поскольку его нельзя будет изменить в формах создания или редактирования элементов, но его можно выбрать для отображения в представлениях, поскольку мы не хотим, чтобы пользователи вводили произвольные значения в этот столбец. Могут возникать вопросы о том, почему он не отображается в представлениях, и т. д.

Теперь, когда у нас есть столбец сайта, мы можем добавить его к типам контента, которые будут использоваться в списке. Затем нужно создать представление, которое мы позже настроим с помощью XSLT. Обязательно создайте стандартное представление, содержащее исходный столбец даты и новый вычисляемый столбец, который будет использоваться в качестве заполнителя для вычисленного значения.

Мы создали все, что нужно для настраиваемого отчета по срокам. Осталось только создать наш шаблон XSL, загрузить его в библиотеку стилей сайта и связать его с нашим представлением списка. Шаблон XSL, который мы будем использовать, будет содержать обычную разметку SharePoint для создания представления, а также нашу собственную разметку, переопределяющую ее некоторые части и вычисляющую нужное значение.

Надо отдать должное, шаблоны XSL для выполнения фактических вычислений, которые я использую для этого решения, были любезно предоставлены "swirch" на форумах MSDN:
http://social.msdn.microsoft.com/Forums/en-US/sharepointcustomization/thread/aeda905b-9bc6-40c4-bd22-21306c5cb0d2/

Загрузите таблицу стилей XSL (aging.zip), которую я собрал здесь:
https://OneDrive.live.com/?cid=c262e8e2d59a86d9&permissionsChanged=1&id=C262E8E2D59A86D9!104

Открыв его в своем любимом текстовом редакторе, вы увидите множество обычной разметки SharePoint XSL для отрисовки представлений, если вы продолжите прокручивать вниз до строки 357, вы увидите начало пользовательских шаблонов, которые я добавил в разметку, первым из которых является шаблон "DateDiff", за которым следуют "calculate-julian-day" и "FieldRef_printTableCell_EcbAllowed.Days_x0020_At_x0020_Status". Это три шаблона, которые позволяют создавать и отображать вычисления в наших представлениях. Если вы собираетесь использовать имена полей, отличные от тех, которые были указаны ранее в этой статье, необходимо просмотреть эти шаблоны и заменить ссылки на другие имена. Помните, что для этого нужно использовать ВНУТРЕННЕЕ имя поля, а не отображаемое имя.

Убедившись, что шаблон готов к использованию, перейдите в библиотеку стилей и загрузите его в папку «Таблицы стилей XSL», а затем скопируйте ссылку на файл. Это позволит при желании легко вносить в него изменения или добавлять его в различные части сайта.

Затем перейдите к списку и выберите представление, которое вы создали выше в этой статье. В меню «Действия сайта» выберите «Изменить страницу».

Команда

Найдите на странице веб-часть представления списка и откройте меню веб-части, щелкнув маленькую стрелку вниз в правом верхнем углу. В этом меню выберите "Изменить веб-часть".

Команда

В правой части окна браузера откроется меню веб-части.

Меню веб-части

Щелкните + для раздела "Разное" и найдите свойство "XSL Link".

Свойство ссылки XSL в меню веб-части

Вставьте ссылку в XSL-файл в библиотеке стилей, который вы скопировали в нее (ссылка может быть относительной или абсолютной).

Вставленная ссылка на XSL-файл

Нажмите кнопку "ОК", чтобы сохранить изменения, а затем нажмите кнопку "Остановить редактирование" на ленте "Страница" в верхней части страницы.

Кнопку

Если все было настроено правильно, вы должны увидеть числа в столбце «Состояние в днях».

Столбец

Вот как страница выглядит с различными тестовыми датами:

Отчет по срокам оплаты с тестовыми данными

Сводка

Итак, вот он: надежный способ создания отчета по возрасту элементов в SharePoint, обеспечивающий привлекательное форматирование и хорошую производительность, а также не требующий программирования для реализации. Он может пригодиться в различных ситуациях в дополнение к той, которую мы здесь рассмотрели. Другой распространенный сценарий для этого типа отчета — прикрепление его к списку задач, чтобы вы могли сразу увидеть, сколько времени прошло с момента создания задачи.

Надеюсь, вам понравилась эта статья.

-Джастин

Джастин Joyce (Justin Joyce), LANtek

Комментарии

Отсутствуют шаги
08.10.2012 г. 3:51
Итак, я выполнил инструкции, но, должно быть, чего-то не хватает - как XSL узнает, какую дату использовать или в какое поле добавить дни с тех пор? Ненавидь, когда шаги пропускаются.

No-Code, договорились!
30.08.2012 12:12
Я согласен - я не думаю, что это действительно считается "без кода".
Интересно, что благодаря какой-то ошибке в SharePoint у меня есть работающий вычисляемый столбец с "Сегодня"... Не знаю, как и почему это произошло, так как больше этот фокус не проходит, но старый столбец на месте и работает.

Формула для вычисляемого столбца "Дни в статусе"?
02.05.2012 г. 7:39
Джастин: Какую формулу вы использовали для вычисляемого столбца сайта "Дни в статусе" (столбец-заполнитель)? Может быть, "=today"?

SharePoint 2007
02.12.2011 11:29
В настоящее время я не пытался применить это решение к SharePoint 2007, однако я изучаю его. К сожалению, свойство XslLink недоступно в веб-части через пользовательский интерфейс.

Отличный пост
30.11.2011 г. 9:53
Здравствуйте!
Отличный пост.
Я использую SharePoint 2007.
У меня нет раздела "Разное", как указано выше.
Есть ли у вас инструкции по настройке SP2007?
Спасибо!

Re: Решение без кода: отображение дней с момента последнего изменения элемента списка SharePoint
11.10.2011 8:24
Привет, Крис.
отличная находка!
Я собираюсь взглянуть на то, что вы, надеюсь, опубликовали позже сегодня, и посмотрю, смогу ли я сделать это решение немного более надежным.
Я рад, что вам понравился пост, и я очень рад, что вы смогли найти решение для европейского формата даты. :)
-Джастин

Решение для европейских форматов дат
11.10.2011 6:45
И снова здравствуйте, Джастин!
К вашему сведению, я нашел решение проблемы, о которой упоминал ранее на этой странице;
https://sharepointbydummies.wordpress.com/2011/07/13/possible-work-around-to-date-format-issue-sharepoint-2010/

Европейские форматы дат
07.10.2011 г. 3:59
Здравствуйте, Джастин!
Это действительно хорошее решение, спасибо, и это именно то, что я искал последние два дня! Но у меня возникли с ним проблемы, и я надеюсь, что ты можешь помочь.
Я немного изменил ваш код, чтобы вычислить количество дней до того, как что-то произойдет, а не после, переключив переменные в последней строке функции "DateDiff";

<xsl:value-of select="$JulianToday - $JulianStartDate"></xsl:value-of>

Однако я могу заставить его правильно объяснить разницу только в половине случаев. Так, например, с этой датой (формат дд/мм/гггг);

30/12/2011

Он вычисляется правильно, но с этой датой (тот же формат)

12/10/2011

Он вычисляет так, как если бы это было 10 декабря 2011 года, а не 12 октября 2011 года.
Я попробовал просто поменять местами значения дня и месяца в переменной "JulianStartDate", вот так;

<xsl:with-param name="Month" select="substring(ddwrt:FormatDateTime(string($StartDate), 1033, 'yyyyMMdd'),7,2)"/>
<xsl:with-param name="Day" select="substring(ddwrt:FormatDateTime(string($StartDate), 1033, 'yyyyMMdd'),5,2)"/>

И это исправило проблему со второй датой, однако тогда она была неверной для первой даты!
Я также безуспешно пытался изменить вызовы FormatDateTime, чтобы использовать европейские LCID и различные изменения последнего параметра FormatDateTime (например, ddMMyyyy, MMddyyyy) с соответствующими корректировками позиционных параметров подстроки.
Я был бы рад твоему совету.
Благодарю за внимание,
Крис (Chris)

No-Code
21.09.2011 4:27
Я не думаю, что XSL можно квалифицировать как решение "без кода", так как понимание языка XSL не для всех, однако оно не включает в себя программирование. За исключением этого, отличное решение, спасибо!