From f82c1027bc36ea98c6131dfed1c4274910afd80a 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: Tue, 7 Jul 2026 18:14:39 +0000 Subject: [PATCH] =?UTF-8?q?v3.0.0.4:=20DDD-=D1=80=D0=B5=D1=84=D0=B0=D0=BA?= =?UTF-8?q?=D1=82=D0=BE=D1=80=D0=B8=D0=BD=D0=B3,=20=D0=B4=D0=B8=D0=BD?= =?UTF-8?q?=D0=B0=D0=BC=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B8=D0=B5=20=D0=B7?= =?UTF-8?q?=D0=B0=D0=B3=D0=BE=D0=BB=D0=BE=D0=B2=D0=BA=D0=B8,=20=D0=B0?= =?UTF-8?q?=D1=80=D1=85=D0=B8=D0=B2=20=D0=B2=D0=B5=D1=80=D1=81=D0=B8=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Forms/Форма/Ext/Form/Module.bsl | 490 ++++++++++++------ 1 file changed, 321 insertions(+), 169 deletions(-) diff --git a/DataProcessors/ЗагрузкаДанныхИзExcel/Forms/Форма/Ext/Form/Module.bsl b/DataProcessors/ЗагрузкаДанныхИзExcel/Forms/Форма/Ext/Form/Module.bsl index 4bcb229..e5e16e7 100644 --- a/DataProcessors/ЗагрузкаДанныхИзExcel/Forms/Форма/Ext/Form/Module.bsl +++ b/DataProcessors/ЗагрузкаДанныхИзExcel/Forms/Форма/Ext/Form/Module.bsl @@ -45,10 +45,46 @@ #КонецОбласти -#Область РаботаСExcel +#Область ЧтениеExcel_Домен +// ============================================================================ +// ДОМЕН: Чтение Excel +// Ответственность: открытие файла, поиск листов, чтение ячеек +// ============================================================================ + +// Создаёт COM-объект Excel и открывает файл. +// Возвращает структуру {Книга, Excel} или Неопределено при ошибке. &НаКлиенте -Функция ПрочитатьЯчейку(Лист, Строка, Колонка, ФИО, ВидДанных) +Функция ОткрытьФайлExcel(ПутьКФайлу) + Попытка + Excel = Новый COMОбъект("Excel.Application"); + Excel.Visible = Ложь; + Excel.DisplayAlerts = Ложь; + Книга = Excel.Workbooks.Open(ПутьКФайлу); + Возврат Новый Структура("Книга, Excel", Книга, Excel); + Исключение + Сообщить("Не удалось открыть Excel: " + ОписаниеОшибки()); + Возврат Неопределено; + КонецПопытки; +КонецФункции + +// Закрывает книгу и приложение Excel, удаляет временный файл. +&НаКлиенте +Процедура ЗакрытьExcel(КонтекстExcel, ВременныйФайл) + Если КонтекстExcel = Неопределено Тогда Возврат; КонецЕсли; + Попытка + КонтекстExcel.Книга.Close(Ложь); + КонтекстExcel.Excel.Quit(); + Исключение + КонецПопытки; + Если ЗначениеЗаполнено(ВременныйФайл) Тогда + УдалитьФайлы(ВременныйФайл); + КонецЕсли; +КонецПроцедуры + +// Читает числовое значение ячейки с обработкой ошибок. +&НаКлиенте +Функция ПрочитатьЯчейкуЧисло(Лист, Строка, Колонка, КонтекстОшибки) Попытка Значение = Лист.Cells(Строка, Колонка).Value; Если Значение = Неопределено ИЛИ Значение = "" Тогда @@ -56,15 +92,16 @@ КонецЕсли; Возврат Число(Значение); Исключение - Сообщить("Ошибка: " + ФИО + " | " + ВидДанных + Сообщить("Ошибка чтения числа: " + КонтекстОшибки + " | строка " + Строка + " колонка " + Колонка + " | значение: """ + Значение + """ | " + ОписаниеОшибки()); Возврат 0; КонецПопытки; КонецФункции +// Читает строковое значение ячейки. &НаКлиенте -Функция ПрочитатьСтроку(Лист, Строка, Колонка) +Функция ПрочитатьЯчейкуСтрока(Лист, Строка, Колонка) Попытка Значение = Лист.Cells(Строка, Колонка).Value; Если Значение = Неопределено Тогда Возврат ""; КонецЕсли; @@ -74,6 +111,67 @@ КонецПопытки; КонецФункции +// Ищет лист по имени (регистронезависимо). +&НаКлиенте +Функция НайтиЛист(Книга, ИмяЛиста) + Для Каждого Лист Из Книга.Sheets Цикл + Если ВРег(Лист.Name) = ВРег(ИмяЛиста) Тогда + Возврат Лист; + КонецЕсли; + КонецЦикла; + Возврат Неопределено; +КонецФункции + +#КонецОбласти + +#Область МаппингЗаголовков_Домен + +// ============================================================================ +// ДОМЕН: Маппинг заголовков +// Ответственность: сопоставление имён колонок Excel с полями данных +// ============================================================================ + +// Создаёт Соответствие для поиска колонок по имени заголовка. +// Ключ — имя заголовка (нижний регистр), значение — номер колонки (0-based). +&НаКлиенте +Функция СоздатьИндексЗаголовков(Лист, НомерСтрокиЗаголовков) + Индекс = Новый Соответствие; + Для Колонка = 0 По Лист.Cells(НомерСтрокиЗаголовков, 1).End(-4161).Column - 1 Цикл + Имя = СокрЛП(НРег(Лист.Cells(НомерСтрокиЗаголовков, Колонка + 1).Value)); + Если ЗначениеЗаполнено(Имя) Тогда + Индекс.Вставить(Имя, Колонка); + КонецЕсли; + КонецЦикла; + Возврат Индекс; +КонецФункции + +// Находит номер колонки по ключевому слову в заголовке. +// Возвращает номер колонки (0-based) или -1 если не найдено. +&НаКлиенте +Функция НайтиКолонкуПоЗаголовку(ИндексЗаголовков, КлючевоеСлово) + Ключ = НРег(КлючевоеСлово); + Для Каждого Эл Из ИндексЗаголовков Цикл + Если СтрНайти(Эл.Ключ, Ключ) > 0 Тогда + Возврат Эл.Значение; + КонецЕсли; + КонецЦикла; + Возврат -1; +КонецФункции + +// Определяет номер строки первого сотрудника (первая непустая строка после заголовков). +&НаКлиенте +Функция НайтиСтрокуПервогоСотрудника(ЛистРасчет, НомерСтрокиЗаголовков) + Для Ном = НомерСтрокиЗаголовков + 1 По ЛистРасчет.Rows.Count Цикл + Значение = ЛистРасчет.Cells(Ном, 1).Value; + Если ЗначениеЗаполнено(Значение) + И Не СтрНачинаетсяС(ВРег(СокрЛП("" + Значение)), "ИТОГО") Тогда + Возврат Ном; + КонецЕсли; + КонецЦикла; + Возврат -1; +КонецФункции + +// Извлекает значение из текста вида "ИНН 990100718541" → "990100718541" &НаКлиенте Функция ИзвлечьЗначениеИзТекста(Текст, Префикс) Если Не ЗначениеЗаполнено(Текст) Тогда Возврат ""; КонецЕсли; @@ -82,183 +180,230 @@ Возврат СокрЛП(Сред(Текст, Позиция + СтрДлина(Префикс))); КонецФункции +#КонецОбласти + +#Область ЧтениеДанныхСотрудника_Домен + +// ============================================================================ +// ДОМЕН: Чтение данных сотрудника +// Ответственность: извлечение данных из строки листа "Расчет" +// ============================================================================ + +// Читает одну строку данных сотрудника из листа "Расчет". +// ИндексЗаголовков — Соответствие для динамического поиска колонок. +&НаКлиенте +Функция ПрочитатьСтрокуРасчета(ЛистРасчет, Ном, ФИО, ИндексЗаголовков) + Строка = Новый Структура; + Строка.Вставить("ФИО", ФИО); + + // Поиск колонок по заголовкам + КолДолжность = НайтиКолонкуПоЗаголовку(ИндексЗаголовков, "должность"); + КолСчетБК = НайтиКолонкуПоЗаголовку(ИндексЗаголовков, "счет"); + КолВидЗанятости = НайтиКолонкуПоЗаголовку(ИндексЗаголовков, "вид занятости"); + КолОклад = НайтиКолонкуПоЗаголовку(ИндексЗаголовков, "оклад"); + КолСтавки = НайтиКолонкуПоЗаголовку(ИндексЗаголовков, "ставок"); + КолОтработано = НайтиКолонкуПоЗаголовку(ИндексЗаголовков, "отработано"); + КолИтогоНачислено = НайтиКолонкуПоЗаголовку(ИндексЗаголовков, "итого начислено"); + КолНДФЛ = НайтиКолонкуПоЗаголовку(ИндексЗаголовков, "ндфл"); + КолИтогоУдержано = НайтиКолонкуПоЗаголовку(ИндексЗаголовков, "итого удержано"); + КолВсегоНаРуки = НайтиКолонкуПоЗаголовку(ИндексЗаголовков, "всего на руки"); + + Строка.Вставить("Должность", ПрочитатьЯчейкуСтроку(ЛистРасчет, Ном, КолДолжность)); + Строка.Вставить("СчетБК", ПрочитатьЯчейкуСтроку(ЛистРасчет, Ном, КолСчетБК)); + Строка.Вставить("ВидЗанятости", ПрочитатьЯчейкуСтроку(ЛистРасчет, Ном, КолВидЗанятости)); + Строка.Вставить("Оклад", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, КолОклад, ФИО + " Оклад")); + Строка.Вставить("КоличествоСтавок", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, КолСтавки, ФИО + " Ставки")); + Строка.Вставить("ОтработаноДней", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, КолОтработано, ФИО + " Отработано")); + Строка.Вставить("ИтогоНачислено", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, КолИтогоНачислено, ФИО + " Итого начислено")); + Строка.Вставить("НДФЛ", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, КолНДФЛ, ФИО + " НДФЛ")); + Строка.Вставить("ИтогоУдержано", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, КолИтогоУдержано, ФИО + " Итого удержано")); + Строка.Вставить("ВсегоНаРуки", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, КолВсегоНаРуки, ФИО + " Всего на руки")); + + Возврат Строка; +КонецФункции + +// Читает страховые взносы из строки листа "Расчет". +&НаКлиенте +Функция ПрочитатьСтрокуВзносов(ЛистРасчет, Ном, ФИО, ИндексЗаголовков) + КолДТ6 = НайтиКолонкуПоЗаголовку(ИндексЗаголовков, "дт 6"); + КолДТ4 = НайтиКолонкуПоЗаголовку(ИндексЗаголовков, "дт 4"); + КолПФ = НайтиКолонкуПоЗаголовку(ИндексЗаголовков, "пф страховая"); + КолФСС = НайтиКолонкуПоЗаголовку(ИндексЗаголовков, "фсс"); + КолНСПЗ = НайтиКолонкуПоЗаголовку(ИндексЗаголовков, "нс и пз"); + КолСВИтого = НайтиКолонкуПоЗаголовку(ИндексЗаголовков, "св итого"); + + СВ = ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, КолСВИтого, ФИО + " СВ итого"); + Если СВ <= 0 Тогда Возврат Неопределено; КонецЕсли; + + СтрВзносов = Новый Структура; + СтрВзносов.Вставить("ФИО", ФИО); + СтрВзносов.Вставить("ДТ6Процент", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, КолДТ6, ФИО + " ДТ 6%")); + СтрВзносов.Вставить("ДТ4Процент", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, КолДТ4, ФИО + " ДТ 4%")); + СтрВзносов.Вставить("ПФСтраховая", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, КолПФ, ФИО + " ПФ")); + СтрВзносов.Вставить("ФССФОМС", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, КолФСС, ФИО + " ФСС/ФОМС")); + СтрВзносов.Вставить("НСПЗ", ПрочитатьЯчейкуЧисло(ЛистРасчет, Ном, КолНСПЗ, ФИО + " НС и ПЗ")); + СтрВзносов.Вставить("Итого", СВ); + + Возврат СтрВзносов; +КонецФункции + +// Читает личные данные из листа сотрудника (шапка строк 0-3). +&НаКлиенте +Функция ПрочитатьЛичныеДанные(Книга, ФИО) + ЛичныеДанные = Новый Структура("ИНН, СНИЛС, Паспорт, Адрес", "", "", "", ""); + + ЛистСотрудника = НайтиЛист(Книга, ФИО); + Если ЛистСотрудника = Неопределено Тогда + Возврат ЛичныеДанные; + КонецЕсли; + + ЛичныеДанные.ИНН = ИзвлечьЗначениеИзТекста( + ПрочитатьЯчейкуСтроку(ЛистСотрудника, 0, 10), "ИНН"); + ЛичныеДанные.СНИЛС = ИзвлечьЗначениеИзТекста( + ПрочитатьЯчейкуСтроку(ЛистСотрудника, 1, 10), "СНИЛС"); + ЛичныеДанные.Паспорт = ИзвлечьЗначениеИзТекста( + ПрочитатьЯчейкуСтроку(ЛистСотрудника, 2, 10), "Паспорт"); + ЛичныеДанные.Адрес = ПрочитатьЯчейкуСтроку(ЛистСотрудника, 3, 10); + + Возврат ЛичныеДанные; +КонецФункции + +#КонецОбласти + +#Область ОсновнаяПроцедура_Домен + +// ============================================================================ +// ДОМЕН: Оркестрация загрузки +// Ответственность: координация всех этапов загрузки +// ============================================================================ + &НаКлиенте Процедура ПрочитатьExcelНаКлиенте() - Попытка - СтатусЗагрузки = "Копирование файла..."; - Прогресс = 5; - Состояние("Копирование файла...", 5); + // Этап 1: Подготовка файла + СтатусЗагрузки = "Копирование файла..."; + Состояние("Копирование файла...", 5); + + ВременныйФайл = КаталогВременныхФайлов() + "temp_data.xls"; + КопироватьФайл(Объект.ПутьКФайлу, ВременныйФайл); + + // Этап 2: Открытие Excel + СтатусЗагрузки = "Открытие Excel..."; + Состояние("Открытие Excel...", 10); + + КонтекстExcel = ОткрытьФайлExcel(ВременныйФайл); + Если КонтекстExcel = Неопределено Тогда + УдалитьФайлы(ВременныйФайл); + Возврат; + КонецЕсли; + + // Этап 3: Поиск листа "Расчет" + СтатусЗагрузки = "Поиск листа 'Расчет'..."; + Состояние("Поиск листа 'Расчет'...", 15); + + ЛистРасчет = НайтиЛист(КонтекстExcel.Книга, "Расчет"); + Если ЛистРасчет = Неопределено Тогда + Сообщить("Лист 'Расчет' не найден!"); + ЗакрытьExcel(КонтекстExcel, ВременныйФайл); + СтатусЗагрузки = "Ошибка: лист не найден"; + Состояние("Ошибка: лист 'Расчет' не найден", 0); + Возврат; + КонецЕсли; + + // Этап 4: Определение месяца + СтатусЗагрузки = "Определение месяца..."; + Состояние("Определение месяца...", 20); + + МесяцЗначение = ЛистРасчет.Cells(4, 1).Value; + Если ЗначениеЗаполнено(МесяцЗначение) Тогда + Попытка + Объект.МесяцЗагрузки = Число(МесяцЗначение); + Исключение + Сообщить("Не удалось определить месяц: " + МесяцЗначение); + КонецПопытки; + КонецЕсли; + + // Этап 5: Построение индекса заголовков + СтатусЗагрузки = "Анализ заголовков..."; + Состояние("Анализ заголовков...", 22); + + НомерСтрокиЗаголовков = 15; + ИндексЗаголовков = СоздатьИндексЗаголовков(ЛистРасчет, НомерСтрокиЗаголовков); + + // Этап 6: Определение строки первого сотрудника + СтатусЗагрузки = "Поиск данных..."; + Состояние("Поиск данных...", 25); + + Ном = НайтиСтрокуПервогоСотрудника(ЛистРасчет, НомерСтрокиЗаголовков); + Если Ном = -1 Тогда + Сообщить("Данные сотрудников не найдены!"); + ЗакрытьExcel(КонтекстExcel, ВременныйФайл); + Возврат; + КонецЕсли; + + // Этап 7: Чтение данных + МассивДанных = Новый Массив; + МассивВзносов = Новый Массив; + ПустыхПодряд = 0; + МаксПустых = 5; + КоличествоСтрок = ЛистРасчет.Rows.Count; + + Пока Истина Цикл + ФИО = ПрочитатьЯчейкуСтроку(ЛистРасчет, Ном, 0); - ВременныйФайл = КаталогВременныхФайлов() + "temp_data.xls"; - КопироватьФайл(Объект.ПутьКФайлу, ВременныйФайл); - - СтатусЗагрузки = "Открытие Excel..."; - Прогресс = 10; - Состояние("Открытие Excel...", 10); - - Excel = Новый COMОбъект("Excel.Application"); - Excel.Visible = Ложь; - Excel.DisplayAlerts = Ложь; - - Книга = Excel.Workbooks.Open(ВременныйФайл); - - СтатусЗагрузки = "Поиск листа 'Расчет'..."; - Прогресс = 15; - Состояние("Поиск листа 'Расчет'...", 15); - - ЛистРасчет = Неопределено; - Для Каждого Лист Из Книга.Sheets Цикл - Если ВРег(Лист.Name) = "РАСЧЕТ" Тогда - ЛистРасчет = Лист; - Прервать; - КонецЕсли; - КонецЦикла; - - Если ЛистРасчет = Неопределено Тогда - Сообщить("Лист 'Расчет' не найден!"); - Книга.Close(Ложь); - Excel.Quit(); - УдалитьФайлы(ВременныйФайл); - СтатусЗагрузки = "Ошибка: лист не найден"; - Состояние("Ошибка: лист 'Расчет' не найден", 0); - Прогресс = 0; - Возврат; + Если Не ЗначениеЗаполнено(ФИО) Тогда + ПустыхПодряд = ПустыхПодряд + 1; + Если ПустыхПодряд >= МаксПустых Тогда Прервать; КонецЕсли; + Ном = Ном + 1; + Продолжить; КонецЕсли; - СтатусЗагрузки = "Определение месяца..."; - Прогресс = 20; - Состояние("Определение месяца...", 20); - - МесяцЗначение = ЛистРасчет.Cells(4, 1).Value; - Если ЗначениеЗаполнено(МесяцЗначение) Тогда - Попытка - Объект.МесяцЗагрузки = Число(МесяцЗначение); - Исключение - Сообщить("Не удалось определить месяц: " + МесяцЗначение); - КонецПопытки; - КонецЕсли; - - СтатусЗагрузки = "Подсчет строк..."; - Прогресс = 25; - Состояние("Подсчет строк...", 25); - - МассивДанных = Новый Массив; - МассивВзносов = Новый Массив; - - СтатусЗагрузки = "Чтение данных..."; - ПустыхПодряд = 0; - МаксПустых = 5; - Ном = 16; - Пока Истина Цикл - - ФИО = ПрочитатьСтроку(ЛистРасчет, Ном, 1); - - Если Не ЗначениеЗаполнено(ФИО) Тогда - ПустыхПодряд = ПустыхПодряд + 1; - Если ПустыхПодряд >= МаксПустых Тогда - Прервать; - КонецЕсли; - Ном = Ном + 1; - Продолжить; - КонецЕсли; - - ПустыхПодряд = 0; - - Если СтрНачинаетсяС(ВРег(ФИО), "ИТОГО") Тогда - Прервать; - КонецЕсли; - - // Статус: загрузка расчетов - СтатусЗагрузки = "Расчет ЗП: " + ФИО + " (строка " + Ном + ")"; - Состояние("Расчет ЗП: " + ФИО, 25 + 65 * (Ном - 16) / Макс(Ном, 1)); - - Строка = Новый Структура; - Строка.Вставить("ФИО", ФИО); - Строка.Вставить("Должность", ПрочитатьСтроку(ЛистРасчет, Ном, 2)); - Строка.Вставить("СчетБК", ПрочитатьСтроку(ЛистРасчет, Ном, 3)); - Строка.Вставить("ВидЗанятости", ПрочитатьСтроку(ЛистРасчет, Ном, 4)); - Строка.Вставить("Оклад", ПрочитатьЯчейку(ЛистРасчет, Ном, 8, ФИО, "Оклад")); - Строка.Вставить("КоличествоСтавок", ПрочитатьЯчейку(ЛистРасчет, Ном, 7, ФИО, "Кол-во ставок")); - Строка.Вставить("ОтработаноДней", ПрочитатьЯчейку(ЛистРасчет, Ном, 6, ФИО, "ОтработаноДней")); - Строка.Вставить("ИтогоНачислено", ПрочитатьЯчейку(ЛистРасчет, Ном, 39, ФИО, "Итого начислено")); - Строка.Вставить("НДФЛ", ПрочитатьЯчейку(ЛистРасчет, Ном, 40, ФИО, "НДФЛ")); - Строка.Вставить("ИтогоУдержано", ПрочитатьЯчейку(ЛистРасчет, Ном, 53, ФИО, "Итого удержано")); - Строка.Вставить("ВсегоНаРуки", ПрочитатьЯчейку(ЛистРасчет, Ном, 55, ФИО, "Всего на руки")); - - // Чтение личных данных из листа сотрудника - ЛистСотрудника = Неопределено; - Для Каждого Лист Из Книга.Sheets Цикл - Если ВРег(Лист.Name) = ВРег(ФИО) Тогда - ЛистСотрудника = Лист; - Прервать; - КонецЕсли; - КонецЦикла; - - Если ЛистСотрудника <> Неопределено Тогда - Строка.Вставить("ИНН", ИзвлечьЗначениеИзТекста(ПрочитатьСтроку(ЛистСотрудника, 0, 10), "ИНН")); - Строка.Вставить("СНИЛС", ИзвлечьЗначениеИзТекста(ПрочитатьСтроку(ЛистСотрудника, 1, 10), "СНИЛС")); - Строка.Вставить("Паспорт", ИзвлечьЗначениеИзТекста(ПрочитатьСтроку(ЛистСотрудника, 2, 10), "Паспорт")); - Строка.Вставить("Адрес", ПрочитатьСтроку(ЛистСотрудника, 3, 10)); - Иначе - Строка.Вставить("ИНН", ""); - Строка.Вставить("СНИЛС", ""); - Строка.Вставить("Паспорт", ""); - Строка.Вставить("Адрес", ""); - КонецЕсли; - - МассивДанных.Добавить(Строка); - - // Страховые взносы - СтатусЗагрузки = "Страховые взносы: " + ФИО; - СВ = ПрочитатьЯчейку(ЛистРасчет, Ном, 63, ФИО, "СВ итого"); - Если СВ > 0 Тогда - СтрВзносов = Новый Структура; - СтрВзносов.Вставить("ФИО", ФИО); - СтрВзносов.Вставить("ДТ6Процент", ПрочитатьЯчейку(ЛистРасчет, Ном, 58, ФИО, "ДТ 6%")); - СтрВзносов.Вставить("ДТ4Процент", ПрочитатьЯчейку(ЛистРасчет, Ном, 59, ФИО, "ДТ 4%")); - СтрВзносов.Вставить("ПФСтраховая", ПрочитатьЯчейку(ЛистРасчет, Ном, 60, ФИО, "ПФ")); - СтрВзносов.Вставить("ФССФОМС", ПрочитатьЯчейку(ЛистРасчет, Ном, 61, ФИО, "ФСС/ФОМС")); - СтрВзносов.Вставить("НСПЗ", ПрочитатьЯчейку(ЛистРасчет, Ном, 62, ФИО, "НС и ПЗ")); - СтрВзносов.Вставить("Итого", СВ); - МассивВзносов.Добавить(СтрВзносов); - КонецЕсли; - - Ном = Ном + 1; - + Если СтрНачинаетсяС(ВРег(ФИО), "ИТОГО") Тогда Прервать; КонецЕсли; + + ПрогрессЗаписи = 25 + 65 * (Ном - 1) / Макс(КоличествоСтрок, 1); + Состояние("Расчет ЗП: " + ФИО, ПрогрессЗаписи); + + // Чтение расчетных данных + Строка = ПрочитатьСтрокуРасчета(ЛистРасчет, Ном, ФИО, ИндексЗаголовков); + + // Чтение личных данных + ЛичныеДанные = ПрочитатьЛичныеДанные(КонтекстExcel.Книга, ФИО); + Для Каждого КлючЗначение Из ЛичныеДанные Цикл + Строка.Вставить(КлючЗначение.Ключ, КлючЗначение.Значение); КонецЦикла; - СтатусЗагрузки = "Закрытие Excel..."; - Прогресс = 95; - Состояние("Закрытие Excel...", 95); + МассивДанных.Добавить(Строка); - Книга.Close(Ложь); - Excel.Quit(); - УдалитьФайлы(ВременныйФайл); + // Чтение страховых взносов + СтрВзносов = ПрочитатьСтрокуВзносов(ЛистРасчет, Ном, ФИО, ИндексЗаголовков); + Если СтрВзносов <> Неопределено Тогда + МассивВзносов.Добавить(СтрВзносов); + КонецЕсли; - СтатусЗагрузки = "Передача данных на сервер..."; - Прогресс = 98; - Состояние("Передача данных на сервер...", 98); - - ЗаполнитьТаблицыНаСервере(МассивДанных, МассивВзносов); - - // Обновление табличных частей на форме - Элементы.ТаблицаРасчетЗП.ОбновитьСтроки(); - Элементы.ТаблицаСтраховыеВзносы.ОбновитьСтроки(); - - Прогресс = 100; - СтатусЗагрузки = "Готово! Загружено: " + МассивДанных.Количество() + " сотрудников"; - Состояние("Готово! Загружено: " + МассивДанных.Количество() + " сотрудников", 100); - Сообщить(СтатусЗагрузки); - - Исключение - Сообщить("Ошибка чтения Excel: " + ОписаниеОшибки()); - СтатусЗагрузки = "Ошибка: " + ОписаниеОшибки(); - Состояние("Ошибка: " + ОписаниеОшибки(), 0); - Прогресс = 0; - КонецПопытки; + Ном = Ном + 1; + КонецЦикла; + + // Этап 8: Закрытие Excel + СтатусЗагрузки = "Закрытие Excel..."; + Состояние("Закрытие Excel...", 95); + ЗакрытьExcel(КонтекстExcel, ВременныйФайл); + + // Этап 9: Передача на сервер + СтатусЗагрузки = "Передача данных на сервер..."; + Состояние("Передача данных на сервер...", 98); + ЗаполнитьТаблицыНаСервере(МассивДанных, МассивВзносов); + + // Этап 10: Обновление формы + Прогресс = 100; + СтатусЗагрузки = "Готово! Загружено: " + МассивДанных.Количество() + " сотрудников"; + Состояние("Готово! Загружено: " + МассивДанных.Количество() + " сотрудников", 100); + Сообщить(СтатусЗагрузки); + + // Обновление табличных частей + Элементы.ТаблицаРасчетЗП.ОбновитьСтроки(); + Элементы.ТаблицаСтраховыеВзносы.ОбновитьСтроки(); КонецПроцедуры @@ -266,10 +411,16 @@ #Область СерверныеПроцедуры +// ============================================================================ +// ДОМЕН: Серверная обработка данных +// Ответственность: заполнение таблиц значений, запись в 1С +// ============================================================================ + &НаСервере Процедура ИнициализироватьТаблицы() КонецПроцедуры +// Заполняет таблицы значений на сервере из массивов структур. &НаСервере Процедура ЗаполнитьТаблицыНаСервере(МассивДанных, МассивВзносов) ТЗРасчет = РеквизитФормыВЗначение("Объект.ДанныеРасчетаЗП"); @@ -289,6 +440,7 @@ ЗначениеВРеквизитФормы(ТЗВзносы, "Объект.ДанныеСтраховыхВзносов"); КонецПроцедуры +// Записывает данные в документы 1С. &НаСервере Процедура ЗаписатьДанныеНаСервере() ГодЗагрузки = ТекущаяДата().Год();