УДАЛЕНИЕ ЗАПИСЕЙ ЖУРНАЛА ЗАРПЛАТЫ И МЯГКАЯ СМЕНА РАСЧЕТНОГО ПЕРИОДА
На период отладки вам может понадобиться процедура удаления записей ЖЗ текущего периода. Ее код прост:
процедура ОчиститьЖЗ()
перем жз; // Журнал заработной платы
жз = СоздатьОбъект("ЖурналРасчетов.Зарплата_2"); жз.ВыбратьПериод(жз.НачалоТекущегоПериодаО); пока жз.ПолучитьЗапись() = 1 цикл жз.УдалитьЗаписьО; конецЦикла // пока конецПроцедуры // ОчиститьЖЗ
Однако у этой процедуры есть особенность: записи удаляются через одну. Это объясняется тем, что после проставления DBF-пометки удаления запись из ЖЗ исчезает и текущей становится следующая запись. Далее вступает в действие метод Полу-читьЗапись, перемещающий позицию ЖЗ еще на одну запись. Поэтому процедуру ОчиститьЖЗ нужно запускать неоднократно, что достигается следующим кодом:
функция ОчиститьЖЗ(жз, нтп)
перем флаг; // Журнал заработной платы
флаг = жз.ВыбратьПериод(нтп); если флаг = 1 тогда
пока жз.ПолучитьЗапись() = 1 цикл |
жз.УдалитьЗапись(); конецЦикла // пока конецЕсли; |
|
возврат флаг;
конецФункции // ОчиститьЖЗ |
// |
флаг = О, если в ЖЗ нет записей |
процедура Выполнить() |
перем жз; |
// |
Журнал заработной платы |
перем нтп; перем флаг; |
// |
Начало текущего периода |
|
жз = СоздатьОбъект(''ЖурналРасчетов.Зарплата_2'');
нтп = жз.НачалоТекущегоПериода();
флаг=1;
пока флаг = 1 цикл
флаг = ОчиститьЖЗ(жз, нтп); конецЦикла // пока
// Вызов формы ЖЗ для просмотра результата ОткрытьФорму('ЖурналРасчетов.Зарплата_2''); конецПроцедуры // Выполнить
После удаления записей текущего периода, возможно, потребуется вернуться к прежнему расчетному периоду и сделать его текущим. Если смена периода вперед была выполнена интерактивно, то записи сменяемого периода получают статус архи в-ных. При интерактивном откате назад произойдет обнуление р езультатов записей, период регистрации которых принадлежит к устанавливаемому расчетному периоду. Чтобы этого не произошло, следует воспользоваться следующей программой:
// Осуществляет мягкую, то есть без отработки системных действий,
// смену расчетного периода ЖЗ процедура Выполнить()
перем жз; // Журнал заработной платы
перем пер; // Переменная типа РасчетныйПериод
если Вопрос("Вернуться к предыдущему расчетному периоду?", "Да+Нет") = "Нет" тогда возврат; конецЕсли;
жз = СоздатьОбъект("ЖурналРасчетов.Зарплата_2");
// Перемещаемся на один период назад
пер = жз.ТекущийПериод( ).ПрибавитьПериод(-1);
// Устанавливаем период пер в качестве текущего, не отрабатывая системные действия если жз.УстановитьТекущийПериод(пер, 0) — 1 тогда
Предупреждение('Тотово.");
// Вызов формы ЖЗ для просмотра результата
// После открытия формы, возможно, придется сменить границу просмотра ЖЗ ОткрытьФорму("ЖурналРасчетов.Зарплата_2"); иначе
Предупреждение("Сменить период не удалось."); конецЕсли;
конецПроцедуры // Выполнить
7.4.6. ЗАГРУЗКА НАЧАЛЬНОГО САЛЬДО ИЗ DBF-ФАЙЛА
При смене программных средств неизбежно возникают задачи переноса остатков из старых файлов в новые. Нередко переносимые данные можно записать в DBF-файлы. Предположим, что так оно и есть и начальное сальдо нужно перенести из файла bal.dbf, фрагмент которого представлен в табл. 7.7, в созданный нами и пока что пустой ЖЗ.
Фрагмент файла bal.dbf с начальным сальдо
Таблица 7.7 |
Employee |
Balance |
Абрамова Лариса Сергеевна |
2.60 |
Агальцов Юрий Алексеевич |
1.70 |
Бараненков Иван Ильич |
0.30 |
|
Алгоритм переноса нетруден: |
|. Начало.
2. Открыть файл bal.dbf и переместиться на его первую запись. ,
3. Пока не обнаружен конец файла bal.dbf, выполнить:
3.1. Осуществить поиск по наименованию элемента справочника Сотрудники_2, применяя в качестве наименования значение поля Employee файла bal.dbf.
3.2. Если элемент найден, то
Добавить в ЖЗ запись, объектом которой является найденный элемент, используя в качестве результата значение поля Balance файла bal.dbf. конец если 3.2.
Перейти к следующей записи файла bal.dbf конец цикла 3.
4. Добавить запись в документ НачПериода_2 о первом расчетном периоде ЖЗ. р. Конец.
В 1С подобные алгоритмы программируются с помощью объектов типа XBase, позволяющих управлять DBF-файлами. Разместим по обычаю код, реализующий алгоритм переноса в модуле обработки Проба. Рисунки, отображающие результаты работы программы переноса данных, приведены сразу после ее текста.
Процедура одинСотр(жз, сотр, тДок, хозОп, нтп, начС) далее
функция ЕстьВЖЗ(жз, сотр) далее
Процедура ФиксироватьСменуРП(жз, док, нтп) далее
процедура Выполнить( ) перем дбф;
перем файл, папка, фио, сотр;
перем сСотр_2, жз, док, тДок, хозОп, флаг, флагЖЗ, нтп;
ОчиститьОкноСообщений();
// Открываем диалог для выбора файла bal.dbf
флаг = ФС.ВыбратьФайл(0, файл, папка, "Выберите файл"," | *.DBF"); если флаг = 0 тогда возврат; конецЕсли;
дбф = СоздатьОбъект("ХВаве"); дбф.ОткрытьФайл(папка + файл); если дбф.Открыта() = 0 тогда
Предупреждение("Не удалось открыть файл " + файл); возврат; конецЕсли;
сСотр_2 = СоздатьОбъект(" Справочник. Сотр удники_2"); жз = СоздатьОбъект("ЖурналРасчетов.Зарплата_2"); хозОп = СоздатьОбъект("Справочник.ХозОпДляВР");
// Ищем простым перебором в справочнике ХозОпДляВР вид расчета НачСальдо_2
хозОп.ВыбратьЭлементы();
флаг = 0;
пока хозОп.ПолучитьЭлемент() = 1 цикл
если хозОп.ВР = ВидРасчета.НачСальдо_2 тогда флаг = 1; прервать; конецЕсли; конецЦикла; // пока если флаг = 0 тогда
Предупреждение("Хозяйственная операция для ВР Начальное сальдо не найдена."); возврат; конецЕсли;
док = СоздатьОбъект("Документ.НачПериода_2");
// Номер документа не меняется и всегда равен единице док. НайтиПоНомеру( 1, Дата(0)); если док.Выбран() = 0 тогда
Предупреждение("Создаю документ НачПериода_2 под номером 1.", 2); док.Новый(); док.НомерДок = 1; док.ДатаДок = ТекущаяДата(); док.Записать(); конецЕсли;
тДок = док.ТекущийДокумент(); нтп = жз.НачалоТекущегоПериода(); флагЖЗ = 0;
дбф.КодоваяСтраница(0); // Используем Windows-кодировку
дбф.Первая(); // Перемещаемся на первую запись DBF-файла
// Перебираем все, кроме удаленных, записи ранее открытого DBF-файла дбф.Показывать Удаленные(0);
пока дбф.ВКонце( ) = 0 цикл // Пока не достигнут конец DBF-файла фио = дбф.Employee; // ФИО сотрудника // Задаем поиск во всем справочнике Сотрудники_2 флаг = сСотр_2.НайтиПоНаименованию(фио, 0); если флаг = 1 тогда
флагЖЗ = 1; // В ЖЗ добавлена по крайней мере одна запись
сотр = сСотр_2.ТекущийЭлемент();
// Запись для одного сотрудника одинСотр(жз, сотр, тДок, хозОп, нтп, дбф.Balance); конецЕсли;
дбф.Следующая(); // Переход на следующую DBF-запись
конецЦикла; // Результат см. на рис. 7.26
если флагЖЗ = 1 тогда // Если в ЖЗ добавлены записи
// Добавляем запись в документ НачПериода_2 о первом расчетном периоде ЖЗ // Результат см. на рис. 7.27 ФиксироватьСменуРП(жз, док, нтп);
// Вызовы форм ЖЗ и документа НачПериода_2 под номером 1 // для просмотра результата ОткрытьФорму(
,ЖурналРасчетов.Зарплата_2'');
ОткрытьФорму(тДок); иначе
Предупреждение("В ЖЗ не перенесено ни одной записи."); конецЕсли;
конецПроцедуры // Выполнить
процедура одинСотр(жз, сотр, тДок, хозОп, нтп, начС)
// Если расчет с ВР НачСальдо_2 объект уже имеет, то обновляем только результат если ЕстьВЖЗ(жз, сотр) = 0 тогда
// Добавляем расчет с ВР НачСальдо_2 для выбранного сотрудника жз.Новая();
жз.УстановитьРеквизит("Документ", тДок); жз.УстановитьРеквизит("РодительскийДокумент", тДок); жз.УстановитьРеквизит("Объект", сотр);
жз.УстановитьРеквизит("ВидРасч", ВидРасчета.НачСальдо_2); жз.УстановитьРеквизит("хозОп", хозОп.ХозОП); жз.УстановитьРеквизит("ДатаНачала", нтп); жз.УстановитьРеквизит("ДатаОкончания", нтп); жз.УстановитьРеквизит("Рассчитана", 1); иначе // Делаем расчет нефиксированным
// Журнал позиционирован функцией ЕстьВЖЗ на нужной записи // Подготовка к обновлению результата
жз.ОсвободитьЗапись(); // Делаем запись нефиксированной
конецЕсли;
// Заносим в атрибут Результат величину начального сальдо сотрудника жз.УстановитьРеквизит("Результат", начС);
// Не забываем записать новые значения реквизитов
жз.3аписать();
жз.ФиксироватьЗапись();
конецПроцедуры // одинСотр
// Вернет 1, если начальное сальдо для выбранного объекта уже введено,
// или О-в противном случае функция ЕстьВЖЗ(жз, сотр)
если жз.ВыбратьПериодПоОбъекгу(сотр) = 1 тогда пока жз.ПолучитьЗапись() = 1 цикл
если жз.ВидРасч = ВидРасчета.НачСальдо_2 тогда возврат 1; конецЕсли; конецЦикла // пока конецЕсли; возврат 0;
конецФункции // ЕстьВЖЗ
// Заносит данные о смене расчетного периода в документ НачПериода_2 процедура ФиксироватьСменуРЩжз, док, нтп)
// период - переменная типа РасчетныйПериод
док.НоваяСтрока(); // Добавляем в документ новую строку
док.НовПериод = жз.ОписательПериода(нтп);
// Дата смены расчетного периода ЖЗ Зарплата_2 док.ДатаУстановки = ТекущаяДата(); док.Пользователь = ИмяПользователя(); док.Записать();
конецПроцедуры // ФиксироватьСменуРП
 |
