Outlook.Interop Items.Find (), кажется, не соответствует правильно - PullRequest
0 голосов
/ 04 сентября 2018

Я хочу найти в календаре Outlook и общих календарях в моей сети информацию о встречах, чтобы проверить, есть ли свободное время в разных календарях.

Не было проблем получить все элементы Appointment-Items календарей, которые я предварительно отфильтровал, используя Items.Restrict (строковый фильтр), чтобы получать элементы только от Today или новее. Мой поисковый шаблон выглядит так:

"[Start] >= '" + DateTime.Today.ToString("dd.MM.yyyy HH:mm") + "' AND [End] <= '" + DateTime.Parse("01.01.2019").ToString("dd.MM.yyyy HH:mm") + "'";

Все работает нормально (были проблемы с форматом времени dd.MM.yyyy и dd / MM / yyyy, но это было решено).

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

Это мой шаблон поиска ({0} - время временного начала, а {1} - время временного окончания):

"(([Start] <= '{0}' AND '{0}' <= [End]) OR 
([Start] <= '{1}' AND '{1}' <= [End])) OR 
(('{0}' <= [Start] AND [Start] <= '{1}') OR 
('{0}' <= [End] AND [End] <= '{1}'))";

Для моего теста я назначил встречу сегодня с 08:00 до 08:30 и искал следующую встречу, начав поиск в 15:18. Таким образом, поиск должен возвращать ноль, потому что он не должен обнаруживать совпадение времени, но возвращает тестовое назначение с утра.

Если я заменим значения в строке поиска на мое время и время найденной встречи ({0} -> 15:18, {1} -> 16:18, [Start] -> 08:00, [Конец] -> 08:30) Я получил это:

((04.09.2018 08:00:00 <= '04.09.2018 15:25:09' AND '04.09.2018 15:25:09' <= 04.09.2018 08:30:00) OR (04.09.2018 08:00:00 <= '04.09.2018 16:25:09' AND '04.09.2018 16:25:09' <= 04.09.2018 08:30:00)) 
OR (('04.09.2018 15:25:09' <= 04.09.2018 08:00:00 AND 04.09.2018 08:00:00 <= '04.09.2018 16:25:09') OR ('04.09.2018 15:25:09' <= 04.09.2018 08:30:00 AND 04.09.2018 08:30:00 <= '04.09.2018 16:25:09'))

Проверка логики-утверждения:

//False OR False is False
(
    //False OR False is False
    (
        //True AND False is False
        (
            //Is True
            04.09.2018 08:00:00 <= '04.09.2018 15:25:09' 
            AND 
            //Is False
            '04.09.2018 15:25:09' <= 04.09.2018 08:30:00
        ) 
        OR 
        //True AND False is False
        (
            //Is True
            04.09.2018 08:00:00 <= '04.09.2018 16:25:09'
            AND 
            //Is False
            '04.09.2018 16:25:09' <= 04.09.2018 08:30:00
        )
    ) 
    OR
    //Fals OR Fals is False 
    (
        //False AND True is False
        (
            //Is Fale
            '04.09.2018 15:25:09' <= 04.09.2018 08:00:00 
            AND 
            //Is True
            04.09.2018 08:00:00 <= '04.09.2018 16:25:09'
        ) 
        OR 
        //False AND True is False
        (
            //Is False
            '04.09.2018 15:25:09' <= 04.09.2018 08:30:00 
            AND 
            //Is True
            04.09.2018 08:30:00 <= '04.09.2018 16:25:09'
        )
    )
)

Я просто не понимаю, почему этот шаблон поиска возвращает True для той встречи, которая даже не близка к проверенному времени.

Если у меня нет других встреч в этот день, это работает (возвращение ноль, а не встреча со следующего дня).

