From c21328cac8e0528a88f0256509317c9639034aa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9F=D1=80=D0=BE=D1=84=D0=B8-=D0=A1=D0=BE=D1=84=D1=82?= Date: Thu, 9 Jul 2026 08:16:43 +0000 Subject: [PATCH] v3.0.0.19: new algorithm - always find employee sheet, skip headers, start at row 17 --- Configuration.xml | 2 +- .../Forms/Форма/Ext/Form/Module.bsl | 402 +++++++++--------- 2 files changed, 206 insertions(+), 198 deletions(-) diff --git a/Configuration.xml b/Configuration.xml index 4c30b92..837f9e7 100755 --- a/Configuration.xml +++ b/Configuration.xml @@ -56,7 +56,7 @@ Russian ООО "Профи-Софт", код партнера 42575-13, г.Байконур. - 3.0.0.18 + 3.0.0.19 Language.Русский diff --git a/DataProcessors/ЗагрузкаДанныхИзExcel/Forms/Форма/Ext/Form/Module.bsl b/DataProcessors/ЗагрузкаДанныхИзExcel/Forms/Форма/Ext/Form/Module.bsl index 54b7fb0..b07ecf6 100644 --- a/DataProcessors/ЗагрузкаДанныхИзExcel/Forms/Форма/Ext/Form/Module.bsl +++ b/DataProcessors/ЗагрузкаДанныхИзExcel/Forms/Форма/Ext/Form/Module.bsl @@ -24,7 +24,7 @@ Сообщить("Выберите файл!"); Возврат; КонецЕсли; - Состояние("Инициализация загрузки...", 0); + Состояние("Инициализация...", 0); Прогресс = 0; СтатусЗагрузки = "Подготовка..."; ПрочитатьExcelНаКлиенте(); @@ -117,190 +117,177 @@ #Область ЧтениеДанныхСотрудника_Домен +// ============================================================================ +// Чтение данных из листа сотрудника +// ============================================================================ + &НаКлиенте -Функция ПрочитатьДанныеИзЛистаСотрудника(ЛистСотрудника, ФИО) - Строка = Новый Структура; - Строка.Вставить("ФИО", ФИО); - Строка.Вставить("Должность", ПрочитатьЯчейкуСтрока(ЛистСотрудника, 3, 3)); - Строка.Вставить("СчетБК", ПрочитатьЯчейкуСтрока(ЛистСотрудника, 3, 4)); - Строка.Вставить("ВидЗанятости", ПрочитатьЯчейкуСтрока(ЛистСотрудника, 5, 1)); +Функция НайтиЛистСотрудника(Книга, ЛистРасчет, НомерСтроки) + // Способ 1: из формулы в ячейке (xlsm) + Формула = ЛистРасчет.Cells(НомерСтроки, 1).Formula; + Если ЗначениеЗаполнено(Формула) Тогда + ИмяЛиста = ИзвлечьИмяЛистаИзФормулы(Формула); + Если ЗначениеЗаполнено(ИмяЛиста) Тогда + Возврат НайтиЛист(Книга, ИмяЛиста); + КонецЕсли; + КонецЕсли; + // Способ 2: ФИО как текст в ячейке — ищем лист по имени (xls) + ФИО = ПрочитатьЯчейкуСтрока(ЛистРасчет, НомерСтроки, 1); + Если ЗначениеЗаполнено(ФИО) Тогда + Возврат НайтиЛист(Книга, ФИО); + КонецЕсли; + Возврат Неопределено; +КонецФункции + +// Определяет строку данных для выбранного месяца на листе сотрудника. +// Строка = 35 + МесяцЗагрузки (36 = Январь, 37 = Февраль, ...) +&НаКлиенте +Функция СтрокаМесяцаНаЛистеСотрудника() + Смещение = Объект.МесяцЗагрузки; + Если Не ЗначениеЗаполнено(Смещение) Тогда Смещение = 1; КонецЕсли; + Возврат 35 + Смещение; +КонецФункции + +// Читает ФИО и данные карточки из листа сотрудника (строки 1-5). +&НаКлиенте +Функция ПрочитатьКарточкуСотрудника(ЛистСотрудника) + Данные = Новый Структура; + Данные.Вставить("ФИО", ПрочитатьЯчейкуСтрока(ЛистСотрудника, 2, 3)); + Данные.Вставить("Должность", ПрочитатьЯчейкуСтрока(ЛистСотрудника, 3, 3)); + Данные.Вставить("СчетБК", ПрочитатьЯчейкуСтрока(ЛистСотрудника, 4, 4)); + Данные.Вставить("ВидЗанятости", ПрочитатьЯчейкуСтрока(ЛистСотрудника, 6, 1)); + Данные.Вставить("ИНН", ПрочитатьЯчейкуСтрока(ЛистСотрудника, 1, 10)); + Данные.Вставить("СНИЛС", ПрочитатьЯчейкуСтрока(ЛистСотрудника, 2, 10)); + Данные.Вставить("Адрес", ПрочитатьЯчейкуСтрока(ЛистСотрудника, 4, 10)); + Возврат Данные; +КонецФункции + +// Читает расчётные данные из листа сотрудника (OFFSET-блок, строки 12+). +&НаКлиенте +Функция ПрочитатьРасчетныеДанныеСЛиста(ЛистСотрудника, ФИО) + Стр = Новый Структура; + Стр.Вставить("ФИО", ФИО); + Стр.Вставить("Должность", ПрочитатьЯчейкуСтрока(ЛистСотрудника, 3, 3)); + Стр.Вставить("СчетБК", ПрочитатьЯчейкуСтрока(ЛистСотрудника, 4, 4)); + Стр.Вставить("ВидЗанятости", ПрочитатьЯчейкуСтрока(ЛистСотрудника, 6, 1)); БазоваяСтрока = 12; Смещение = Объект.МесяцЗагрузки; Если Не ЗначениеЗаполнено(Смещение) Тогда Смещение = 1; КонецЕсли; - Стр = БазоваяСтрока + Смещение; - Строка.Вставить("Оклад", ПрочитатьЯчейкуЧисло(ЛистСотрудника, Стр, 3, ФИО + " Оклад")); - Строка.Вставить("КоличествоСтавок", ПрочитатьЯчейкуЧисло(ЛистСотрудника, Стр, 4, ФИО + " Ставки")); - Строка.Вставить("ОтработаноДней", ПрочитатьЯчейкуЧисло(ЛистСотрудника, Стр, 5, ФИО + " Отработано")); - Строка.Вставить("ИтогоНачислено", ПрочитатьЯчейкуЧисло(ЛистСотрудника, Стр, 10, ФИО + " Итого начислено")); - Строка.Вставить("НДФЛ", 0); - Строка.Вставить("ИтогоУдержано", 0); - Строка.Вставить("ВсегоНаРуки", 0); - Возврат Строка; + СтрокаДанных = БазоваяСтрока + Смещение; + Стр.Вставить("Оклад", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 3, ФИО + " Оклад")); + Стр.Вставить("КоличествоСтавок", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 4, ФИО + " Ставки")); + Стр.Вставить("ОтработаноДней", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 5, ФИО + " Отработано")); + Стр.Вставить("ИтогоНачислено", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 10, ФИО + " Итого начислено")); + Стр.Вставить("НДФЛ", 0); + Стр.Вставить("ИтогоУдержано", 0); + Стр.Вставить("ВсегоНаРуки", 0); + Возврат Стр; КонецФункции -// Читает все расчётные поля из листа "Расчет" для строки сотрудника. -// Колонки РАСЧЕТ: 9-38 расчёты, 39 итого, 40 НДФЛ, 41-52 удержания, 53 итого удержано, 55 на руки +// Читает расчётные данные из листа "Расчет" (табличные колонки 5-63). &НаКлиенте -Функция ПрочитатьСтрокуРасчета(ЛистРасчет, Ном, ФИО) +Функция ПрочитатьРасчетныеДанныеИзРасчета(ЛистРасчет, Ном, ФИО) Строка = Новый Структура; Строка.Вставить("ФИО", ФИО); Строка.Вставить("Должность", ПрочитатьЯчейкуСтрока(ЛистРасчет, Ном, 2)); Строка.Вставить("СчетБК", ПрочитатьЯчейкуСтрока(ЛистРасчет, Ном, 3)); Строка.Вставить("ВидЗанятости", ПрочитатьЯчейкуСтрока(ЛистРасчет, Ном, 4)); + // col 5-8: Оклад и базовые Строка.Вставить("Оклад", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 8, ФИО + " Оклад")); Строка.Вставить("КоличествоСтавок", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 7, ФИО + " Ставки")); Строка.Вставить("ОтработаноДней", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 6, ФИО + " Отработано")); - // Расчетные поля (col 9-38) - Строка.Вставить("ЧасыДежурства", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 9, ФИО + " Часы дежурства")); - Строка.Вставить("ЧасыНочные", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 10, ФИО + " Часы ночные")); - Строка.Вставить("ЧасыПраздничные", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 11, ФИО + " Часы праздничные")); - Строка.Вставить("РабочиеЧасыПоТабелю", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 12, ФИО + " Рабочие часы")); - Строка.Вставить("ИзРасчетаМесячногоОкладаДни", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 13, ФИО + " Расчет оклада дни")); - Строка.Вставить("ДоплатаСовместительство", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 14, ФИО + " Совместительство")); - Строка.Вставить("ДоплатаСовмещениеПроцент", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 15, ФИО + " Совмещение %")); - Строка.Вставить("ДоплатаИнтенсивность", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 16, ФИО + " Интенсивность")); - Строка.Вставить("ИзРасчетаМесячногоОкладаЧасы", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 17, ФИО + " Расчет оклада часы")); - Строка.Вставить("ДоплатаНочные", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 18, ФИО + " Доплата ночные")); - Строка.Вставить("ДоплатаПраздничные", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 19, ФИО + " Доплата праздничные")); - Строка.Вставить("ЗаСтаж", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 20, ФИО + " За стаж")); - Строка.Вставить("НадбавкаЗаКатегорию", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 21, ФИО + " Надбавка категория")); - Строка.Вставить("НадбавкаЗаВредность", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 22, ФИО + " Надбавка вредность")); - Строка.Вставить("ПовышающийКоэффициент", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 23, ФИО + " Повыш. коэфф.")); - Строка.Вставить("СтимулирующиеВыплаты", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 24, ФИО + " Стимулирующие")); - Строка.Вставить("СтимулирующаяНадбавка", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 25, ФИО + " Стимул. надбавка")); - Строка.Вставить("РайонныйКоэффициент", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 26, ФИО + " Районный К")); - Строка.Вставить("ВыплатыПоУказу597", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 27, ФИО + " Указ 597")); - Строка.Вставить("ПремияРазовая", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 28, ФИО + " Премия разовая")); - Строка.Вставить("БольничныйЛистЗаСчетПредприятия", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 29, ФИО + " Больничный")); - Строка.Вставить("ДоплатаПрофактиву", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 30, ФИО + " Профактив")); - Строка.Вставить("ПусковыеОбсервация", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 31, ФИО + " Пусковые")); - Строка.Вставить("Отпуск", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 32, ФИО + " Отпуск")); - Строка.Вставить("КомпенсацияЗаОтпуск", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 33, ФИО + " Компенсация отпуск")); - Строка.Вставить("ПрочиеКомандировочныйУчебныйОтпуск", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 34, ФИО + " Прочие отпуска")); - Строка.Вставить("ВыходноеПособие", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 35, ФИО + " Выходное пособие")); - Строка.Вставить("ПоУходуЗаРебенкомИнвалидом", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 36, ФИО + " Уход ребенок-инвалид")); - Строка.Вставить("ДоплатаДоМРОТ", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 37, ФИО + " Доплата МРОТ")); - Строка.Вставить("Родовые", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 38, ФИО + " Родовые")); - // Итоги - Строка.Вставить("ИтогоНачислено", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 39, ФИО + " Итого начислено")); - Строка.Вставить("НДФЛ", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 40, ФИО + " НДФЛ")); - Строка.Вставить("ПрофВзнос", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 41, ФИО + " Проф. взнос")); - Строка.Вставить("ИсполнительныеДокументы", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 42, ФИО + " Исп. документы")); - Строка.Вставить("Аванс", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 43, ФИО + " Аванс")); - Строка.Вставить("ИтогоУдержано", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 53, ФИО + " Итого удержано")); - Строка.Вставить("ВсегоНаРуки", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 55, ФИО + " Всего на руки")); + // col 9-38: Расчётные поля + Строка.Вставить("ЧасыДежурства", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 9, ФИО)); + Строка.Вставить("ЧасыНочные", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 10, ФИО)); + Строка.Вставить("ЧасыПраздничные", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 11, ФИО)); + Строка.Вставить("РабочиеЧасыПоТабелю", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 12, ФИО)); + Строка.Вставить("ИзРасчетаМесячногоОкладаДни", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 13, ФИО)); + Строка.Вставить("ДоплатаСовместительство", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 14, ФИО)); + Строка.Вставить("ДоплатаСовмещениеПроцент", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 15, ФИО)); + Строка.Вставить("ДоплатаИнтенсивность", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 16, ФИО)); + Строка.Вставить("ИзРасчетаМесячногоОкладаЧасы", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 17, ФИО)); + Строка.Вставить("ДоплатаНочные", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 18, ФИО)); + Строка.Вставить("ДоплатаПраздничные", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 19, ФИО)); + Строка.Вставить("ЗаСтаж", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 20, ФИО)); + Строка.Вставить("НадбавкаЗаКатегорию", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 21, ФИО)); + Строка.Вставить("НадбавкаЗаВредность", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 22, ФИО)); + Строка.Вставить("ПовышающийКоэффициент", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 23, ФИО)); + Строка.Вставить("СтимулирующиеВыплаты", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 24, ФИО)); + Строка.Вставить("СтимулирующаяНадбавка", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 25, ФИО)); + Строка.Вставить("РайонныйКоэффициент", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 26, ФИО)); + Строка.Вставить("ВыплатыПоУказу597", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 27, ФИО)); + Строка.Вставить("ПремияРазовая", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 28, ФИО)); + Строка.Вставить("БольничныйЛистЗаСчетПредприятия", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 29, ФИО)); + Строка.Вставить("ДоплатаПрофактиву", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 30, ФИО)); + Строка.Вставить("ПусковыеОбсервация", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 31, ФИО)); + Строка.Вставить("Отпуск", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 32, ФИО)); + Строка.Вставить("КомпенсацияЗаОтпуск", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 33, ФИО)); + Строка.Вставить("ПрочиеКомандировочныйУчебныйОтпуск", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 34, ФИО)); + Строка.Вставить("ВыходноеПособие", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 35, ФИО)); + Строка.Вставить("ПоУходуЗаРебенкомИнвалидом", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 36, ФИО)); + Строка.Вставить("ДоплатаДоМРОТ", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 37, ФИО)); + Строка.Вставить("Родовые", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 38, ФИО)); + // col 39-55: Итоги и удержания + Строка.Вставить("ИтогоНачислено", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 39, ФИО)); + Строка.Вставить("НДФЛ", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 40, ФИО)); + Строка.Вставить("ПрофВзнос", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 41, ФИО)); + Строка.Вставить("ИтогоУдержано", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 53, ФИО)); + Строка.Вставить("ВсегоНаРуки", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 55, ФИО)); Возврат Строка; КонецФункции +// Читает НДФЛ из блока внизу листа сотрудника (строки 31-48). &НаКлиенте -Функция ПрочитатьСтрокуВзносовИзРасчета(ЛистРасчет, Ном, ФИО) - КолДТ6 = 58; КолДТ4 = 59; КолПФ = 60; КолФСС = 61; КолНСПЗ = 62; КолСВИтого = 63; - СВ = ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, КолСВИтого, ФИО + " СВ итого"); - Если СВ <= 0 Тогда Возврат Неопределено; КонецЕсли; - Стр = Новый Структура; - Стр.Вставить("ФИО", ФИО); - Стр.Вставить("ДТ6Процент", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, КолДТ6, ФИО + " ДТ 6%")); - Стр.Вставить("ДТ4Процент", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, КолДТ4, ФИО + " ДТ 4%")); - Стр.Вставить("ПФСтраховая", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, КолПФ, ФИО + " ПФ")); - Стр.Вставить("ФССФОМС", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, КолФСС, ФИО + " ФСС/ФОМС")); - Стр.Вставить("НСПЗ", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, КолНСПЗ, ФИО + " НС и ПЗ")); - Стр.Вставить("Итого", СВ); - Возврат Стр; -КонецФункции - -// Читает данные НДФЛ и СВ из блока внизу листа сотрудника. -// Заголовки блока: строки 33-35. Данные: строки 36-47 (Январь-Декабрь). Итого: строка 48. -&НаКлиенте -Функция ПрочитатьНДФЛСоЛистаСотрудника(ЛистСотрудника, ФИО) +Функция ПрочитатьНДФЛСоЛиста(ЛистСотрудника, ФИО) Если ЛистСотрудника = Неопределено Тогда Возврат Неопределено; КонецЕсли; - // Проверяем наличие блока: строка 31 содержит "Расчет НДФЛ" + // Проверяем наличие блока НДФЛ ЕстьБлок = Ложь; Для ПроверяемаяСтрока = 30 По 32 Цикл Текст = НРег(ПрочитатьЯчейкуСтрока(ЛистСотрудника, ПроверяемаяСтрока, 1)); Если СтрНайти(Текст, "ндфл") > 0 ИЛИ СтрНайти(Текст, "взнос") > 0 Тогда - ЕстьБлок = Истина; - Прервать; + ЕстьБлок = Истина; Прервать; КонецЕсли; КонецЦикла; Если Не ЕстьБлок Тогда - // Fallback: проверяем строку 36 — там должен быть "Январь" ТекстЯнв = НРег(ПрочитатьЯчейкуСтрока(ЛистСотрудника, 36, 1)); Если СтрНайти(ТекстЯнв, "январь") = 0 Тогда Возврат Неопределено; КонецЕсли; - ЕстьБлок = Истина; КонецЕсли; - Если Не ЕстьБлок Тогда Возврат Неопределено; КонецЕсли; - - // Определяем строку данных для выбранного месяца - Смещение = Объект.МесяцЗагрузки; - Если Не ЗначениеЗаполнено(Смещение) Тогда Смещение = 1; КонецЕсли; - СтрокаДанных = 35 + Смещение; - - // Проверяем что в строке название месяца - МассивМесяцев = Новый Массив; - МассивМесяцев.Добавить("январь"); МассивМесяцев.Добавить("февраль"); - МассивМесяцев.Добавить("март"); МассивМесяцев.Добавить("апрель"); - МассивМесяцев.Добавить("май"); МассивМесяцев.Добавить("июнь"); - МассивМесяцев.Добавить("июль"); МассивМесяцев.Добавить("август"); - МассивМесяцев.Добавить("сентябрь"); МассивМесяцев.Добавить("октябрь"); - МассивМесяцев.Добавить("ноябрь"); МассивМесяцев.Добавить("декабрь"); - - ТекстМесяца = НРег(ПрочитатьЯчейкуСтрока(ЛистСотрудника, СтрокаДанных, 1)); - Если МассивМесяцев.Найти(ТекстМесяца) = Неопределено Тогда - // Ищем строку с нужным месяцем - Для Строка = 36 По 47 Цикл - Если (Строка - 35) = Смещение Тогда - СтрокаДанных = Строка; - Прервать; - КонецЕсли; - КонецЦикла; - КонецЕсли; - - // Колонки блока НДФЛ/СВ (по структуре xlsm): - // 4: Сумма валового дохода за месяц - // 6: Сумма валового дохода с начала года - // 8: Скидка для НДФЛ за месяц - // 9: Скидка для НДФЛ за год - // 10: Скидка для СВ за месяц - // 12: Вычет на работника за месяц - // 13: Вычет на иждивенцев за месяц - // 14: Всего вычетов за год - // 15: Облагаемый доход за год - // 16: НДФЛ начисленный за год - // 18: Итого НДФЛ за месяц - // 23: Налоговая база по СВ за месяц - // 37: СВ итого за месяц - + СтрокаДанных = СтрокаМесяцаНаЛистеСотрудника(); НДФЛ = Новый Структура; НДФЛ.Вставить("ФИО", ФИО); НДФЛ.Вставить("МесяцРасчета", ПрочитатьЯчейкуСтрока(ЛистСотрудника, СтрокаДанных, 1)); - НДФЛ.Вставить("СуммаВаловогоДохода", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 4, ФИО + " Сумма валового дохода")); - НДФЛ.Вставить("СуммаВаловогоДоходаСНачалаГода", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 6, ФИО + " Доход с начала года")); - НДФЛ.Вставить("СкидкаДляНДФЛЗаМесяц", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 8, ФИО + " Скидка НДФЛ месяц")); - НДФЛ.Вставить("СкидкаДляНДФЛЗаГод", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 9, ФИО + " Скидка НДФЛ год")); - НДФЛ.Вставить("СкидкаДляСВЗаМесяц", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 10, ФИО + " Скидка СВ месяц")); - НДФЛ.Вставить("ВычетНаРаботникаЗаМесяц", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 12, ФИО + " Вычет работника")); + НДФЛ.Вставить("СуммаВаловогоДохода", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 4, ФИО + " вал. доход")); + НДФЛ.Вставить("СуммаВаловогоДоходаСНачалаГода", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 6, ФИО + " вал. доход с н.г.")); + НДФЛ.Вставить("СкидкаДляНДФЛЗаМесяц", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 8, ФИО + " скидка НДФЛ мес")); + НДФЛ.Вставить("СкидкаДляНДФЛЗаГод", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 9, ФИО + " скидка НДФЛ год")); + НДФЛ.Вставить("СкидкаДляСВЗаМесяц", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 10, ФИО + " скидка СВ мес")); + НДФЛ.Вставить("ВычетНаРаботникаЗаМесяц", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 12, ФИО + " вычет работник")); НДФЛ.Вставить("ВычетНаРаботникаЗаГод", 0); - НДФЛ.Вставить("ВычетНаИждивенцевЗаМесяц", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 13, ФИО + " Вычет иждивенцев")); - НДФЛ.Вставить("ВсегоВычетовЗаМесяц", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 14, ФИО + " Всего вычетов")); + НДФЛ.Вставить("ВычетНаИждивенцевЗаМесяц", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 13, ФИО + " вычет иждивенцы")); + НДФЛ.Вставить("ВсегоВычетовЗаМесяц", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 14, ФИО + " всего вычетов")); НДФЛ.Вставить("ОблагаемыйДоходЗаМесяц", 0); - НДФЛ.Вставить("ОблагаемыйДоходЗаГод", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 15, ФИО + " Облагаемый доход")); - НДФЛ.Вставить("НачисленныйНДФЛЗаГод", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 16, ФИО + " НДФЛ начисленный")); - НДФЛ.Вставить("ИтогоНДФЛЗаМесяц", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 18, ФИО + " Итого НДФЛ")); - НДФЛ.Вставить("НалоговаяБазаПоСВЗаМесяц", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 23, ФИО + " База СВ месяц")); - НДФЛ.Вставить("ИтогоФСС", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 37, ФИО + " Итого СВ")); + НДФЛ.Вставить("ОблагаемыйДоходЗаГод", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 15, ФИО + " обл. доход год")); + НДФЛ.Вставить("НачисленныйНДФЛЗаГод", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 16, ФИО + " НДФЛ начисл. год")); + НДФЛ.Вставить("ИтогоНДФЛЗаМесяц", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 18, ФИО + " итого НДФЛ")); + НДФЛ.Вставить("НалоговаяБазаПоСВЗаМесяц", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 23, ФИО + " база СВ мес")); + НДФЛ.Вставить("ИтогоФСС", ПрочитатьЯчейкуЧисло(ЛистСотрудника, СтрокаДанных, 37, ФИО + " итого СВ")); Возврат НДФЛ; КонецФункции +// Читает страховые взносы из листа "Расчет" (cols 58-63). &НаКлиенте -Функция ПрочитатьДанныеСотрудника(ЛистСотрудника) - Данные = Новый Структура; - Данные.Вставить("ФИО", ПрочитатьЯчейкуСтрока(ЛистСотрудника, 2, 3)); - Данные.Вставить("ИНН", ПрочитатьЯчейкуСтрока(ЛистСотрудника, 0, 10)); - Данные.Вставить("СНИЛС", ПрочитатьЯчейкуСтрока(ЛистСотрудника, 1, 10)); - Данные.Вставить("ЛицевойСчетВБанке", ПрочитатьЯчейкуСтрока(ЛистСотрудника, 3, 4)); - Данные.Вставить("ВидЗанятости", ПрочитатьЯчейкуСтрока(ЛистСотрудника, 5, 1)); - Данные.Вставить("АдресРегистрации", ПрочитатьЯчейкуСтрока(ЛистСотрудника, 3, 10)); - Возврат Данные; +Функция ПрочитатьВзносыИзРасчета(ЛистРасчет, Ном, ФИО) + СВ = ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 63, ФИО + " СВ итого"); + Если СВ <= 0 Тогда Возврат Неопределено; КонецЕсли; + Стр = Новый Структура; + Стр.Вставить("ФИО", ФИО); + Стр.Вставить("ДТ6Процент", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 58, ФИО)); + Стр.Вставить("ДТ4Процент", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 59, ФИО)); + Стр.Вставить("ПФСтраховая", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 60, ФИО)); + Стр.Вставить("ФССФОМС", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 61, ФИО)); + Стр.Вставить("НСПЗ", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, 62, ФИО)); + Стр.Вставить("Итого", СВ); + Возврат Стр; КонецФункции #КонецОбласти @@ -316,30 +303,48 @@ СтатусЗагрузки = "Открытие Excel..."; КонтекстExcel = ОткрытьФайлExcel(ВременныйФайл); Если КонтекстExcel = Неопределено Тогда УдалитьФайлы(ВременныйФайл); Возврат; КонецЕсли; - СтатусЗагрузки = "Поиск листа Расчет..."; + ЛистРасчет = НайтиЛист(КонтекстExcel.Книга, "Расчет"); Если ЛистРасчет = Неопределено Тогда Сообщить("Лист Расчет не найден!"); ЗакрытьExcel(КонтекстExcel, ВременныйФайл); Возврат; КонецЕсли; + + // Месяц загрузки МесяцЗначение = ЛистРасчет.Cells(4, 1).Value; Если ЗначениеЗаполнено(МесяцЗначение) Тогда Попытка Объект.МесяцЗагрузки = Число(МесяцЗначение); Исключение КонецПопытки; КонецЕсли; - Ном = 1; - // Определяем строку первого сотрудника - Для Ном = 1 По 30 Цикл - Значение = ЛистРасчет.Cells(Ном, 1).Value; - Если Значение <> Неопределено И Значение <> "" Тогда - ФИОТест = СокрЛП("" + Значение); - Если Не СтрНачинаетсяС(ВРег(ФИОТест), "ИТОГО") - И Не СтрНачинаетсяС(ВРег(ФИОТест), "СОТРУДНИК") - И СтрДлина(ФИОТест) > 3 Тогда - Прервать; - КонецЕсли; + + // Определяем строку начала данных: первая строка с формулой-ссылкой вида ='ИмяЛиста'!... + НачальнаяСтрока = 0; + Для Ном = 17 По 30 Цикл + Формула = ЛистРасчет.Cells(Ном, 1).Formula; + Если ЗначениеЗаполнено(Формула) И СтрНайти("" + Формула, "='") > 0 Тогда + НачальнаяСтрока = Ном; + Прервать; КонецЕсли; КонецЦикла; + Если НачальнаяСтрока = 0 Тогда + // Fallback для xls: ищем первую непустую строку с текстом > 3 символов + Для Ном = 17 По 30 Цикл + ФИОТест = СокрЛП("" + ЛистРасчет.Cells(Ном, 1).Value); + Если ЗначениеЗаполнено(ФИОТест) + И Не СтрНачинаетсяС(ВРег(ФИОТест), "ИТОГО") + И Не СтрНачинаетсяС(ВРег(ФИОТест), "СОТРУДНИК") + И Не СтрНачинаетсяС(ВРег(ФИОТест), "ФАМИЛИЯ") + И СтрДлина(ФИОТест) > 3 Тогда + НачальнаяСтрока = Ном; + Прервать; + КонецЕсли; + КонецЦикла; + КонецЕсли; + Если НачальнаяСтрока = 0 Тогда + Сообщить("Данные сотрудников не найдены!"); + ЗакрытьExcel(КонтекстExcel, ВременныйФайл); + Возврат; + КонецЕсли; МассивДанных = Новый Массив; МассивВзносов = Новый Массив; @@ -348,53 +353,58 @@ Счетчик = 0; ПустыхПодряд = 0; - Пока Истина Цикл - ФИО = ""; - ЛистСотрудника = Неопределено; - // Пробуем прочитать ФИО из РАСЧЕТ - ФИО = ПрочитатьЯчейкуСтрока(ЛистРасчет, Ном, 1); - Если Не ЗначениеЗаполнено(ФИО) Тогда - // xlsm: ФИО в формуле-ссылке - Формула = ЛистРасчет.Cells(Ном, 1).Formula; - Если ЗначениеЗаполнено(Формула) Тогда - ИмяЛиста = ИзвлечьИмяЛистаИзФормулы(Формула); - Если ЗначениеЗаполнено(ИмяЛиста) Тогда - ЛистСотрудника = НайтиЛист(КонтекстExcel.Книга, ИмяЛиста); - Если ЛистСотрудника <> Неопределено Тогда - ФИО = ПрочитатьЯчейкуСтрока(ЛистСотрудника, 2, 3); - КонецЕсли; - КонецЕсли; + Для Ном = НачальнаяСтрока По ЛистРасчет.Rows.Count Цикл + // Проверка окончания данных + ЗначениеЯчейки = ЛистРасчет.Cells(Ном, 1).Value; + Если ЗначениеЯчейки = Неопределено ИЛИ ЗначениеЯчейки = "" Тогда + // Может быть пустая строка в середине — проверяем ещё 2 строки + След1 = ЛистРасчет.Cells(Ном + 1, 1).Value; + След2 = ЛистРасчет.Cells(Ном + 2, 1).Value; + Если (След1 = Неопределено ИЛИ След1 = "") И (След2 = Неопределено ИЛИ След2 = "") Тогда + Прервать; КонецЕсли; + Продолжить; + КонецЕсли; + ФИОТекст = СокрЛП("" + ЗначениеЯчейки); + Если СтрНачинаетсяС(ВРег(ФИОТекст), "ИТОГО") Тогда Прервать; КонецЕсли; + Если СтрНачинаетсяС(ВРег(ФИОТекст), "СОТРУДНИК") Тогда Продолжить; КонецЕсли; + Если СтрНачинаетсяС(ВРег(ФИОТекст), "ФАМИЛИЯ") Тогда Продолжить; КонецЕсли; + + // Ищем лист сотрудника — ВСЕГДА, независимо от того, есть ли ФИО + ЛистСотрудника = НайтиЛистСотрудника(КонтекстExcel.Книга, ЛистРасчет, Ном); + Если ЛистСотрудника = Неопределено Тогда Продолжить; КонецЕсли; + + // Читаем ФИО из листа сотрудника (приоритет) или из формулы + ФИО = ""; + Если ЛистСотрудника <> Неопределено Тогда + ФИО = ПрочитатьЯчейкуСтрока(ЛистСотрудника, 2, 3); // C2 листа сотрудника КонецЕсли; Если Не ЗначениеЗаполнено(ФИО) Тогда - ПустыхПодряд = ПустыхПодряд + 1; - Если ПустыхПодряд >= 5 Тогда Прервать; КонецЕсли; - Ном = Ном + 1; Продолжить; + ФИО = ФИОТекст; КонецЕсли; - ПустыхПодряд = 0; - Если СтрНачинаетсяС(ВРег(СокрЛП(ФИО)), "ИТОГО") Тогда Прервать; КонецЕсли; + Если Не ЗначениеЗаполнено(ФИО) Тогда Продолжить; КонецЕсли; Счетчик = Счетчик + 1; - Состояние("Расчет ЗП: " + ФИО, 25 + 60 * Счетчик / 100); + Состояние("Загрузка: " + ФИО, 20 + 70 * Счетчик / 50); - // Чтение данных ЗП (все расчётные колонки из РАСЧЕТ) - Строка = ПрочитатьСтрокуРасчета(ЛистРасчет, Ном, ФИО); + // Основные расчётные данные — из листа РАСЧЕТ (все колонки 5-63) + Строка = ПрочитатьРасчетныеДанныеИзРасчета(ЛистРасчет, Ном, ФИО); Строка.Вставить("ИдентификаторСотрудника", Счетчик); - // Если есть лист сотрудника — обогащаем данными карточки + // Обогащение данными карточки с листа сотрудника Если ЛистСотрудника <> Неопределено Тогда - ДанныеКарточки = ПрочитатьДанныеСотрудника(ЛистСотрудника); - // ФИО и Должность уже из РАСЧЕТ, перезаписываем только карточные - Строка.Вставить("ИНН", ДанныеКарточки.ИНН); - Строка.Вставить("СНИЛС", ДанныеКарточки.СНИЛС); - Строка.Вставить("Адрес", ДанныеКарточки.АдресРегистрации); + Карточка = ПрочитатьКарточкуСотрудника(ЛистСотрудника); + // Обновляем ФИО если лист вернул более точное + Если ЗначениеЗаполнено(Карточка.ФИО) Тогда + Строка.Вставить("ФИО", Карточка.ФИО); + КонецЕсли; КонецЕсли; МассивДанных.Добавить(Строка); // Таблица сотрудников Если ЛистСотрудника <> Неопределено Тогда - ДанныеСотр = ПрочитатьДанныеСотрудника(ЛистСотрудника); + ДанныеСотр = ПрочитатьКарточкуСотрудника(ЛистСотрудника); Иначе ДанныеСотр = Новый Структура("ФИО, ИНН, СНИЛС, ЛицевойСчетВБанке, ВидЗанятости, АдресРегистрации", ФИО, "", "", "", "", ""); @@ -402,29 +412,27 @@ ДанныеСотр.Вставить("Идентификатор", Счетчик); МассивСотрудников.Добавить(ДанныеСотр); - // НДФЛ из блока внизу листа сотрудника + // НДФЛ — ВСЕГДА из листа сотрудника Если ЛистСотрудника <> Неопределено Тогда - ДанныеНДФЛ = ПрочитатьНДФЛСоЛистаСотрудника(ЛистСотрудника, ФИО); + ДанныеНДФЛ = ПрочитатьНДФЛСоЛиста(ЛистСотрудника, ФИО); Если ДанныеНДФЛ <> Неопределено Тогда ДанныеНДФЛ.Вставить("ИдентификаторСотрудника", Счетчик); МассивНДФЛ.Добавить(ДанныеНДФЛ); КонецЕсли; КонецЕсли; - // Страховые взносы из РАСЧЕТ (cols 58-63) - СтрВзносов = ПрочитатьСтрокуВзносовИзРасчета(ЛистРасчет, Ном, ФИО); + // Страховые взносы — из РАСЧЕТ (cols 58-63) + СтрВзносов = ПрочитатьВзносыИзРасчета(ЛистРасчет, Ном, ФИО); Если СтрВзносов <> Неопределено Тогда СтрВзносов.Вставить("ИдентификаторСотрудника", Счетчик); МассивВзносов.Добавить(СтрВзносов); КонецЕсли; - - Ном = Ном + 1; - Если Ном > ЛистРасчет.Rows.Count Тогда Прервать; КонецЕсли; КонецЦикла; ЗакрытьExcel(КонтекстExcel, ВременныйФайл); ЗаполнитьТаблицыНаСервере(МассивДанных, МассивВзносов, МассивНДФЛ, МассивСотрудников); - СтатусЗагрузки = "Готово! Загружено: " + МассивДанных.Количество() + " сотрудников"; + СтатусЗагрузки = "Готово! Загружено: " + МассивДанных.Количество() + " сотрудников, " + + МассивНДФЛ.Количество() + " записей НДФЛ"; Сообщить(СтатусЗагрузки); ОбновитьОтображениеДанных(); КонецПроцедуры