Рис. 7.26. Расчеты НачСальдо_2 введены из файла bal. dbf |
 |
Рис. 7.27. Первый расчетный период в документе НачПериода_2 № 1 Замечания:
1. Первый расчетный период задается при создании ЖЗ в поле Дата отсчета (см. рис. 7.19).
2. Не исключено, что для изменения кодировки записей DBF-файла, вам придется прибегнуть к встроенным функциям OemToAnsi и AnsiToOem, приведенным в табл. 2.8. |
7.4.7. ОТЧЕТ ПО НАЧАЛЬНОМУ САЛЬДО
Отчеты, как мы уже знаем, сподручнее всего строить на базе запросов. Напишем запрос, осуществляющий выбор из ЖЗ расчетов с заданным типом ВР, и разместим его в модуле обработки Проба. Запрос и сопровождающий его код крайне просты:
// Формирует и выполняет запрос запр функция ВыпЗапр(запр, ВРДляЗапр) далее
процедура ВыводЗапрТЗнач(запр) далее // Выводит запрос в таблицу значений процедура ВыводЗапрСооб(запр) далее // Выводит запрос в окно сообщений
процедура Выполнить()
перем запр, ВРДляЗапр;
ВРДляЗапр = ВидРасчета.НачСальдо_2; запр = СоздатьОбъект("Запрос");
// Передаем функции ВыпЗапр значение ВР для отбора расчетов // Функция ВыпЗапр формирует и выполняет запрос запр // Если запрос выполнен если ВыпЗапр(запр, ВРДляЗапр) = 1 тогда
ВыводЗапрТЗнач(запр); // Выводит запрос в таблицу значений ВыводЗапрСооб(запр); // Выводит запрос в окно сообщений конецЕсли;
конецПроцедуры // Выполнить
функция ВыпЗапр(запр, ВРДляЗапр) // Формирует и выполняет запрос запр перем жз, нтп, текстЗапр; // текстЗапр - текст запроса
жз = СоздатьОбъект("ЖурналРасчетов.Зарплата_2"); нтп = жз.НачалоТекущегоПериода(); текстЗапр ="
| период с нтп по нтп; // Подходящий для Начального сальдо период
// Определяем переменные запроса; они содержат нужные нам данные | сотр = ЖурналРасчетов.Зарплата_2.0бъект;
| ВР = ЖурналРасчетов.Зарплата_2.ВидРасч;
| рез = ЖурналРасчетов.Зарплата_2.Результат;
// Задаем порядок выборки данных
| группировка сотр упорядочить по сотр.Наименование;
// Условие отбора данных | условие (ВР = ВРДляЗапр);";
// Выполняем запрос возврат запр. Выполнить(текстЗапр); конецФункции // ВыпЗапр
процедура ВыводЗапрТЗнач(запр) // Выводит запрос в таблицу значений перем тЗнач;
// Объект тЗнач создаем для промежуточной демонстрации выборки запроса тЗнач = СоздатьОбъект("ТаблицаЗначений");
// Выгружаем для предварительного просмотра все переменные запроса // в таблицу значений тЗнач запр.Выгрузить(тЗнач, 1);
// Просмотр таблицы значений (результатов запроса). Результат см. на рис. 7.28 тЗнач.ВыбратьСтроку(, "Начальное сальдо в таблице значений"); энецПроцедуры // ВыводЗапрТЗнач
выводит запрос в окно сообщений
Результат имеет ту же структуру, что и данные в таблице, приведенной на рис. 7.28 эоцедура ВыводЗапрСооб(запр)
// В этой процедуре еще раз иллюстрируется метод запросов Группировка пока запр.Группировка("сотр") = 1 цикл если запр.ЭтоГруппа("сотр") = 1 тогда
Сообщить("Сотрудники подразделения " + запр.сотр);
иначе
Сообщить(СокрЩзапр.сотр) + СимволТабуляции + запр.ВР + СимволТабуляции + запр.рез); конецЕсли; конецЦикла; // пока конецПроцедуры // ВыводЗапрСооб
 |