Я уже проверил проблему с форматированием времени (dd.MM.yyyy против dd / MM / yyyy и т. Д.), Поэтому я предполагаю, что это не является причиной поведения (если я использую '/' с секундами, то шаблон поиска возвращает встречу из завтрашнего дня, если я использую «.» с секундами, она возвращает сегодняшнюю встречу).

Мой шаблон поиска неверен? Я наблюдал за чем-то или форматирование времени работает в фоновом режиме по-другому?

Есть идеи? Спасибо.

EDIT

Может быть, эта фильтрация глючит? Я скопировал и вставил пример, сделанный Microsoft ( msdn ). Независимо от того, что я делаю, Outlook.Items.count (до и после Restrict ()) всегда 2147483647. Но когда я выводлю ограниченные элементы, For-Each запускается 5 раз.

Когда я читаю MAPI-папку, я предварительно сортирую элементы с помощью «[Start]> = DateTime.Now.ToString (« g »)», сортирую их и смотрю на первый элемент с датой> = Now. Ограничьте эти Предметы с ограничениями другим фильтром, когда я смотрю на первый Предмет в Предметах с ограниченным ограничением, я получил дату, которая была 5 лет назад.

Все элементы -> Ограничено [Пуск]> Сейчас -> Ограничено [Пуск]> = 08:00 -> Результат: все что угодно с 2013 года ... -.-

1 Ответ

0 голосов
/ 06 сентября 2018

Итак, поскольку функция Items.Find () кажется глючной или, по крайней мере, не способной обрабатывать более сложные вещи, чем «1 И 1», мне пришлось написать «маленький обходной путь» (который мне не нравится, и это кажется, немного медленно, если есть много встреч), чтобы решить эту проблему:

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

Dictionary<DateTime, DateTime> Plunder = new Dictionary<DateTime, DateTime>();
int AppointLength = 60;    

private void GetCalendar(object username, bool Shared)
{
    Outlook.MAPIFolder oCalendar;
    Outlook.Application oApp = new Outlook.Application();
    Outlook.NameSpace oNS = oApp.GetNamespace("mapi");
    oNS.Logon(Missing.Value, Missing.Value, true, true);

    if (Shared)
    {
        Outlook.Recipient oRecip = oNS.CreateRecipient((string)username);
        oCalendar = oNS.GetSharedDefaultFolder(oRecip, Outlook.OlDefaultFolders.olFolderCalendar);
    }
    else
    {
        oCalendar = oNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
    }

    Outlook.Items oItems = oCalendar.Items;
    oItems.IncludeRecurrences = true;
    oItems.Sort("[Start]");

    string strRestriction = "[Start] >= '" + DateTime.Today.ToString("g") + "' AND [End] <= '" + dtpEndDate.Value.ToString("g") + "'";

    Outlook.Items allNew = oItems.Restrict(strRestriction);

    allNew.Sort("[Start]");

    foreach (Outlook.AppointmentItem appt in allNew)
    {
        if (Plunder.ContainsKey(appt.Start))
        {
            if (Plunder[appt.Start] < appt.End)
            {
                Plunder[appt.Start] = appt.End;
            }
        }
        else
        {
            Plunder.Add(appt.Start, appt.End);
        }
    }
}

После того, как у меня есть все предметы из всех каландаров, которые я хочу найти в Словаре грабежей

private DateTime CheckForAppointment(DateTime now)
{
    DateTime then = now.AddMinutes(AppointLength);

    var AppointmentFound = Plunder.Select(i => i).Where(d => 
        ((d.Key < now && now < d.Value) 
        || (d.Key < then && then < d.Value)) 
        || ((now < d.Key && d.Key < then) 
        || (now < d.Value && d.Value < then)));

    if (AppointmentFound.Any())
    {
        now = CheckForAppointment(((KeyValuePair<DateTime, DateTime>)AppointmentFound.First()).Value);
    }

    return now;
}

Чтобы вернуться к следующему свободному времени.

Поскольку это решение кажется немного медленным, у кого-нибудь есть идея получше, быстрее?

Изменить:

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

...