Entendendo a estrutura de eventos recorrentes no SharePoint (RecurrenceData)
A funcionalidade de eventos recorrentes, presente nas listas do tipo Calendário do SharePoint, pode ser muito interessante e útil. Para aprender como agendar um evento, veja esse link: http://office.microsoft.com/pt-br/sharepoint-server-help/agendar-eventos-e-etapas-com-um-calendario-HA101729898.aspx.
Existem alguns truques que, se usados corretamente, podem facilitar e muito a vida de um desenvolvedor.
O primeiro passo é entender como o SharePoint se comporta com esses eventos, ao salvar um item de calendário, internamente. Para isso, o primeiro passo é observar alguns campos internos (fRecurrence, fAllDayEvent, EventType):
Tipo | Descrição | fRecurrence | fAllDayEvent | EventType |
Evento Único | Um evento criado com o checkbox “Dia todo” e “Recorrência” desmarcados. | False | False | 0 |
Evento de um dia inteiro | Um evento criado com o checkbox “dia todo” marcado. | False | True | 0 |
Evento Recorrente | Um evento criado com o checkbox “recorrência” marcado. Tem um ícone de recorrência na visualização de Todos os Eventos. Aparece como um único evento mestre, mas nas visões de calendários todas as instâncias são mostradas. | True | False | 1 |
Evento de dia todo recorrente | Igual o item acima, mas com o checkbox “dia todo” marcado. | True | True | 1 |
Exceção da recorrência | Criado com a edição de uma instância de um evento recorrente. Tem um ícone de recorrência “riscado”. | True | False | 4 |
Exceção da recorrência de eventos de dia todo | Igual acima, mas com um evento de dia todo. | True | True | 4 |
Item deletado de uma recorrência | Criado deletando uma instância de um evento recorrente. O título é alterado para começar com “Deletado: “ na view de Todos os Eventos e não aparece nas visualizações de calendário. | True | False | 3 |
Item deletado de uma recorrência de dia todo. | Igual acima, mas para eventos de dia todo. | True | True | 3 |
O quadro acima, mostra como o SharePoint se comporta durante o salvamento de um item na lista de calendário. Entretanto, alguns campos "default" podem ter comportamentos diferentes de acordo com o cenário de teste. Vejam:
Campo | Valor para evento único | Valor para evento recorrente |
EventDate | Data e hora de ínicio | Data e hora de início de quando o evento recorrente foi criado, que pode ser uma data anterior a primeira instância de um evento recorrente; |
EndDate | Data e hora de término | Data e hora da última instância de um evento recorrente. Para eventos recorrentes sem data de término, esta é uma data calculada a vários anos no futuro. |
Duration | O tempo em segundos entre a data de início e término | A duração em segundos de uma instância individual do evento recorrente. |
A maior confusão está no armazenamento desses itens, a forma como é mostrado na visão de calendário sugere que ao criarmos um evento recorrente, são gerados vários itens, um para cada ocorrência da recorrência desejada.
Entretanto, a engine do SharePoint armazena apenas 1 ITEM na lista. Todas as recorrências são apenas SOMBRAS ou projeções. Tudo isso é controlado pelo campo RecurrenceData.
Vejam alguns exemplos:
Tipo de recorrência | Valor do campo RecurrenceData |
Diariamente, a cada um dia, sem data de término | <recurrence><rule><firstDayOfWeek>su</firstDayOfWeek>
<repeat><daily dayFrequency=”1″ /></repeat> <repeatForever>FALSE</repeatForever> </rule></recurrence> |
Semanalmente, toda segunda, terça e quarta, terminando em 31/05/2007 | <recurrence><rule><firstDayOfWeek>su</firstDayOfWeek>
<repeat><weekly mo=”TRUE” tu=”TRUE” we=”TRUE” weekFrequency=”1″ /></repeat> <windowEnd>2007-05-31T22:00:00Z</windowEnd> </rule></recurrence> |
Mensalmente, toda terceira quarta-feira a cada 2 meses, sem data de término | <recurrence><rule><firstDayOfWeek>su</firstDayOfWeek>
<repeat><monthlyByDay we=”TRUE” weekdayOfMonth=”third” monthFrequency=”2″ /></repeat> <repeatForever>FALSE</repeatForever> </rule></recurrence> |
Anualmente, todo dia 18 de maio, termina após 10 ocorrências. | <recurrence><rule><firstDayOfWeek>su</firstDayOfWeek>
<repeat><yearly yearFrequency=”1″ month=”5″ day=”18″ /></repeat> <repeatInstances>10</repeatInstances> </rule></recurrence> |
Para os desenvolvedores, todo o truque está no objeto SPQuery, utilizando a propriedade ExpandRecurrence que "explode" os itens, gerando uma sombra de vários itens com o mesmo ID do original.
using(SPSite site = new SPSite("http://localhost/"))using (SPWeb web = site.RootWeb){SPList calendarList = web.Lists.TryGetList("Calendar");if (calendarList != null){SPQuery query = new SPQuery();// Aqui que a mágica acontecequery.ExpandRecurrence = true;query.Query = "<Where><Eq><FieldRef Name='EventDate' IncludeTimeValue='False'/><Value Type='DateTime'>"+SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Now)+"</Value></Eq></Where>";// Pesquisar apartir do começo do mês atualquery.CalendarDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);// Retorna todos os itens (incluindo as ocorrências de um // evento recorrente que aparecem na visão de calendário// do mês atual para frente // Exemplo: Se tem apenas 1 item na lista, com 10 ocorrências// nesse mês, o resultado serão 10 SPListItem com o mesmo ID de// item, mudando apenas as informações sobre a data para conter// uma única ocorrênciaSPListItemCollection calendarItems = calendarList.GetItems(query);foreach (SPListItem item in calendarItems){Console.WriteLine(item["Title"] + ": começa " + item["EventDate"].ToString() + " e termina "+ item["EndDate"].ToString());}}}