Legio

Advanced Member | Редактировать | Профиль | Сообщение | ICQ | Цитировать | Сообщить модератору Не очень понимаю, чего вы с задачей про Excel делаете в этой теме, но свой велосипед тем не менее предложу. Допущения: а) данные о каждом звонке записаны в одну строчку в три колонки, б) данные упорядочены по времени начала звонка, в) обработка будет вестись унутре Excel'я посредством VBA (хотя последнее не очень важно, на самом-то деле). (Смысл алгоритма такой -- по первой строчке берём начало текущего учитываемого промежутка; дальше смотрим, сколько ещё звонков начинаются в это же время; дальше ищем начало следующего промежутка -- это либо конец одного из звонков, либо начало какого-то из следующих звонков; уже учтённые данные стираются.) Алгоритм детализировался методом "где левая пятка скажет, там и уточню", переменных для хранения состояния должно быть минимум 4 -- начальное время рассматриваемого промежутка (StartTime), конечное время рассматриваемого промежутка (EndTime), количество звонков за рассматриваемый промежуток (CurrentCount) и номер текущего ряда на листе "Результат" (CurrentResultRowIdx). Инициализация переменной с номером текущего ряда (CurrentResultRowIdx) должна происходить до начала обработки, остальные три (хранящие состояние рассматриваемого промежутка) должны обнуляться в начале каждого прохода по циклу. 0. Копируем исходные данные "куда-нибудь", куда не очень жалко, потому что оне в процессе помрут; в этом "куда-нибудь" помимо листа с исходными данными должен быть лист с "результатом обработки" -- пусть это будут "Данные" и "Результат". Формат листа "Результат" -- два столбца на дату и время начала промежутка, два столбца на дату и время окончания промежутка, столбец с количеством звонков за этот промежуток. 1. [На листе "Данные"] берём начальное время звонка (полное, вместе с датой; сохраняем в StartTime) из первой строчки. (Если оно там есть; если первая строчка пустая -- сворачиваемся.) 2. [На листе "Данные"] Смотрим, сколько ещё звонков началось в это время (смотрим данные во втором столбце, пока либо они не кончатся, либо не сменится время, сохраняем это значение в CurrentCount). 3. [На листе "Данные"] в текущих обрабатываемых звонках (число которых см. в CurrentCount) ищем наиболее раннее время завершения звонка (тоже полное, вместе с датой; сохраняем в EndTime). (EndTime обязательно надо сравнивать ещё и с началом "следующего" звонка -- который будет в ряду (CurrentCount+1), иначе из-за длинных звонков пропадёт много-много данных.) 4. [На листе "Результат"] Записываем время начала промежутка, время окончания промежутка и количество звонков за промежуток. (А заодно увеличиваем на единицу CurrentResultRowIdx.) 5. [На листе "Данные"] в текущих обрабатываемых звонках (число которых см. в CurrentCount) заменяем время начала звонка на EndTime. 6. [На листе "Данные"] в текущих обрабатываемых звонках (число которых см. в CurrentCount) удаляем все строчки, в которых StartTime = EndTime. 7. См. п. 1. Более чем уверен, что есть решения проще (и уж точно должны быть решения быстрее). Ещё здесь не обрабатывается случай, когда звонок нулевой длины (времена начала звонка и конца звонка совпадают). Понятия не имею, как в вашей "бизнес-логике" это надо учитывать. Если учитывать не надо, то такие случаи отлавливаются в процессе определения CurrentCount (п. 2) и по мере обнаружения изничтожаются (в CurrentCount они учитываться, естественно, не должны). При такой преобработке никто, кроме таких краевых случаев, вроде бы пострадать не должен. В роли цикла выступает While. Ещё на листе "Результат" логи будут скорее всего прерываться -- и перед практическим употреблением очень даже стоит пройтись по этому листу (снизу вверх -- потому что придётся добавлять строчки) и если у соседних рядов не совпадают начало промежутка нижнего ряда с концом промежутка верхнего ряда, добавлять строчку с недостающим промежутком, а в количество звонков за этот промежуток писать ноль. Вроде всё. Добавлено: В принципе, какой-то там лист "Результат" и не нужен вовсе -- можно же всё просто тупо append'ить в файл (т. е. минус одна переменная для хранения состояния) Добавлено: Чуть не забыл учесть длинные звонки Точно спать пора. | Всего записей: 695 | Зарегистр. 01-08-2003 | Отправлено: 20:18 09-02-2012 | Исправлено: Legio, 20:46 09-02-2012 |
|