Стандартные конфигурации 1С: дополнение и исправление
Добрый день всем, кто читает этот выпуск.
Сперва немного повтора, т.к. вряд ли кто-то читал первый выпуск. Правда, я
удивлюсь, если кто-то прочитает и второй.
Цель данной рассылки - обмен информацией по стандартным конфигурациям 1С. Не
секрет, что они далеки от потребностей живых организаций, и программистам
приходится прилагать массу усилий, чтобы "заточить" конфигурацию под
конкретного пользователя. Одни организации работают для этого с франчайзи, в
других тем же занимаются штатные или приходящие программисты. Франчайзи
немного легче, т.к. они имеют возможность сравнивать несколько фирм, у них
есть доступ к закрытой информации, они даже могут взаимодействовать с
разработчиками. У остальных такой возможности нет.
Предвижу такой вопрос: "Зачем еще один ресурс, ведь есть разные клубы,
например, http://1c.hippo.ru?" Конечно, такие
клубы есть. Но... во-первых, не у всех есть время и/или возможность проводить
в таких клубах много времени, рассылка же будет приходить по почте. Во-вторых,
у данной рассылки будет более узкая специализация.
Обсуждаться будут те вопросы, которые будут интересны подписчикам (ну и мне,
конечно :) Кроме того, всерьез рассчитываю на соавторство подписчиков. Манией
величия не страдаю, естественно, я знаю и могу разобраться не во всем, да и
времени на это нужно прорву. Конечно, буду подкидывать и отсебятину, как
вопросы, так и ответы. Просто информацию, которую сочту интересной.
Отдельно скажу о сайте
http://blue-bird-ltd.narod.ru.
Сайт предназначен для размещения файлов, которые не могут быть прикреплены к
рассылке. В первую, вторую и третью очередь это будут различные примеры.
Пока-что я не планирую развитие сайта как самостоятельного ресурса, хотя кто
знает...
Ну а теперь то, ради чего эта рассылка. Сегодня я привожу кусочек алгоритма
закрытия месяца в 1С:Бухгалтерия 7.70.433
Основная проблема с этим документом - сильно уж он долго проводится. Делаем
замер производительности и обнаруживаем, что основное торможение происходит в
функции ОтобратьСтрокиТаблицы. Еще бы, эта функция вызывается несколько
десятков раз для каждого сотрудника, а таблица, из которой она выбирает
строки, содержит все начисления сотрудника с начала года! Если на предприятии
2-3 тысячи сотрудников, это становится заметно :)
Оригинал функции любой может посмотреть сам. Я привожу здесь исправленный.
Замечу, что в оригинале функция сразу создает копию таблицы, с которой далее
работает. Это довольно дорогостоящая (по времени) процедура, которая нужна,
тем не менее, далеко не всегда. Кстати, время создания экземпляра таблицы
намного больше времени копирования даже десятка строк, так что мы имеем
торможение даже на пустых таблицах. Поэтому я создаю копию таблицы только
тогда, когда это необходимо - перед тем, как удалить лишние строки.
Функция ОтобратьСтрокиТаблицы(Таб, СписокКолонок)
Если (Таб.КоличествоСтрок() = 0) или (СписокКолонок.РазмерСписка() = 0) Тогда
Возврат Таб;
КонецЕсли;
// Отсортируем полученную таблицу по переданным в функцию колонкам
ИменаКолонок = "";
ИмяКолонки = "";
Для а = 1 по СписокКолонок.РазмерСписка() Цикл
СписокКолонок.ПолучитьЗначение(а, ИмяКолонки);
ИменаКолонок = ИменаКолонок + ?(ИменаКолонок="","",",") + ИмяКолонки;
КонецЦикла;
Таб.Сортировать(ИменаКолонок);
// Определим начальную и конечную строки таблицы, в которых есть указанные значения.
НачСтрока = 0;
КонСтрока = 0;
// Пропустим первые ненужные строки таблицы.
НачСтрокаПоиска = 0;
ИмяПервойКолонки = "";
Если Таб.НайтиЗначение(СписокКолонок.ПолучитьЗначение(1, ИмяПервойКолонки), НачСтрокаПоиска, ИмяПервойКолонки) = 0 Тогда
Т = СоздатьОбъект("ТаблицаЗначений");
Таб.Выгрузить(Т, 1, 1);
Т.УдалитьСтроки();
Возврат Т;
КонецЕсли;
Для а = НачСтрокаПоиска по Таб.КоличествоСтрок() Цикл
СтрокаУдовлетворяетУсловиям = 1;
Для б = 1 по СписокКолонок.РазмерСписка() Цикл
ИмяКолонки = "";
ЗначениеЯчейки = СписокКолонок.ПолучитьЗначение(б, ИмяКолонки);
Если (Таб.ПолучитьЗначение(а, ИмяКолонки) <> ЗначениеЯчейки) Тогда
СтрокаУдовлетворяетУсловиям = 0;
Прервать;
КонецЕсли;
КонецЦикла;
Если СтрокаУдовлетворяетУсловиям = 1 Тогда
Если НачСтрока = 0 Тогда // начальная строка пока не найдена
НачСтрока = а;
КонецЕсли;
Иначе
Если НачСтрока > 0 Тогда // начальная строка уже была найдена
КонСтрока = а - 1;
Прервать;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если НачСтрока = 0 Тогда // ни одной строки не найдено
Т = СоздатьОбъект("ТаблицаЗначений");
Таб.Выгрузить(Т, 1, 1);
Т.УдалитьСтроки();
Возврат Т;
КонецЕсли;
Если КонСтрока = 0 Тогда // последняя строка таблицы удовлетворяла условиям
КонСтрока = Таб.КоличествоСтрок();
КонецЕсли;
Результат = СоздатьОбъект("ТаблицаЗначений");
Таб.Выгрузить(Результат, НачСтрока, КонСтрока);
Возврат Результат;
КонецФункции; // ОтобратьСтрокиТаблицы()
Использование такого варианта функции дает до 50% экономии времени на цикле
перебора сотрудников. Еще процентов 25 можно наскрести в другом месте, но об
этом в другой раз.