v3.0.0.4: DDD-рефакторинг, динамические заголовки, архив версий

This commit is contained in:
Профи-Софт
2026-07-07 18:14:39 +00:00
parent 311969db49
commit f82c1027bc
@@ -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; Значение = Лист.Cells(Строка, Колонка).Value;
Если Значение = Неопределено ИЛИ Значение = "" Тогда Если Значение = Неопределено ИЛИ Значение = "" Тогда
@@ -56,15 +92,16 @@
КонецЕсли; КонецЕсли;
Возврат Число(Значение); Возврат Число(Значение);
Исключение Исключение
Сообщить("Ошибка: " + ФИО + " | " + ВидДанных Сообщить("Ошибка чтения числа: " + КонтекстОшибки
+ " | строка " + Строка + " колонка " + Колонка + " | строка " + Строка + " колонка " + Колонка
+ " | значение: """ + Значение + """ | " + ОписаниеОшибки()); + " | значение: """ + Значение + """ | " + ОписаниеОшибки());
Возврат 0; Возврат 0;
КонецПопытки; КонецПопытки;
КонецФункции КонецФункции
// Читает строковое значение ячейки.
&НаКлиенте &НаКлиенте
Функция ПрочитатьСтроку(Лист, Строка, Колонка) Функция ПрочитатьЯчейкуСтрока(Лист, Строка, Колонка)
Попытка Попытка
Значение = Лист.Cells(Строка, Колонка).Value; Значение = Лист.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НаКлиенте() Процедура ПрочитатьExcelНаКлиенте()
Попытка // Этап 1: Подготовка файла
СтатусЗагрузки = "Копирование файла..."; СтатусЗагрузки = "Копирование файла...";
Прогресс = 5; Состояние("Копирование файла...", 5);
Состояние("Копирование файла...", 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"; Если Не ЗначениеЗаполнено(ФИО) Тогда
КопироватьФайл(Объект.ПутьКФайлу, ВременныйФайл); ПустыхПодряд = ПустыхПодряд + 1;
Если ПустыхПодряд >= МаксПустых Тогда Прервать; КонецЕсли;
СтатусЗагрузки = "Открытие Excel..."; Ном = Ном + 1;
Прогресс = 10; Продолжить;
Состояние("Открытие Excel...", 10);
Excel = Новый COMОбъект("Excel.Application");
Excel.Visible = Ложь;
Excel.DisplayAlerts = Ложь;
Книга = Excel.Workbooks.Open(ВременныйФайл);
СтатусЗагрузки = "Поиск листа 'Расчет'...";
Прогресс = 15;
Состояние("Поиск листа 'Расчет'...", 15);
ЛистРасчет = Неопределено;
Для Каждого Лист Из Книга.Sheets Цикл
Если ВРег(Лист.Name) = "РАСЧЕТ" Тогда
ЛистРасчет = Лист;
Прервать;
КонецЕсли;
КонецЦикла;
Если ЛистРасчет = Неопределено Тогда
Сообщить("Лист 'Расчет' не найден!");
Книга.Close(Ложь);
Excel.Quit();
УдалитьФайлы(ВременныйФайл);
СтатусЗагрузки = "Ошибка: лист не найден";
Состояние("Ошибка: лист 'Расчет' не найден", 0);
Прогресс = 0;
Возврат;
КонецЕсли; КонецЕсли;
СтатусЗагрузки = "Определение месяца...";
Прогресс = 20;
Состояние("Определение месяца...", 20);
МесяцЗначение = ЛистРасчет.Cells(4, 1).Value;
Если ЗначениеЗаполнено(МесяцЗначение) Тогда
Попытка
Объект.МесяцЗагрузки = Число(МесяцЗначение);
Исключение
Сообщить("Не удалось определить месяц: " + МесяцЗначение);
КонецПопытки;
КонецЕсли;
СтатусЗагрузки = "Подсчет строк...";
Прогресс = 25;
Состояние("Подсчет строк...", 25);
МассивДанных = Новый Массив;
МассивВзносов = Новый Массив;
СтатусЗагрузки = "Чтение данных...";
ПустыхПодряд = 0; ПустыхПодряд = 0;
МаксПустых = 5;
Ном = 16;
Пока Истина Цикл Если СтрНачинаетсяС(ВРег(ФИО), "ИТОГО") Тогда Прервать; КонецЕсли;
ФИО = ПрочитатьСтроку(ЛистРасчет, Ном, 1); ПрогрессЗаписи = 25 + 65 * (Ном - 1) / Макс(КоличествоСтрок, 1);
Состояние("Расчет ЗП: " + ФИО, ПрогрессЗаписи);
Если Не ЗначениеЗаполнено(ФИО) Тогда
ПустыхПодряд = ПустыхПодряд + 1; // Чтение расчетных данных
Если ПустыхПодряд >= МаксПустых Тогда Строка = ПрочитатьСтрокуРасчета(ЛистРасчет, Ном, ФИО, ИндексЗаголовков);
Прервать;
КонецЕсли; // Чтение личных данных
Ном = Ном + 1; ЛичныеДанные = ПрочитатьЛичныеДанные(КонтекстExcel.Книга, ФИО);
Продолжить; Для Каждого КлючЗначение Из ЛичныеДанные Цикл
КонецЕсли; Строка.Вставить(КлючЗначение.Ключ, КлючЗначение.Значение);
ПустыхПодряд = 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;
КонецЦикла; КонецЦикла;
СтатусЗагрузки = "Закрытие Excel..."; МассивДанных.Добавить(Строка);
Прогресс = 95;
Состояние("Закрытие Excel...", 95);
Книга.Close(Ложь); // Чтение страховых взносов
Excel.Quit(); СтрВзносов = ПрочитатьСтрокуВзносов(ЛистРасчет, Ном, ФИО, ИндексЗаголовков);
УдалитьФайлы(ВременныйФайл); Если СтрВзносов <> Неопределено Тогда
МассивВзносов.Добавить(СтрВзносов);
КонецЕсли;
СтатусЗагрузки = "Передача данных на сервер..."; Ном = Ном + 1;
Прогресс = 98; КонецЦикла;
Состояние("Передача данных на сервер...", 98);
// Этап 8: Закрытие Excel
ЗаполнитьТаблицыНаСервере(МассивДанных, МассивВзносов); СтатусЗагрузки = "Закрытие Excel...";
Состояние("Закрытие Excel...", 95);
// Обновление табличных частей на форме ЗакрытьExcel(КонтекстExcel, ВременныйФайл);
Элементы.ТаблицаРасчетЗП.ОбновитьСтроки();
Элементы.ТаблицаСтраховыеВзносы.ОбновитьСтроки(); // Этап 9: Передача на сервер
СтатусЗагрузки = "Передача данных на сервер...";
Прогресс = 100; Состояние("Передача данных на сервер...", 98);
СтатусЗагрузки = "Готово! Загружено: " + МассивДанных.Количество() + " сотрудников"; ЗаполнитьТаблицыНаСервере(МассивДанных, МассивВзносов);
Состояние("Готово! Загружено: " + МассивДанных.Количество() + " сотрудников", 100);
Сообщить(СтатусЗагрузки); // Этап 10: Обновление формы
Прогресс = 100;
Исключение СтатусЗагрузки = "Готово! Загружено: " + МассивДанных.Количество() + " сотрудников";
Сообщить("Ошибка чтения Excel: " + ОписаниеОшибки()); Состояние("Готово! Загружено: " + МассивДанных.Количество() + " сотрудников", 100);
СтатусЗагрузки = "Ошибка: " + ОписаниеОшибки(); Сообщить(СтатусЗагрузки);
Состояние("Ошибка: " + ОписаниеОшибки(), 0);
Прогресс = 0; // Обновление табличных частей
КонецПопытки; Элементы.ТаблицаРасчетЗП.ОбновитьСтроки();
Элементы.ТаблицаСтраховыеВзносы.ОбновитьСтроки();
КонецПроцедуры КонецПроцедуры
@@ -266,10 +411,16 @@
#Область СерверныеПроцедуры #Область СерверныеПроцедуры
// ============================================================================
// ДОМЕН: Серверная обработка данных
// Ответственность: заполнение таблиц значений, запись в 1С
// ============================================================================
&НаСервере &НаСервере
Процедура ИнициализироватьТаблицы() Процедура ИнициализироватьТаблицы()
КонецПроцедуры КонецПроцедуры
// Заполняет таблицы значений на сервере из массивов структур.
&НаСервере &НаСервере
Процедура ЗаполнитьТаблицыНаСервере(МассивДанных, МассивВзносов) Процедура ЗаполнитьТаблицыНаСервере(МассивДанных, МассивВзносов)
ТЗРасчет = РеквизитФормыВЗначение("Объект.ДанныеРасчетаЗП"); ТЗРасчет = РеквизитФормыВЗначение("Объект.ДанныеРасчетаЗП");
@@ -289,6 +440,7 @@
ЗначениеВРеквизитФормы(ТЗВзносы, "Объект.ДанныеСтраховыхВзносов"); ЗначениеВРеквизитФормы(ТЗВзносы, "Объект.ДанныеСтраховыхВзносов");
КонецПроцедуры КонецПроцедуры
// Записывает данные в документы 1С.
&НаСервере &НаСервере
Процедура ЗаписатьДанныеНаСервере() Процедура ЗаписатьДанныеНаСервере()
ГодЗагрузки = ТекущаяДата().Год(); ГодЗагрузки = ТекущаяДата().Год();