Рис. 7.28. Результат запроса о начальном сальдо с группами
Группы (имена родителей) не попадут в запрос, если оператор Группировка дополнить опцией Без групп:
[группировка сотр упорядочить по сотр.Наименование без групп; что приведет к следующему результату: |
 |
Рис. 7.29. Результат запроса о начальном сальдо с группами |
Из рис. 7.28 и 7.29 видно, что элементы-родители справочника Сотрудники_2 являются в запросе группами и метод запр.ЭтоГруппа("сотр") вернет для них единицу. Для иных записей этот метод вернет нуль.
Первая строка таблицы значений отображает начало выборки. Строка содержит пустое значение переменной запроса сотр. Первое же употребление метода
запр.Группировка("сотр");
приведет к перемещению позиции выборки на ее первую, содержащую непустое значение переменной сотр запись.
Если в текст запроса добавить переменную род, содержащую родителя объекта:
| род = ЖурналРасчетов.Зарплата_2.0бъект.Родитель; то результат запроса не изменится.
Если же вдобавок в тексте запроса разместить и группировку по род, то есть передать методу Выполнить такой текст:
текстЗапр ="
| период с нтп по нтп;
| род = ЖурналРасчетов.Зарплата_2.Объект.Родитель;
| сотр = ЖурналРасчетов.Зарплата_2.Объект;
I BP = ЖурналРасчетов.Зарплата_2.ВидРасч;
| рез = ЖурналРасчетов.Зарплата_2.Результат;
| группировка род;
| группировка сотр упорядочить по сотр.Наименование;
| условие (ВР = ВРДляЗапр);";
то в таблице значений мы увидим дополнительные строки, в которых переменная запроса сотр имеет пустое значение (рис. 7.30).
 |
Рис. 7.30. Запрос с двумя группами |
Эти строки, кроме первой, начинают группы род. Первая строка - это начало выборки. В ней и род и сотр имеют пустые значения.
При двойной группировке, чтобы получить доступ к данным запроса более низкого уровня, необходимо прежде выбрать вышестоящие группы. Поэтому придется изменить код процедуры ВыводЗапрСооб на следующий:
// Выводит запрос в окно сообщений для случая двойной группировки процедура ВыводЗапрСооб(запр)
// В этой процедуре еще раз иллюстрируется метод запросов Группировка пока запр.Группировка("род") = 1 цикл
Сообщить("Сотрудники подразделения " + запр.род); пока запр.Группировка("сотр") = 1 цикл если запр.ЭтоГруппа("сотр") = 0 тогда
Сообщить(СокрП(запр.сотр) + Символ Табуляции + запр.ВР + СимволТабуляции + запр.рез); конецЕсли;
конецЦикла; // пока запр.Группировка("сотр") = 1 конецЦикла; // пока запр.Группировка("род") =1 конецПроцедуры // ВыводЗапрСооб
Результат соответствует рис. 7.28: |
Сотрудники подразделения 01 Цех Сотрудники подразделения 01/1 Агальцов Юрий Алексеевич |
Начальное сальдо |
1.7 |
Добрецов Борис Юрьевич |
Начальное сальдо |
0.1 |
Сотрудники подразделения 01/2 Ьараненков Иван Ильич |
Начальное сальдо |
0.3 |
|
Сравнение двух запросов показывает, что при запросах к ЖЗ для вывода сотрудников с разбивкой по цехам нет необходимости вводить в текст запроса переменную род и устраивать вторую группу. Все необходимые данные даст группировка по переменной запроса сотр.
7.5. КАЛЕНДАРИ И ПРАЗДНИКИ
Наша задача - употребить календари 1С для вычисления общего числа рабочих дней и часов. Учет рабочего времени осуществляется по табелю, который мы оформим как самостоятельный документ 1С.
7.5.1. СОЗДАНИЕ КАЛЕНДАРЯ
Пусть на нашем виртуальном предприятии имеются служащие и рабочие. Создадим для этих категорий свои календари. Войдем в конфигурацию, откроем подменю Календарь и разместим в нем календари Служащие_2 и Рабочие_2 (рис. 7.31).
 |
Рис. 7.31. Новые календари системы |
Свойства календарей определим в соответствии с рис. 7.32. |
 |
а б
Рис. 7.32. Рабочая неделя: а - календаря Служащие_2; б - календаря Рабочие_2
Добавим в меню интерфейса Ученик колонку Календари и табель и определим в ней указанные на рис. 7.33 пункты.
Б 1=3 Календари и табель 0 Календари і 0 Праздники 0 Табель
Рис. 7.33. Новая колонка меню интерфейса Ученик
С новыми пунктами Календари и Праздники свяжем приведенные на рис. 7.34 название, объект и команды.

а б
Рис. 7.34. Свойства пунктов меню: а - Календари; б - Праздники
Объект и команду для пункта Табель зададим несколько позже - после создания документа Табель.
Сохраним изменения конфигурации. Загрузим 1 С: Предприятие. Откроем прежде таблицу для ввода праздников и внесем в нее праздники текущего года, проставив в столбце Значение нулевую продолжительность рабочего дня (рис. 7.35).
 |
Рис. 7.35. Два праздника |
Откроем далее последовательно календари Служащие_2 и Рабочие_2 и выполним их автоматическое заполнение с включенным флажком Учитывать праздники (рис. 7.36).
 |
Рис. 7.36. Календарь Служащие_2 в ноябре 2001 г. |
В поле Значение по текущей дате (рис. 7.36) заполненного календаря отображается число часов, взятое из определенного в конфигурации и изображенного на рис. 7.32, а календаря Сотрудники_2. Для праздничных дней календарь использует данные приведенной на рис. 7.35 таблицы.
Замечание. И календари и праздники хранятся в файле CL.DBF информационной базы.
7.5.2. ПРИМЕНЕНИЕ КАЛЕНДАРЕЙ И ПРАЗНИКОВ
7.5.2.1. ДОСТУП К КАЛЕНДАРЯМ И ПРАЗДНИКАМ
Объекты типа Календарь присутствуют в конфигурации и доступны непосредственно по именам (идентификаторам), которые можно использовать с методами для календарей и чтения их атрибутов.
Пример. Методом Часов вычисляется число рабочих часов в ноябре 2001 г. по календарю Служащие_2.
всегоЧасов = Календари.Служащие_2.Часов('01.11.200Г, КонМесяца('01.11.2001')); Сообщить(всегоЧасов); //Напечатает 167
Тот же результат метод предоставит, будучи употребленным с объектом типа Календарь, возвращаемым функцией СоздатьОбъект:
кален = СоздатьОбъект(''Календарь.Служащие_2''); всегоЧасов = кален.Часов('01.11.2001', КонМесяца('01.11.2001'));
Сообщить(всегоЧасов); // Напечатает 167
Еще один вариант применения методов календарей, например метода Часов, - это использование в составе префикса метода ПолучитьАтрибут:
всегоЧасов = Календари. ПолучитьАтрибут(''Служащие_2'').Часов('01.11.2001',
КонМесяца('01.11.2001'));
Сообщить(всегоЧасов); //Напечатает 167
Переменные типа Праздники относятся к внешним объектам и создаются, как и иные внешние объекты, например таблицы значений, функцией СоздатьОбъект. Имя переменной используется в качестве префикса методов и атрибутов объекта типа Праздники.
Пример. Печатаются праздники текущего года.
процедура Выполнить()
перем празд, нг, кг, флаг;
ОчиститьОкноСообщений();
нг = НачГода(ТекущаяДата()); // Начало и конец текущего года
кг = КонГода(ТекущаяДата()); праздн = СоздатьОбъект("Праздники");
// Перемещаемся на первую запись (дату) выборки флаг = праздн.ВыбратьДаты(нг, кг); если флаг = 1 тогда
пока праздн.СледующаяДата() = 1 цикл
Сообщить("" + праздн.Дата + " - это праздник");
// или Сообщить("" + праздн.ПолучитьАтрибут("Дата") + " - это праздник"); конецЦикла; // пока иначе
Сообщить("В текущем году нет праздников."); конецЕсли;
конецПроцедуры // Выполнить
Результат (соответствует рис. 7.35):
07.11.01 - это праздник
12.12.01 - это праздник
7.5.2.2. А ТРИБУТЫ КАЛЕНДАРЕЙ И ПРАЗДНИКОВ
Календари имеют следующие атрибуты:
- <имя капендаря>; имеет тип Календарь и возвращается методом ПолучитьАтрибут;
- Дата; имеет тип Дата, читается непосредственно по имени или методом ПолучитьАт-
рибут;
- Значение; имеет числовой тип.
Пример. Печатаются нерабочие даты текущего месяца (с нулевой продолжительностью рабочего дня) календаря Служащие_2.
процедура Выполнить()
перем кален, нм, км, нерДни;
ОчиститьОкноСообщенийО;
нм = НачМесяца(ТекущаяДата()); // Начало и конец текущего месяца
км = КонМесяца(ТекущаяДата());
попытка
// Создаем объект типа Календарь. Для этого у нас имеется 3 возможности кален = Капендари.ПолучитьАlрибут("Служащие_2");
// или кален = Календари.Служащие_2;
// или кален = СоздатьОбъект("Календарь.Служащие_2"); исключение
Предупреждение("Нет такого календаря."); возврат; конецПопытки; нерДни = "";
// Перемещаемся на первую запись (дату) выборки
кален.ВыбратьДаты(нм, км);
пока кален.СледующаяДата() = 1 никл
если кален. Значение = 0 тогда // Если нерабочий день нерДни = нерДни + Строка(кален.Дата) + ";";
// или нерДни = нерДни + Строка(кален.ПолучигьАірибут("Даіа")) + ";"; конецЕсли; конецЦикла; // пока если СтрДлина^ерДни) = 0 тогда
Сообщить("В текущем месяце все дни рабочие"); иначе
// Заменяем в строке нерДни последнюю точку с запятой на точку нерДни = Лев(нерДни, СтрДлина(нерДни) - 2) + ".";
Сообщшь("Нерабочие дни текущего месяца: " + нерДни); конецЕсли;
конецПроцедуры // Выполнить Результат:
Нерабочие дни текущего месяца: 02.12.01; 09.12.01; 12.12.01; 16.12.01; 23.12.01; 30.12.01.
Праздники имеют два атрибута:
• Дата; имеет тип Дата;
• Значение; имеет числовой тип.
Замечание. Атрибуты календарей и праздников Дата и Значение читаются непосредственно по имени или методом ПолучитьАтрибут; изменяются методом Устано-витьЗначение.
7.5.2.3. МЕТОДЫ КАЛЕНДАРЕЙ И ПРАЗДНИКОВ
Сведены в табл. 7.8, в которой первоначально следуют общие методы рассматриваемых объектов, а далее их специфические методы.
Методы календарей и праздников
Общие методы календарей и праздников |
знач = кален|праздн.Получить
Атрибут("Дата"|"Значение"); |
Возвращает значение атрибута Дата или Значение в текущей записи объекта. Возможно прямое обращение к атрибуту, например дт = кален.Дата; часы = праздн.Значение; |
кален|праздн.УстановитьАтрибут ("Дата"|"3начение", знач); |
Изменяет значение атрибута Дата или Значение в текущей записи объекта на величину знач |
флаг = кален|праздн.ВыбратьДаты (датаНачала, датаКонца); |
Открывает выборку записей объекта, расположенных между датами датаНачала и датаКонца, перемещая его позицию на первую запись выборки.
Вернет 1, если в выборке есть хотя бы один элемент, или 0, если выборка пуста |
флаг = кален|праздн. Следующая Дата(); |
Выбирает текущую запись и перемещает позицию выборки на следующую запись. Вернет 1, если запись выбрана, или 0, если вся выборка исчерпана |
|
Методы календарей |
кален = Календари.ПолучитьАтрибут (идент); |
Возвращает объект типа Календари с разновидностью типа идент, где идент - строка, содержащая идентификатор календаря, например "Служа-щие_2". Возникнет завершающая ошибка, если идент содержит несуществующий идентификатор |
идент = кален.Вид(); |
Вернет строку, содержащую идентификатор календаря кален. Если, например, в справочнике сСотр_2 есть реквизит Календарь типа Календари, то идентификатор календаря выбранного сотрудника вернет вызов
идент = сСотр_2.Календарь.Вид(); |
флаг = кален.Выбран(); |
Вернет 1, если календарь выбран, или О-в противном случае. Для справочника сСотр_2, в котором есть реквизит Календарь типа Календари, для текущей записи признак выбран календарь или нет вернет вызов
флаг = сСотр_2. Календарь. Выбран(); |
|
Метод |
Описание |
числоРабДней = кален. Дней
(датаНачала, датаКонца); |
Вернет число дней с ненулевой величиной атрибута Значение в календаре кален, расположенных между датами датаНачала и датаКонца. Выдаст сообщение "Неверные даты", если датаКонца < датаНачала |
числоРабЧасов = кален.Часов
{датаНачала, датаКонца); |
Вернет сумму значений атрибута Значение календаря кален для записей, расположенных между датами датаНачала и датаКонца. Выдаст сообщение "Неверные даты", если датаКонца < датаНачала |
флаг = кален. Автозаполнение
(датаНачала, датаКонца); |
Заполняет календарь кален в заданном параметрами датаНачала и датаКонца временном интервале, используя определенные в конфигурации для этого календаря данные о продолжительности рабочей недели (разд. 7.5.1). При заполнении учитываются занесенные в базу данных праздники (разд. 7.5.1, рис. 7.35), если перед вызовом метода употреблен метод УчитыватьПраздники(1). Вернет 1, если заполнение произведено, или 0 - при неудаче |
праздСтар =
кален.УчитыватьПраздники
(праздНов); |
Задает, если числовой параметр праздНов = 1, режим учета занесенные в базу данных праздников (разд. 7.5.1, рис. 7.35) при выполнении метода Автозаполнение для календаря кален. Если праздНов = 0, то праздники при автозаполнении календаря кален не учитываются. Если метод для календаря кален не вызывался, то при его автозаполнении праздники учитываются. Возвращает текущую установку режима учета праздников |
дат = кален. ПолучитьДату (датаНачала, числоРабДней); |
Возвращает дату, отстоящую от даты, заданной параметром датаНачала, на число рабочих дней, заданное параметром числоРабДней. День считается рабочим, если атрибут Значение соответствующей записи календаря кален не равен нулю. Параметр числоРабДней не должен быть меньше нуля |
Методы праздников |
праздн.Новый(датаЛраздн,
числоРабЧасов); |
Добавляет в базу данных (файл CL.DBF) новый праздник. Параметр датаПраздн задает дату праздника, а числоРабЧасов - число рабочих часов в праздник. Параметр числоРабЧасов неотрицателен и меньше 100 |
праздн.Удалить(датаЛраздн); |
Удаляет из базы данных праздник, приходящийся на дату датаПраздн. Если записи о таком празднике нет, то метод никаких изменений не производит |
|
Замечание. Имена кален и праздн, употребленные в табл. 7.8 перед названиями методов, могут быть произвольными.
Пример. В текущем году праздник 12 декабря переносится на 14 декабря. Поскольку перенос затрагивает все календари, то для их модификации используем объект Метаданные и методы календарей Автозаполнение и УчитыватьПраздники.
процедура Выполнить()
перем празд, тГод, пСтар, пНов, нм, км, всегоКален, ин, идеи, кален; |
ОчиститьОкноСообщений(); тГод = ДатаГод(ТекущаяДата()); |
// |
Текущий год, например 2001 |
пСтар = Дата("12.12." +тГод); |
//Дата |
старого праздника |
пНов = Дата("14.12." + тГод); |
// |
Дата нового праздника |
праздн = СоздатьОбъект("Праздники"); |
|
// Перенос праздника праздн.Удалить(пСтар); праздн.Новый(пНов, 0); |
// |
Число рабочих часов равно нулю |
нм = Дата("01.12." + тГод); |
// |
Начало и конец декабря |
км = КонМесяца(нм); |
|
|
|
// Всего календарей в конфигурации (в метаданных) всегоКален = Метаданные.КалендарьО; для ин = 1 по всегоКален цикл
// Атрибут очередного календаря
идеи = Метаданные.Календарь(ин).Идентификатор;
// Календарь как объект
кален = Календари.ПолучитьАтрибут(иден);
// Учитываем при автозаполнении праздники кален.У читыватьПраздники(1); кален.Автозаполнение(нм, км); конецЦикла; // для Предупреждение("Готово."); конецПроцедуры // Выполнить
Замечание. Функция ОткрытьФорму непригодна для активизации формы списка объекта Праздники (см. рис. 7.35) и отображения календарей.
7.5.2.4. УСОВЕРШЕНСТВОВАНИЕ СПРАВОЧНИКА СОТРУДНИКИ_2
Если стоит задача автоматизировать учет рабочего времени сотрудника, то его следует связать с подходящим календарем. Такие календари у нас уже есть (см. рис. 7.32). Если нет отклонений, то рабочее время сотрудника полностью определяется его календарем. В противном случае необходимо использовать табель.
Поскольку учет рабочего времени - задача трудоемкая, дополним справочник Сот-рудники_2 реквизитом Календарь (рис. 7.37, а), задав ему свойства в соответствии с рис. 7.37, б.
 |
б |
Идентификатор:
?ино«*и:
^«¦еаентармй:
Іш значения | «Календарь»
РакаИЭИГЫ
О клан
Образование
ПрикаэОклаа
ПршаэЛрием
Рис. 7.37. Новый реквизит Календарь и его свойства: а -реквизит; б - свойства
Внесем изменения и в диалог формы элемента, приведя его в соответствие с рис. 7.38. (О порядке выполнения изменений см. разд. 5.7.)
 |
Рис. 7.38. Обновленный диалог формы элемента справочника Сотрудники_2 |
Календарь - обязательный для заполнения реквизит справочника, поэтому модуль формы элемента, его предопределенную процедуру ПриЗаписи (разд. 5.3.4.2), дополним следующей проверкой:
если Календарь.Выбран() = 0 тогда
Прелупреждение("3адайге Календарь");
СтатусВозврата(0); // Данные не записываются; форма не закрывается // Перемешаемся на элемент диалога Календарь Активизировать("Календарь", 0); возврат; конецЕсли;
Формы списка (основную и для ввода) справочника Сотрудники_2 оставим без изменений.
Ускорим ввод начальных значений нового реквизита, запустив в обработке Проба программу, назначающую работникам с высшим и неоконченным высшим образованием календарь Служащие_2, а всем прочим - Рабочие_2.
процедура Выполнить() перем сСотр_2;
ОчистшъОкноСообщений();
сСотр_2 = СоздагъОбъект("Справочник.Сотрудники_2");
сСотр_2.ВыбратьЭлементы();
пока сСотр_2.ПолучигьЭлемент() = 1 цикл
если (сСотр_2.0бразование.Наименование = "Высшее") или
(сСотр_2.0бразование.Наименование = "Неоконченное высшее") тогда сСотр_2.Календарь = Календари.Служащие_2; иначе
сСотр_2. Календарь = Календари.Рабочие_2; конецЕсли;
// Не забываем сохранить изменения сСотр_2.3аписать(); конецЦикла; // пока Предупреждение('Тотово.");
// Просмотр результата. Для просмотра необходимо в открытой форме списка // войти в режим редактирования элемента ОткрытьФормуС'Справочник. Сотрудники_2"); конецПроцедуры // Выполнить
7.6. ТАБЕЛЬ
7.6.1. ПОРЯДОК ЗАПОЛНЕНИЯ ТАБЕЛЯ
На предприятии табель - это документ, учитывающий отработанное время. Изначально табель сотрудника может формироваться на бумажном носителе. Далее данные переносятся в документ 1С, которому мы также дадим имя Табель. В дальнейшем, употребляя это имя, мы будем иметь в виду документ 1С.
Табель играет важную роль в задаче начисления зарплаты. В частности, все документы, вводящие начисления (удержания) и зависящие от проработанного времени, должны оформляться на основании табеля.
Алгоритм учета рабочего времени за месяц (для одного сотрудника):
1. Начало.
2. Выбрать сотрудника.
3. Заполнить, используя календарь сотрудника, табель
4. Внести при необходимости в табель коррективы.
5. Вычислить суммарное отработанное время. Результат разместить в столбце Всего часов.
6. Провести документ. Результатом его проведения является добавление в ЖЗ расчетов с Оклад_2, НДФЛ_2 и ВБанк_2.
Расчет регистрируется в текущем расчетном периоде.
7. Конец.
Данный алгоритм воспроизводится для каждого сотрудника предприятия, занесенного в табель, то есть в общем случае один табель порождает несколько расчетов. Предоставим пользователю следующие возможности по заполнению табеля:
1. Добавление в табель (его табличную часть) по одному сотруднику. Производится при помощи метода модуля формы ОткрытьПодбор и предопределенной процедуры модуля формы ОбработкаПодбора; существующие записи сохраняются.
2. Заполнение табличной части для сотрудников выбранного подразделения; существующие записи удаляются.
3. Занесение в табличную часть всех сотрудников предприятия; существующие записи удаляются.
В каждом из режимов табличная часть после перенесения в нее сотрудника автоматически заполняется данными его календаря.
Также предусмотрим в интерфейсе документа удаление одной выбранной записи табличной части или всех ее записей.
При каждом сохранении документа будем выполнять его перепроведение. Позаботимся о том, чтобы в документ один и тот же сотрудник не попал дважды. Однако если по какой-либо причине данные о сотруднике введены дважды в разные табели, то проведение любого из этих табелей должно приводить к обновлению соответствующих ему расчетов в ЖЗ.
Замечание. Имеющийся в 1С документ ВводОтработанногоВремени весьма сложен, так как рассчитан на многие случаи жизни. Внушителен и объем кода, сопровождающий этот документ. Так, модуль формы документа содержит около 600 строк плотного кода. Поскольку наш алгоритм ввода рабочего времени и последующей проводки документа гораздо проще, то имеет смысл взамен существующего в 1С документа создать и использовать свой, более простой и эффективный. Так и поступим.
7.6.2. РЕКВИЗИТЫ И ДИАЛОГ ТАБЕЛЯ
Перечисленные требования к табелю позволяют определиться относительно состава диалога документа и его реквизитов (табл. 7.9).
Таблица 7.9
Реквизиты документа Табель
Тип (разновидность типа) /Длина.Точность
Реквизиты
Описание
Способ заполнения табличной части документа. Используется как идентификатор радиокнопок диалога формы списка документа. Если кто = 1, то подбор выполняется по одному сотруднику; если кто = 2, то в табличную часть документа заносятся сотрудники выбранного подразделения, и если кто = 3, в табличную часть заносятся сотрудники всего предприятия. Используется при открытии проведенного документа
Числовой/ 1.0
кто
Номер выбранной строки в списке подразделе • ний сПодр. Используется при открытии проведенного документа для верного позиционирования списка подразделений
текСтрока
Числовой/3.0
Дата документа (реквизит задан по умолчанию)
Дата
ДатаДок
Номер документа (реквизит задан по умолчанию)
НомерДок
Числовой /5.0
Сотрудник
Сотрудник, табель которого вводится
Справочник. Сотрудники 2
ч1-ч31
ч, - число фактически отработанных часов в день й=1.2. ...31
Числовой/4.1 |
 |
Создавая документ, попутно, пользуясь услугами конструктора (рис. 7.39), добавим в конфигурацию журнал Табель, в котором и будут размещаться формируемые пользователями документы учета отработанного времени.
 |
Рис. 7.39. Новый журнал для документа Табель |
Задавая свойства документа Табель (рис. 7.40), не забудем активизировать флажок Расчет.
 |
Рис. 7.40. Свойства и реквизиты документа Табель |
Диалог формы табеля оформим, следуя рис. 7.41. |
 |
Рис. 7.41. Диалог формы табеля |
Замечания:
1. Чтобы просмотреть неотображенные столбцы табличной части формы, следует воспользоваться стрелками горизонтальной полосы прокрутки.
2. Элемент диалога сПодр является списком значений. Он заполняется в предопределенной процедуре ПриОткрытии, которая, используя справочник Сотрудики_2, заносит в сПодр список подразделений предприятия.
Нажав для проверки диалога Ctrl+R, обнаружим некоторое несоответствие в расположении граф 1-31, а также дополнительную неименованную графу 32 (рис. 7.42).
 |
Рис. 7.42. Расположение граф 1-32 |
Графа 32 введена с целью симметричного размещения столбцов 1-16 и 17-31, что и получилось на рис. 7.42. Для достижения такого результата необходимо ячейки 1-32 сделать одной ширины. К сожалению, простого средства выравнивания ширины столбцов табличной части в 1С нет.
С 32-й графой связана формула "X", обеспечивающая вывод этой буквы в ячейки столбца. Добавление столбца таблицы, напомним, осуществляется при помощи иконки Г, расположенной на панели инструментов Элементы диалога.
Чтобы разместить столбцы 17-32 под столбцами 1-16, столбец 1 получил свойство Новая колонка (рис. 7.43, а), а последующие столбцы - свойство В той же колонке (рис. 7.43, б).

а 6
Рис. 7.43. Положение полей ввода ч1-ч32: положение поля ввода ч1; положение полей ввода ч2-ч32
Соответствие между заголовками столбцов табличной части документа и их идентификаторами (реквизитами документа) отображено в табл. 7.10.
Таблица 7.10
Заголовками столбцов табличной части документа и их идентификаторы |
Заголовок столбца |
Идентификатор |
Примечание |
Сотрудник |
Сотрудник |
Ячейки столбца доступны только для чтения; заполняются в результате работы процедуры Заполнить |
Всего |
всегоЧасов |
Ячейки столбца доступны только для
?^ЗІ
чтения; всегда всего Часов = / Ч; |
1,2.....31 |
чі, ч2.....чЗІ |
Доступны как для чтения, так и для редактирования; заполняются в результате работы процедуры Заполнить |
|
Замечание. Ввод одного сотрудника, так же как и группы сотрудников, осуществляется при нажатии на кнопку Заполнить. То есть мы отказались от выбора сотрудника непосредственно в табличной части, задав свойства ячеек столбца Сотрудник в соответствии с рис. 7.44. |
 |
Рис. 7.44. Свойства ячеек столбца Сотрудник |
Это, несомненно, делает диалог более дружественным. Действительно, каждый выббр сотрудника приводит к заполнению реквизитов ч1-ч31. При этом случайный выбор сотрудника в строке, содержащей ранее введенные данные, приведет к обновлению значений этих реквизитов. Если же они содержали ручную правку, то ее результаты будут этим обновлением уничтожены. Теперь же, когда ячейки столбца недоступны, такой ошибки быть не может.
Группа радиокнопок, имеющая название Режим заполнения, формируется следующим образом:
1. Добавляется радиокнопка с заголовком Сотрудник, ей присваивается идентификатор, например кто, который и будет служить идентификатором группы. На закладке дополнительно этой радиокнопке задается формула Проследить() и свойство Первый в группе.
2. Добавляются радиокнопки с заголовками Цех и Все. Никаких дополнительных свойств для них не задается.
3. Кнопки обводятся рамкой группы, которой присваивается заголовок Режим заполнения.
После таких действий переменная диалога кто принимает значение:
• 1, если выбрана радиокнопка Сотрудник; и в этом случае табель заполняется в результате подбора сотрудников;
• 2, если выбрана радиокнопка Цех; табель заполняется на сотрудников подразделения, выбранного в поле сПодр;
• 3, если выбрана радиокнопка Все; в табель заносятся все сотрудники предприятия. Кроме задания режима заполнения, радиокнопки управляют доступностью элементов диалога сПодр и Заполнить.
С текстом заголовка свяжем следующую формулу:
"Ввод отработанного времени за "+ Формат(ЦащЦок, "ДММММГ ПТ") + ", " +
?(кто = 2, сПодр.ПолучитъЗначение(сПодр.ТекущаяСтрокаО),
?(кто = 3, "все предприятие", "")) + "."
Тогда, если, например, ДатаДок - это '12.12.200Г и выбран второй цех, в заголовке появится сообщение, в котором благодаря встроенной функции Формат дата '12.12.2001' преобразована в текст Декабрь 2001 г.:
Ввод отработанного времени за Декабрь 2001 г., 02 Цех
Формулы (процедуры), с которыми связываются поля диалога, перечислим в табл. 7.11, в которой в графе Элементы диалога курсивом приводятся идентификаторы элементов диалога, а прямым шрифтом - их имена (идентификаторы не заданы). Имена, соответствующие идентификаторам, легко узнаваемы.
Таблица 7.11
Элементы диалога документа Табель и их формулы |
 |
Проследить()
Управляет доступностью элемента диалога сПодр. Если кто = 1 (активна радиокнопка Сотрудник) или кто = 3, то элемент сПодр недоступен; если кто = 2, то доступен
кто |
сПодр
ОтобразитьСПодр()
Отображает имя выбранного в списке сПодр подразделения и запоминает значение текущей строки списка текСтрока
Заполнить
Заполнить( )
Заполняет табличную часть для сотрудников выбранного подразделения, если кто = 2, или всего предприятия, если кто = 3. Открывает форму подбора сотрудников, если кто = 1
Удаляет текущую строку табличной части. Удалению предшествует запрос о необходимости удаления. Доступен, если в табличной части есть хотя бы одна запись
Удалить
УдалитьЗап(1)
Очистить
УдалитьЗап(2)
Удаляет все строки табличной части. Удалению предшествует запрос о необходимости удаления. Доступен, если в табличной части есть хотя бы одна запись
Распечатывает, если не пуста табличная часть, табель по форме Т-13, которая предоставляется 1С
Т13()
ФормаТ-13
Действия
гдДействия(, сДейст)
Открывает документ в журнале (если он в нем есть). Переменная модуля сДейст (список значений) заполняется в процедуре ПриОткрытии формы документа значением "Открыть в журнале". Процедура глДействия расположена в глобальном модуле и поставляется с 1С
Выполняет проведение (перепроведение) документа Табель, то есть заносит в ЖЗ расчеты с ВР Оклад_2, НДФЛ_2 и ВБанк_2
#Провести
Провести
ОК
#3аписать Провести Закрыть
Проводит (перепроводит) и сохраняет документ в журнале документов Табель
Закрыть
#3акрыть
Закрывает документ
Теперь у нас есть достаточно информации, чтобы перейти к созданию кода модуля формы документа и самого документа. Напомним, что в модуле документа можно разместить его предопределенные процедуры ОбработкаПроведения и/или Обрабо тка-УдаленияПроведения.
7.6.3. МОДИФИКАЦИЯ МЕНЮ ИНТЕРФЕЙСА УЧЕНИК
Для доступа к созданным журналам и документам модифицируем отдельные колонки меню интерфейса Ученик (рис. 7.45). Для вновь введенных в колонку Журналы документов пунктов (Расчеты и Табель) укажем соответственно объекты Жур-нал.Расчеты и Журнал.Табель.
Hjj Документы |
^ Журналы документов |
^ Журналы расчетов |
^ Календари |
И Приказ о приеме |
;--0 Кадровые приказы |
0 Журнал зарплаты_2 |
г- 0 Календари |
S Изменение оклада S Табель |
!— 0 Расчеты -0 Табель |
|
|- 0 Праздники |
У Премия |
|
|
|
|
Рис. 7.45. Модифицированные колонки меню интерфейса Ученик |
7.6.4. МОДУЛЬ ФОРМЫ СПИСКА ДОКУМЕНТА
Содержит, кроме названных в табл. 7.11, процедуру ПриОткрытии. перем часы[31], сДейст; // часы - массив часов по календарю
процедура Проследить() далее
процедура Заполнить() далее
процедура ОбработкаПодбора(значен, конт) далее
процедура ОдинСотрудник() далее
процедура Ч131 () далее
процедура Всего () далее
процедура УдалитьЗап(флаг) далее
// Формирует список подразделений сПодр и устанавливает начальные значения // переменных диалога процедура ПриОткрытии() перем сСотр_2, дост;
сСотр_2 = СоздатьОбъект("Справочник.Сотрудники_2");
// Формируем, анализируя справочник Сотрудники_2, список подразделгний // Задаем выбор элементов справочника в порядке возрастания их кодов сСотр_2 .ПорядокКодов(); сСотр_2.ВыбратьЭлементы( ); пока сСотр_2.ПолучитьЭлемент() = 1 цикл если сСотр_2.ЭтоГруппа() = 1 тогда
Если документ не проведен Табель на сотрудников выбранного подразделения Позиционируемся на цехе 01 в списке сПодр Документ проведен
Правильно позиционируем список значений сПодр
сПодр.ДобавитьЗначение(сСотр_2.ТекущийЭлемент(), сСотр_2.Наименование); конецЕсли; конецЦикла; // пока если Проведен()= 0 тогда //
сПодр.ТекущаяСтрока(текСтрока); конецЕсли; конецЕсли;
Проследить();
// дост = 1, если в табличной части есть записи. Переменная используется // для управления доступностью элементов диалога формы списка документа дост = ?(КоличествоСтрок() = 0, 0, 1); формаУдалтъДоступность(цост); форма. Очистить.Доступность(цост);
форма.ПанельИнструментов(О); // Отключаем панель инструментов форма.Заголовок("Табель");
// Для кнопки Действия (рис. 7.40) сДейст = СоздатьОбъект("СписокЗначений"); сДейстДобавитьЗначение("Открьнь в журнале"); конецПроцедуры // ПриОткрытии
// Управляет доступностью элемента диалога сПодр процедура Проследить()
если (кто = 1) или (кто = 3) тогда // Табель на отобранных или всех сотрудников форма.СПодр.Доступность(О); иначе // кто = 2
форма.СПодр.Доступность(І); конецЕсли;
конецПроцедуры // Проследить
процедура ОтобразитьСПодр() // Формула элемента диалога сПодр текСтрока = сПодр.ТекущаяСтрока(); сПодр.ПолучитьЗначение(текСтрока); конецПроцедуры // ОтобразитьСПодр
процедура ОдинСотрудник() // Заполняет массив часы для одного сотрудник перем ин, кален;
для ин - 1 по 31 цикл // Инициализация массива часов
часы[ин] = 0; конецЦикла; // для кален = СотрудникКалендарь; если кален.Выбран() = 1 тогда
кален.ВыбратьДаты(НачМесяца(ДатаЦок), КонМесяца(ДатаДок)); ин = 0;
// Заносим в массив часы данные календаря сотрудника пока кален.СледующаяДата() = 1 цикл ин = ин+ 1;
часы[ин] = кален.Значение; конецЦикла; // пока конецЕсли;
конецПроцедуры // ОдинСотрудник
// Определяем значения реквизитов документа ч 1 - чЗ 1 // Далее эти значения могут быть отредактированы процедура Ч131()
ч1 = часы[1]; ч2 = часы[2]; чЗ = часы[3]; ч4 = часы[4]; ч5 = часы[5]; чб = часы[6]; ч7 = часы[7]; ч8 = часы[8]; ч9 = часы[9]; ч10 = часы[10]; ч11 = часы[11]; ч12 = часы[12]; ч13 = часы[13]; ч14 = часы[14]; ч15 = часы[15];
ч16 = часы[16]; ч17 - часы[17]; ч18 = часы[18] ч19 = часы[19]; ч20 = часы[20]; ч21 = часы[21] ч22 = часы[22]; ч23 = часы[23]; ч24 = часы[24] ч25 = часы[25]; ч26 = часы[26]; 427 = 4асы[27]
428 = 4асы[28]; 429 = часы[29]; 430 = часы[30]; 431 = 4асы[31]; конецПроцедуры // Ч131
процедура Всего() // Возвращает общее 4исло отработанных 4асов
всегоЧасов = ч1 + ч2 + ч3 + ч4 + ч5 + ч6 + ч7 + ч8 + ч9 + ч10 + ч11 + ч12 + ч13 + ч14 + ч15 + ч16 + ч17+ ч18+ч19 + ч20 + ч21 + ч22 + ч23 + ч24 + ч25 + ч26 + ч27 + ч28 + ч29 + ч30 + ч31; конецПроцедуры // Всего
// Заполняет табличную часть документа Табель для одного или группы сотрудников процедура Заполнить() перем подр;
// Удаляем, если табличная часть заполняется для подразделение или всего предприятие, // ее строки, но только с согласия пользователя если (кто > 1) и (КоличествоСтрок() > 0) тогда
если Вопрос("Удалить имеющиеся строки?", "Да+Нет") = "Да" тогда
УдалитьСтроки(); // 04ищаем табли4ную 4асть документа
иначе
возврат; конецЕсли; конецЕсли; если кто = 1 тогда
// Указываем явно имя основной формы списка для метода ОткрытьПодбор // Задаем режим множественного выбора
// Добавляем в табличную часть в результате каждого выбора в открытой форме // данные одного сотрудника. Собственно добавление осуществляет // предопределенная процедура модуля формы ОбработкаПодбора ОткрытьПодбор("Справо4ник.Сотрудники_2", "ФормаСписка",, 1); ина4еЕсли кто >= 2 тогда // Подразделение или все предприятие
сСотр_2 = СоздатьОбъект("Справочник.Сотрудники_2");
// Заносим в табличную часть данные о сотрудниках выбранного подразделения подр если кто = 2 тогда // Подразделение
подр = сПодр.ПолучитьЗначение(сПодр.ТекущаяСтрока()); сСотр_2.ИспользоватьРодителя(подр); конецЕсли;
с Сотр_2 .ВыбратьЭлементы();
пока сСотр_2.ПолучитьЭлемент() = 1 цикл
если сСотр_2.ЭтоГруппа() = 0 тогда // Только сотрудники
// Используем уже имеющуюся процедуру ОбработкаПодбора,
// выполняющую обработку одного сотрудника ОбработкаПодбора(сСотр_2,""); конецЕсли; конецЦикла; // пока конецЕсли;
если КоличествоСтрок() > 0 тогда форма.Удалить. Доступность(1); форма. Очистить .Доступность(1); конецЕсли;
конецПроцедуры // Заполнить
процедура ОбработкаПодбора(значен, конт)
// Запрещаем, если добавляем по одному сотруднику, выбор того же лица дважды если (кто = 1) и (ВыбратьСтроки( ) = 1) тогда пока ПолучитьСтроку( ) = 1 цикл
если Сотрудник = значен.ТекущийЭлемент( ) тогда Предупреждение("Сотрудник уже выбран."); возврат; конецЕсли; конецЦикла; // пока конецЕсли;
НоваяСтрока(); // Новая строка в табличной части табеля
Сотрудник = значен.ТекущийЭлемент();
ОдинСотрудник(); // Заполняет массив часы для одного сотрудника
// Определяем значения реквизитов документа ч1-чЗ 1 и всегоЧасов
Ч131();
Всего();
// Если есть хотя бы одна запись, то есть что удалять если (кто = 1) и (КоличествоСтрок() = 1) тогда форма.Удалить. Доступность(1); форма.Очистить.Доступность(1); конецЕсли;
конецПроцедуры // ОбработкаПодбора
// Удаляет с согласия пользователя, если флаг = 1, текущую запись табличной // части документа, и, если флаг = 2, все записи процедура УдалитьЗап(флаг) перем вопр;
вопр = "Удалить " + ?(флаг= 1, "одну запись", "все записи") + "?"; если Вопрос(вопр, "Да+Нет") = "Да" тогда если флаг = 1 тогда УдалитьСтроку();
иначе // флаг = 2
УдалитьСтроки(); конецЕсли;
если КоличествоСтрок() = О тогда форма.Удалить.Доступность(О); форма.Очистить.Доступность(О); конецЕсли; конецЕсли;
конецПроцедуры // УдалитьЗап
Результат автоматического заполнения табеля для сотрудников второго цеха приведен на рис. 7.46.
 |
Рис. 7.46. Фрагмент табеля цеха 02 |
7.6.5. МОДУЛЬ ДОКУМЕНТА
Содержит предопределенную процедуру ОбработкаПроведения. Она для каждого сотрудника табличной части заносит в ЖЗ расчеты Оклад_2, НДФЛ2 и ВБанк_2, а также вычисляет результат каждого введенного расчета. Поскольку вводимые расчеты должны обновляться при перепроведении, то метод их ввода - ВвестиРасчет, а не ЗаписатьРасчет. Даты начала и окончания всех расчетов совпадают с датами начала и конца текущего периода ЖЗ. Функция НайтиХозОп возвращает связанную с ВР хозяйственную операцию. Эти связи хранит справочник ХозОпДляВР (разд. 7.3.7). Число отработанных часов вводится только для ВР Оклад_2.
функция НайтиХозОп(хозОп, ВР) далее
процедура ВводРасчВЖЗ(жз, нтп, ктп, хозОп, ВР) далее
процедура ОбработкаПроведения() перем жз, нтп, ктп;
// Объект с разновидностью типа Справочник.ХозОпДляВР перем хозОп;
// Для поиска хозяйственных операций ВР
хозОп = СоздатьОбъект("Справочник.ХозОпДляВР");
жз = СоздатьОбъект("ЖурналРасчетов.Зарплата_2");
нтп = жз.НачалоТекущегоПериодаО;
ктп = жз.КонецТекущегоПериодаО;
ВыбратьСтроки(); // Открываем выборку строк документа
пока ПолучитьСтроку( ) = 1 цикл
// Устанавливаем реквизиты для каждого вводимого ВР // ВР Оклад_2
жз.УстановитьРеквизит("всегоЧасов", всегоЧасов);
ВводРасчВЖЗ(жз, нтп, ктп, хозОп, ВидРасчета.Оклад_2);
// ВР НДФЛ_2
ВводРасчВЖЗ(жз, нтп, ктп, хозОп, ВидРасчета.НДФЛ_2);
// ВР ВБанк_2
ВводРасчВЖЗ(жз, нтп, ктп, хозОп, ВидРасчета.ВБанк_2); конецЦикла; // пока
// Вычисляем результаты введенных расчетов // Выборка записей ЖЗ по документу не дает верного результата // Поэтому используем выбор записей текущего периода по объекту ВыбратьСтроки(); // Открываем выборку строк документа
пока ПолучитьСтроку() = 1 цикл
жз.ВыбратьПериодПоОбъекту(Сотрудник, нтп); пока жз.ПолучитьЗапись() = 1 цикл
если жз.Документ = ТекущийДокументО тогда
// Метод Рассчитать вызывает процедуру ПровестиРасчет соответствующего ВР жз.Рассчитать( ); // или жз.ВыполнитьРасчет
конецЕсли; конецЦикла; // пока конецЦикла; // пока
если Проведен() = 0 тогда // Если документ проводится впервые
// Ограничиваем время показа окна с предупреждением тремя секундами Предупреждение(''Документ проведен.", 3); иначе
ПредупреждениеСДокумент перепроведен.", 3); конецЕсли;
конецПроцедуры // ОбработкаПроведения
// Вводит новые или редактирует имеющиеся в ЖЗ расчеты с заданным ВР процедура ВводРасчВЖЗ(жз, нтп, ктп, хозОп, ВР)
жз.УстановитьРеквизит("строкаДок", НомерСтроки); жз.УстановитьРеквизит("хозОп", НайтиХозОп(хозОп, ВР)); жз.ВвестиРасчет(Сотрудник, ВР, нтп, ктп); конецПроцедуры // ВводРасчВЖЗ
// Возвращает хозяйственную операцию ВР функция НайтиХозОп(хозОп, ВР)
// Ищем простым перебором в справочнике ХозОпДляВР вид расчета ВР
хозОп.ВыбратьЭлементы();
флаг = 0;
пока хозОп.ПолучитьЭлемент() = 1 цикл если хозОп.ВР = ВР тогда флаг = 1; прервать; конецЕсли; конецЦикла; // пока если флаг = 1 тогда
возврат хозОп.хозОп; иначе
возврат ПолучитьПустоеЗначение(хозОп); конецЕсли;
конецФункции // НайтиХозОп
Фрагмент ЖЗ после проведения табеля, например для сотрудников 2-го цеха, показан на рис. 7.47.
|
Сотрудник |
ВР |
Часы |
ІРезчльтаті |
Хоз. on. |
Начало I |
Оконча... |
<h |
Горюнова У льяна |
Начальное салъд |
|
0.50 |
2013000 |
01.12.01 I |
01.1201 |
t] |
Горюнова Ульяна |
Оклад |
1Б5.0 |
3.200.00 |
2013000 |
01.12.01 |
31.12.01 |
|
Горюнова Ульяна |
НДФЛ |
|
|
2017002 |
01.12.01 |
31.12.01 |
ь |
Горюнова Ульяна |
Перечисление в С |
|
2.784.00 |
2300100 |
01.12.01 |
31.12.01 |
|
Рис. 7.47. Документ Табель проведен для сотрудников 2-го цеха |
Замечания:
1. Расчеты одного объекта располагаются в ЖЗ в порядке очередности их исполнения.
2. Чтобы быстро найти в ЖЗ сотрудника, следует переместиться на поле Сотрудник и начать набирать на клавиатуре его фамилию (рис. 7.48).
 |
Рис. 7.48. Локализация сотрудника в форме списка ЖЗ |
[«I
При поиске должна быть выбрана иконка , обеспечивающая отображение всех сотрудников текущего подразделения.
3. Ввод нового документа Табель проще всего выполнить, воспользовавшись кнопкой Ввод расчета, предусмотренной в диалоге формы ЖЗ (см. рис. 7.21).
4. Чтобы открыть документ Табель, породивший текущий расчет, достаточно, находясь в ЖЗ, нажать на правую кнопку мыши и выбрать соответствующий пункт появившегося меню (рис. 7.49).
 |
Рис. 7.49. Открываем документ Табель |
Тот же пункт можно выбрать и из колонки Действия меню интерфейса Ученик.
Команда проведения документа при выполнении перепроведения отслеживает все возможные произошедшие в документе изменения. Так, если в предопределенной процедуре ОбработкаПроведения после проведения документа закомментировать код, вводящий, например, расчеты с ВР ВБанк_2, то соответствующие расчеты исчезнут из ЖЗ в результате перепроведения документа. Если из проведенного документа удалить табель для какого-либо сотрудника, то в результате перепроведения все ранее порожденные документом расчеты, относящиеся к удаленному сотруднику, будут удалены и из ЖЗ и т. д.
Если по какой-либо причине табель на сотрудника заполняется повторно, то его проведение не приведет к появлению в ЖЗ новых расчетов, поскольку расчеты с ВР Оклад_2, НДФЛ_2 и ВБанк_2 созданы как самовытесняющиеся. Однако при этом старые расчеты будут заменены на вновь вводимые, поскольку нами использован метод ВвестиРасчет. Метод ЗаписатьРасчет также вводит расчеты в ЖЗ, но при этом само-вытесняющиеся расчеты остаются в ЖЗ неизмененными.
Если же перепроводится существующий Табель, то методы ВвестиРасчет и Запи-сатьРасчет работают совершенно одинаково.
Результаты введенных документом Табель расчетов оцениваются в процедуре Об-работкаПроведения после ввода расчетов следующим кодом:
// Выполняем расчет всех введенных записей жз.ВыбратьЗаписиПоДокументу(ТекущийДокумент( ));
пока жз.ПолучитьЗапись() = 1 цикл
// Метод Рассчитать вызывает процедуру ПровестиРасчет соответствующего ВР жз.Рассчитать( ); // или жз.ВыполнитьРасчет( );
конецЦикла; // пока
Рассмотрим теперь, как задаются свойства используемых нами ВР, и запишем для них код, возвращающий результат расчета. Прежде, однако, зададим правила перерасчета ВР.
Содержание раздела