Gerenciar Compromissos: Criar & Manipular, Converter ICS para MSG
Este artigo cobre compromissos iCalendar (ICS) baseados em padrões manipulados através do Appointment classe. Para trabalhar com Outlook MapiCalendar itens, veja Gerenciando itens de calendário do Outlook; para armazenar e ler itens de calendário dentro de um PST, veja Gerenciando Itens de Calendário em Arquivos PST.
Criar um Compromisso e Salvar em Disco nos Formatos MSG ou ICS
O Appointment classe em Aspose.Email para .NET pode ser usada para criar um novo compromisso. Neste artigo, primeiro criamos um compromisso e o salvamos em disco no formato ICS. Os passos a seguir são necessários para criar um compromisso e salvá-lo em disco.
- Crie uma instância do Appointment classe e inicialize‑a com este construtor.
- Passe os seguintes argumentos no construtor acima
- Local
- Resumo
- Descrição
- Data de Início
- Data de Término
- Organizador
- Participantes
- Chame o Save() método e especifique o nome do arquivo e o formato nos argumentos.
O compromisso pode ser aberto no Microsoft Outlook ou em qualquer programa que possa carregar um arquivo ICS. Se o arquivo for aberto no Microsoft Outlook, ele adiciona automaticamente o compromisso ao calendário do Outlook.
O trecho de código a seguir mostra como criar e salvar um compromisso em disco nos formatos ICS ou MSG.
// Create and initialize an instance of the Appointment class
Appointment appointment = new Appointment(
"Meeting Room 3 at Office Headquarters",// Location
"Monthly Meeting", // Summary
"Please confirm your availability.", // Description
new DateTime(2015, 2, 8, 13, 0, 0), // Start date
new DateTime(2015, 2, 8, 14, 0, 0), // End date
"from@domain.com", // Organizer
"attendees@domain.com"); // Attendees
// Save the appointment to disk in ICS format
appointment.Save(fileName + ".ics", new AppointmentIcsSaveOptions());
Console.WriteLine("Appointment created and saved to disk successfully.");
// Save the appointment to disk in MSG format
appointment.Save(fileName + ".msg", new AppointmentMsgSaveOptions());
Console.WriteLine("Appointment created and saved to disk successfully.");
Criar um Compromisso com Conteúdo HTML
Você pode especificar representações alternativas da descrição do evento em diferentes tipos de conteúdo usando o cabeçalho X-ALT-DESC. Ele permite que os destinatários do arquivo iCalendar escolham a representação que melhor atenda às suas necessidades. Por exemplo, você pode incluir uma descrição em texto simples usando o tipo de conteúdo "text/plain" e uma descrição em HTML usando o tipo de conteúdo "text/html". O cabeçalho X-ALT-DESC é adicionado para cada representação alternativa. Para criar um compromisso com conteúdo HTML, defina o HtmlDescription propriedade.
Experimente o seguinte exemplo de código para criar um compromisso com descrição HTML alternativa:
- Crie uma nova instância da classe Appointment.
- Forneça os parâmetros necessários ao construtor Appointment:
- Especifique o local do compromisso.
- Defina a data e hora de início.
- Defina a data e hora de término.
- Especifique o organizador.
- Especifique o participante.
- Defina o HtmlDescription propriedade do objeto de compromisso, indicando que a descrição está em formato HTML.
- Defina a propriedade Description do objeto de compromisso para uma string formatada em HTML, delimitada por uma string multilinha:
- A marcação HTML inclui um bloco <style> definindo uma classe CSS chamada "text" com estilos de fonte.
- O corpo HTML contém uma tag de parágrafo <p> com a classe CSS "text", e a mensagem real de convite.
- O objeto de compromisso está agora pronto, e você pode executar operações adicionais ou salvá-lo como um arquivo iCalendar.
var appointment = new Appointment("Bygget 83",
DateTime.UtcNow, // start date
DateTime.UtcNow.AddHours(1), // end date
new MailAddress("TintinStrom@from.com", "Tintin Strom"), // organizer
new MailAddress("AinaMartensson@to.com", "Aina Martensson")) // attendee
{
HtmlDescription = @"
<html>
<style type=""text/css"">
.text {
font-family:'Comic Sans MS';
font-size:16px;
}
</style>
<body>
<p class=""text"">Hi, I'm happy to invite you to our party.</p>
</body>
</html>"
};
Criar uma Solicitação de Compromisso em Rascunho
Foi mostrado em nossos artigos anteriores como criar e salvar um compromisso no formato ICS. Muitas vezes é necessário criar uma solicitação de compromisso no modo Rascunho, assim as informações básicas são adicionadas e então o mesmo compromisso em rascunho pode ser encaminhado a outros usuários para as alterações necessárias de acordo com usos individuais. Para salvar um compromisso no modo Rascunho, o MethodType propriedade da classe Appointment deve ser definida como AppointmentMethodType.Publish. O trecho de código a seguir mostra como criar uma solicitação de compromisso em rascunho.
string sender = "test@gmail.com";
string recipient = "test@email.com";
MailMessage message = new MailMessage(sender, recipient, string.Empty, string.Empty);
Appointment app = new Appointment(string.Empty, DateTime.Now, DateTime.Now, sender, recipient)
{
MethodType = AppointmentMethodType.Publish
};
message.AddAlternateView(app.RequestApointment());
MapiMessage msg = MapiMessage.FromMailMessage(message);
// Save the appointment as draft.
msg.Save(dstDraft);
Console.WriteLine(Environment.NewLine + "Draft saved at " + dstDraft);
Criação de Compromisso Rascunho a partir de Texto
O trecho de código a seguir mostra como criar um compromisso em rascunho a partir de Texto.
string ical = @"BEGIN:VCALENDAR
METHOD:PUBLISH
PRODID:-//Aspose Ltd//iCalender Builder (v3.0)//EN
VERSION:2.0
BEGIN:VEVENT
ATTENDEE;CN=test@gmail.com:mailto:test@gmail.com
DTSTART:20130220T171439
DTEND:20130220T174439
DTSTAMP:20130220T161439Z
END:VEVENT
END:VCALENDAR";
string sender = "test@gmail.com";
string recipient = "test@email.com";
MailMessage message = new MailMessage(sender, recipient, string.Empty, string.Empty);
AlternateView av = AlternateView.CreateAlternateViewFromString(ical, new ContentType("text/calendar"));
message.AlternateViews.Add(av);
MapiMessage msg = MapiMessage.FromMailMessage(message);
msg.Save(dataDir + "draft_out.msg");
Personalizar Compromissos
Definir o Status dos Participantes dos Compromissos
A API Aspose.Email para .NET permite definir o status dos participantes de um compromisso ao formular uma mensagem de resposta. Isso adiciona a propriedade PARTSTAT ao arquivo ICS.
DateTime startDate = new DateTime(2011, 12, 10, 10, 12, 11),
endDate = new DateTime(2012, 11, 13, 13, 11, 12);
MailAddress organizer = new MailAddress("aaa@amail.com", "Organizer");
MailAddressCollection attendees = new MailAddressCollection();
MailAddress attendee1 = new MailAddress("bbb@bmail.com", "First attendee");
MailAddress attendee2 = new MailAddress("ccc@cmail.com", "Second attendee");
attendee1.ParticipationStatus = ParticipationStatus.Accepted;
attendee2.ParticipationStatus = ParticipationStatus.Declined;
attendees.Add(attendee1);
attendees.Add(attendee2);
Appointment target = new Appointment(location, startDate, endDate, organizer, attendees);
Personalizar o Identificador de Produto para iCalendar
A API Aspose.Email para .NET permite obter ou definir o identificador de produto que criou o objeto iCalendar.
string description = "Test Description";
Appointment app = new Appointment("location", "test appointment", description, DateTime.Today,
DateTime.Today.AddDays(1), "first@test.com", "second@test.com");
AppointmentIcsSaveOptions saveOptions = AppointmentIcsSaveOptions.Default;
saveOptions.ProductId = "Test Corporation";
app.Save(dataDir + "ChangeProdIdOfICS.ics", saveOptions);
Carregando Compromissos
Além disso, o Appointment classe pode ser usada para carregar um compromisso a partir de um arquivo ICS.
Carregar um Compromisso em Formato ICS
Para carregar um compromisso em formato ICS, os seguintes passos são necessários:
- Crie uma instância do Appointment classe.
- Chame o Load() método fornecendo o caminho do arquivo ICS.
- Leia qualquer propriedade para obter qualquer informação do compromisso (arquivo ICS).
O trecho de código a seguir mostra como carregar um compromisso no formato ICS.
// Load an Appointment just created and saved to disk and display its details.
Appointment loadedAppointment = Appointment.Load(dstEmail);
Console.WriteLine(Environment.NewLine + "Loaded Appointment details are as follows:");
// Display the appointment information on screen
Console.WriteLine("Summary: " + loadedAppointment.Summary);
Console.WriteLine("Location: " + loadedAppointment.Location);
Console.WriteLine("Description: " + loadedAppointment.Description);
Console.WriteLine("Start date: " + loadedAppointment.StartDate);
Console.WriteLine("End date: " + loadedAppointment.EndDate);
Console.WriteLine("Organizer: " + loadedAppointment.Organizer);
Console.WriteLine("Attendees: " + loadedAppointment.Attendees);
Console.WriteLine(Environment.NewLine + "Appointment loaded successfully from " + dstEmail);
Converter ICS para MSG
A API permite converter facilmente um Compromisso em um objeto de mensagem. O exemplo de código a seguir mostra como converter uma solicitação de compromisso em um MailMessage ou MapiMessage:
var appointment = Appointment.Load("appRequest.ics");
var eml = appointment.ToMailMessage();
var msg = appointment.ToMapiMessage();
Ler Múltiplos Eventos de um Arquivo ICS
List<Appointment> appointments = new List<Appointment>();
CalendarReader reader = new CalendarReader(dataDir + "US-Holidays.ics");
while (reader.NextEvent())
{
appointments.Add(reader.Current);
}
//working with appointments...
Escrever Múltiplos Eventos em Arquivo ICS
AppointmentIcsSaveOptions saveOptions = new AppointmentIcsSaveOptions();
saveOptions.Action = AppointmentAction.Create;
using (CalendarWriter writer = new CalendarWriter(dataDir + "WriteMultipleEventsToICS_out.ics", saveOptions))
{
for (int i = 0; i < 10; i++)
{
Appointment app = new Appointment(string.Empty, DateTime.Now, DateTime.Now, "sender@domain.com", "receiver@domain.com");
app.Description = "Test body " + i;
app.Summary = "Test summary:" + i;
writer.Write(app);
}
}
Determinar a Versão do Compromisso
Para determinar a versão de um compromisso, você pode usar o Appointment.Version propriedade do Appointment classe. Esta propriedade auxilia a determinar com base em qual versão seus arquivos foram criados, garantindo integração com outros sistemas e aplicativos.
O exemplo de código a seguir mostra como implementar esta propriedade em seu projeto:
var app = Appointment.Load("meeting.ics");
// Version is a string that holds the ICS/VCS version, e.g. "2.0" for iCalendar
if (app.Version == "2.0")
{
// do something
}
Enviando e Cancelando Solicitações de Reunião
O Appointment classe, juntamente com o SmtpClient, pode ser usado para enviar solicitações de reunião, solicitações de reunião recorrentes, atualizações e cancelamentos por e‑mail. O compromisso é adicionado a um MailMessage como visualização alternativa.
Enviar uma Solicitação de Reunião
Para enviar uma solicitação de reunião, crie um Appointment, adicione-a a uma mensagem usando o RequestApointment método, e envie a mensagem. Salve o UniqueId valor para que você possa referenciar o mesmo compromisso posteriormente ao enviar uma atualização ou cancelamento.
// Create an instance of SmtpClient
SmtpClient client = new SmtpClient("smtp.gmail.com", 587, "user@gmail.com", "password");
client.SecurityOptions = SecurityOptions.Auto;
// Gather the attendees
MailAddressCollection attendees = new MailAddressCollection();
attendees.Add(new MailAddress("first.attendee@domain.com", "First Attendee"));
attendees.Add(new MailAddress("second.attendee@domain.com", "Second Attendee"));
// Create the message and the appointment
MailMessage msg = new MailMessage();
msg.From = "organizer@domain.com";
msg.To = attendees;
Appointment app = new Appointment("Meeting Room 1", DateTime.Now, DateTime.Now.AddHours(1), msg.From, attendees);
app.Summary = "Monthly Meeting";
app.Description = "Please confirm your availability.";
// Add the appointment to the message and send it
msg.AddAlternateView(app.RequestApointment());
client.Send(msg);
Enviar uma Solicitação de Reunião Recorrente
Para criar uma solicitação de reunião com recorrência, atribua um padrão de recorrência (por exemplo, um WeeklyRecurrencePattern) para o Appointment.Recurrence propriedade. Salvar o ID exclusivo do compromisso permite enviar atualizações ao compromisso posteriormente.
// Create a mail message
MailMessage msg1 = new MailMessage();
msg1.To.Add("to@domain.com");
msg1.From = new MailAddress("from@gmail.com");
// Fill the appointment object
DateTime startDate = new DateTime(2013, 12, 1, 17, 0, 0);
DateTime endDate = new DateTime(2013, 12, 31, 17, 30, 0);
Appointment agendaAppointment = new Appointment("same place", startDate, endDate, msg1.From, msg1.To);
// Create a unique id so the appointment can be accessed later
string szUniqueId = Guid.NewGuid().ToString();
agendaAppointment.UniqueId = szUniqueId;
agendaAppointment.Description = "----------------";
// Create a weekly recurrence pattern: Mon, Tue and Thu
WeeklyRecurrencePattern pattern1 = new WeeklyRecurrencePattern(14);
pattern1.StartDays = new CalendarDay[3];
pattern1.StartDays[0] = CalendarDay.Monday;
pattern1.StartDays[1] = CalendarDay.Tuesday;
pattern1.StartDays[2] = CalendarDay.Thursday;
pattern1.Interval = 1;
// Set the recurrence pattern for the appointment
agendaAppointment.Recurrence = pattern1;
// Attach the appointment to the mail
msg1.AlternateViews.Add(agendaAppointment.RequestApointment());
// Send the mail with the appointment request
SmtpClient client = new SmtpClient("smtp.gmail.com", 587, "your.email@gmail.com", "your.password");
client.SecurityOptions = SecurityOptions.Auto;
client.Send(msg1);
Enviar uma Solicitação de Atualização de Compromisso
Para enviar uma atualização de um compromisso previamente enviado, o ID exclusivo do compromisso é necessário. Use o UpdateAppointment método para construir a visualização alternativa de atualização.
static public void SendUpdate(string szUniqueId)
{
DateTime startDate = new DateTime(2013, 12, 12, 17, 0, 0);
DateTime endDate = new DateTime(2013, 12, 12, 17, 30, 0);
Appointment appUpdate = new Appointment("Different Place", startDate, endDate,
"organizer@gmail.com", "attendee@domain.com");
appUpdate.UniqueId = szUniqueId;
appUpdate.Summary = "update meeting request summary";
appUpdate.Description = "update";
MailMessage msgUpdate = new MailMessage("organizer@gmail.com", "attendee@domain.com",
"test email - update meeting request", "test email");
msgUpdate.AddAlternateView(appUpdate.UpdateAppointment());
SmtpClient smtp = new SmtpClient("server.domain.com", 587, "username", "password");
smtp.Send(msgUpdate);
}
Cancelar uma Solicitação de Reunião
Para cancelar uma reunião, construa a mesma Appointment (usando as informações que você armazenou quando a solicitação foi enviada), adicione-a a uma mensagem com o CancelAppointment método, e envie a mensagem aos participantes.
// Re-create the attendee collection and the appointment from your stored data
MailAddressCollection attendees = new MailAddressCollection();
attendees.Add(new MailAddress("first.attendee@domain.com", "First Attendee"));
attendees.Add(new MailAddress("second.attendee@domain.com", "Second Attendee"));
Appointment app = new Appointment("Meeting Room 1", "Monthly Meeting", "Please confirm your availability.",
DateTime.Now, DateTime.Now.AddHours(1),
new MailAddress("organizer@domain.com", "Organizer"), attendees);
// Create the cancellation message
MailMessage msg = new MailMessage();
msg.From = new MailAddress("organizer@domain.com", "");
msg.To = attendees;
msg.Subject = "Cancel meeting";
msg.AddAlternateView(app.CancelAppointment());
SmtpClient smtp = new SmtpClient("smtp.gmail.com", 587, "user@gmail.com", "password");
smtp.Send(msg);
Trabalhando com Padrões de Recorrência iCalendar
Um padrão de recorrência é uma forma de descrever uma agenda específica. Ele contém informações suficientes para construir uma lista de ocorrências (datas e horários) de acordo com uma agenda dada. Um padrão de recorrência pode conter regras de recorrência que descrevem ciclos que se combinam para formar o padrão geral. Em geral, quanto mais complexo for um padrão de recorrência, mais regras de recorrência ele conterá.
Padrões de recorrência podem incluir exceções (não confundir com exceções que representam erros durante a execução da aplicação). Exceções adicionam ou removem datas de ocorrência em relação ao padrão original. Elas podem ser especificadas como ocorrências explícitas ou como um padrão próprio. Exemplos de padrões de recorrência com exceções:
- Todo segundo sexta‑feira, exceto de junho a agosto.
- O dia 1 de cada mês, exceto janeiro, quando deve ser no dia 2.
O RFC iCalendar define componentes, como VEVENT ou VTODO, que representam eventos ou tarefas. Os componentes podem ter propriedades como data/hora de início, descrição, local, participantes e recorrência. Um padrão de recorrência normalmente existe como propriedade de uma tarefa ou evento recorrente. As propriedades de padrão de recorrência definidas pelo iCalendar são:
- DTSTART – a data e hora de início do padrão (também representa a primeira ocorrência se não for excluída explicitamente).
- RRULE – especifica uma regra de repetição para um conjunto de recorrência.
- RDATE – define uma lista de datas e horários a serem incluídos em um conjunto de recorrência.
- EXRULE – especifica uma regra de repetição para exceções de um conjunto de recorrência.
- EXDATE – define uma lista de datas e horários de exceções de um conjunto de recorrência.
Apenas o DTSTART é obrigatório, e deve existir apenas um DTSTART. Todas as demais propriedades são opcionais e podem ser especificadas mais de uma vez.
O Modelo de Objetos de Recorrência do Aspose.Email
O Aspose.Email.Calendar.Recurrences namespace contém as classes usadas para trabalhar com recorrências iCalendar. CalendarRecurrence e RecurrenceRule são as classes centrais, e fornecem implementações concretas dos elementos RFC 2445 correspondentes.
- O
CalendarRecurrenceclasse representa o padrão de recorrência completo. Você pode criar um novo padrão de recorrência do zero usando o construtor padrão, ou carregar um padrão existente no formato iCalendar usando o método estáticoFromiCalendarmétodo. - O
RecurrenceRuleclasse representa a parte RRULE ou EXRULE de um padrão de recorrência.RecurrenceRuleexibe várias propriedades que mapeiam diretamente para suas contrapartes no padrão iCalendar. Por exemplo,ByMonthmapeia para BYMONTH no iCalendar, etc. Ao examinar ou definir valores doRecurrenceRulepropriedades, você pode analisar ou modificar uma regra de recorrência.
O trecho de código a seguir carrega um padrão de recorrência (no qual a parte RRULE contém a regra de recorrência) e gera as ocorrências:
// Ten team meetings, every Monday at 10am.
CalendarRecurrence pattern = new CalendarRecurrence("DTSTART:20040301T100000\n" + "RRULE:FREQ=WEEKLY;COUNT=10;BYDAY=MO");
DateCollection dates = pattern.GenerateOccurrences();
Gerar Ocorrências a Partir de um Padrão de Recorrência
Com Aspose.Email é possível gerar ocorrências a partir de um padrão de recorrência. Para obter a ocorrência "próxima", use o GenerateOccurrences método com o parâmetro nNextOccurrences = 1. O trecho de código a seguir gera 20 ocorrências usando GenerateOccurrences(20).
CalendarRecurrence recurrencePattern = new CalendarRecurrence();
recurrencePattern.StartDate = new DateTime(1997, 9, 10, 9, 0, 0);
RecurrenceRule rule = recurrencePattern.RRules.Add();
rule.Frequency = Frequency.Monthly;
rule.Count = 20;
rule.Interval = 18;
rule.ByMonthDay.Add(new int[] { 10, 11, 12, 13, 14, 15 });
DateCollection expectedDates = recurrencePattern.GenerateOccurrences(20);
Console.WriteLine("expectedDates.Count = " + expectedDates.Count);
foreach (DateTime date in expectedDates)
{
Console.WriteLine("DateTime = " + date);
}
Obter Texto Amigável para uma Recorrência
Texto amigável para uma regra pode ser obtido usando o FriendlyText propriedade. A saída do código a seguir é: "Recorrência a cada mês no 1.º e no 1.º dia a partir do final do mês para um máximo de 2 ocorrências."
RecurrenceRule rule = new RecurrenceRule();
rule.Frequency = Frequency.Monthly;
rule.Count = 2;
rule.ByMonthDay.Add(1);
rule.ByMonthDay.Add(-1);
Console.WriteLine(rule.FriendlyText);
Padrões de Recorrência de Exemplo
As strings de amostra RRULE a seguir ilustram como expressar agendas comuns.
-
O último dia do mês, todos os meses. Se desejar uma ocorrência no dia anterior ao último dia do mês, use
BYMONTHDAY=-2. Se você especificarBYMONTHDAY=31, então, de acordo com o padrão iCalendar, nenhuma ocorrência é gerada em meses que têm menos de 31 dias.RRULE:FREQ=MONTHLY;BYMONTHDAY=-1 -
O último dia útil de cada mês. Esta regra especifica todos os dias úteis de um mês e seleciona o último. O resultado final é o último dia útil de um mês.
RRULE:FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1 -
A última segunda‑feira do ano.
RRULE:FREQ=YEARLY;BYDAY=-1MO -
Sexta‑feira da primeira semana ISO 8601 do ano. Na especificação ISO 8601, a primeira semana do ano é a primeira que tem ao menos quatro dias.
FREQ=YEARLY;BYWEEKNO=1;BYDAY=FR -
Primeira Sexta‑feira do ano. Em 1999, por exemplo, a primeira sexta‑feira do ano é 1999/01/01, enquanto a sexta‑feira da primeira semana ISO 8601 é 1999/01/08.
FREQ=YEARLY;BYDAY=1FR
Detalhes Importantes do iCalendar (RFC 2445)
Datas, ou datas com horários associados, podem ser usadas nos elementos DTSTART, UNTIL, EXDATE e RDATE ao especificar um padrão de recorrência. O iCalendar define o tipo de valor DATE para identificar valores que contêm apenas uma data de calendário, e o tipo DATE‑TIME para identificar valores que especificam uma data de calendário precisa e horário do dia. Valores DATE‑TIME podem ser especificados em três formas: horário local, horário UTC e horário local com fuso horário.
- DATE. De acordo com o padrão iCalendar, valores DATE devem seguir o
yyyyMMddformato. Por exemplo,19970714representa 14 de julho de 1997. - DATE‑TIME com horário local. A forma de data‑hora local é simplesmente um valor de data‑hora que não contém o designador UTC e não faz referência a um fuso horário. Por exemplo,
DTSTART:19980118T230000representa 18 de janeiro de 1998, às 23 h. Valores de data‑hora desse tipo são chamados de "flutuantes" e não estão vinculados a nenhum fuso horário específico. Eles representam o mesmo valor de hora, minuto e segundo independentemente do fuso horário observado. - DATE‑TIME com horário UTC. A data com horário UTC (horário absoluto) é identificada por uma letra maiúscula
Zsufixo anexado ao valor de horário. Por exemplo,DTSTART:19980119T070000Zrepresenta 19 de janeiro de 1998, às 07:00 UTC. Observe que o Aspose.Email ignora o designador UTCZsufixo e trata o horário como horário local. O padrão RFC 2445 afirma que a parte de horário especificada na regra UNTIL de um padrão de recorrência deve estar no formato UTC; o Aspose.Email aceita horário em qualquer formato na regra UNTIL. - DATE‑TIME com horário local e fuso horário. Para referenciar um fuso horário, DATE‑TIME é modificado com a propriedade TZID. Por exemplo,
DTSTART;TZID=US-Eastern:19980119T020000representa 2 h da manhã em Nova Iorque em 19 de janeiro de 1998. Observe que o Aspose.Email atualmente ignora o parâmetro TZID e trata o horário como horário local. - Conformidade BYWEEKNO e ISO 8601. Use BYWEEKNO somente quando a conformidade com ISO 8601 é necessário. Os números de semana definidos pela ISO 8601 diferem dos números de semana no sentido normal: o número da primeira semana do ano calendário é a primeira semana que contém pelo menos quatro dias. A regra BYWEEKNO especifica uma lista de números separados por vírgula que identificam semanas do ano (valores válidos são de 1 a 53 e -1 a -53), e é válida apenas para regras ANUAIS.
Veja Também
- Gerenciando itens de calendário do Outlook — criar e gerenciar itens de calendário como Outlook
MapiCalendar(MSG) objetos. - Gerenciando Itens de Calendário em Arquivos PST — armazenar e ler itens de calendário dentro de um PST.