При интеграции систем учета с банковскими сервисами типа «Клиент-Банк» (в частности, при выгрузке реестров на зачисление зарплаты) разработчики часто сталкиваются с нестандартными форматами обмена. Один из таких форматов требует, чтобы вся табличная часть со списком сотрудников и суммами передавалась строго в пределах одной строки с разделителями, например, внутри блока ^_Table=...^.
Разберем типичную проблему: при вызове метода ДобавитьСтроку() внутри цикла обхода строк документа или таблицы значений объект Текст автоматически добавляет перевод строки. В результате файл разбивается на множество отдельных строчек, и банковский парсер выдает ошибку формата. Рассмотрим, как правильно сформировать единую строку, а также проанализируем нюансы работы платформы 1С:Предприятие 7.7 с большими объемами текста.
Проанализируем исходный фрагмент кода, в котором происходила ошибка:
Т.ДобавитьСтроку("^_Table=");
Пока ПолучитьСтроку() = 1 Цикл
Т.ДобавитьСтроку("Npp1="+СокрЛП(НомерСтроки)+"~Name1="+СокрЛП(Сотрудник)+"~Nch1="+"~Nch2="+СокрЛП(Сотрудник.ЛицевойСчет)+"~Sum1="+СокрЛП(Число(Сумма))+"~"+"^");
КонецЦикла;
Каждый вызов метода ДобавитьСтроку() встроенного объекта Текст добавляет в результирующий текстовый документ символ перевода строки (CRLF). Поэтому префикс ^_Table= и записи каждого отдельного сотрудника оказываются на новых строках. Для решения задачи необходимо предварительно накопить всю цепочку данных в строковую переменную внутри цикла и лишь затем единовременно отправить ее в файл.
Рассмотрим основной способ решения, предложенный на форуме. Разберем его по шагам:
^_Table=.Пока ПолучитьСтроку() = 1 Цикл выполняем конкатенацию сведений о сотруднике, разделяя поля тильдой ~.^ и вызываем Т.ДобавитьСтроку() ровно один раз для всей собранной конструкции.Посмотрим на исправленный код процедуры выгрузки:
СтрочкаВывода = "^_Table=";
Пока ПолучитьСтроку() = 1 Цикл
СтрочкаВывода = СтрочкаВывода + "Npp1=" + СокрЛП(НомерСтроки)
+ "~Name1=" + СокрЛП(Сотрудник)
+ "~Nch1="
+ "~Nch2=" + СокрЛП(Сотрудник.ЛицевойСчет)
+ "~Sum1=" + СокрЛП(Число(Сумма)) + "~";
КонецЦикла;
// Закрываем блок символом циркумфлекса и добавляем в объект Текст одной строкой
Т.ДобавитьСтроку(СтрочкаВывода + "^");
В результате весь массив информации попадает в файл единой непрерывной строкой требуемого вида:
^_Table=Npp1=1~Name1=Иванов Иван Иванович~Nch1=~Nch2=720000159~Sum1=150000~Npp1=2~Name1=Петров Петр Петрович~Nch1=~Nch2=720000147~Sum1=540000~^
При использовании стандартной конкатенации необходимо учитывать особенности платформы 1С 7.7:
Текст корректно выгружает длинные строки в файл через метод Записать(). Однако если после формирования вызвать метод Т.Показать() или попытаться вывести эту строку в окно сообщений через Сообщить(), платформа аварийно завершит работу с ошибкой: «Одна из строк исходного текста превышает допустимые размеры» (лимит составляет около 500 символов на одну визуальную строку). Не вызывайте метод Показать() для файлов такого формата.Строка = Строка + НовыеДанные на реестрах из сотен и тысяч сотрудников платформа постоянно перевыделяет оперативную память. Скорость склеивания существенно падает с каждой новой строкой.Если в реестре зарплаты содержится большое количество сотрудников, чтобы избежать переполнения памяти и ограничений платформы, применим потоковую запись через системный COM-объект Windows Scripting.FileSystemObject. Метод Write() записывает данные в файл напрямую без перевода строки:
ФСО = СоздатьОбъект("Scripting.FileSystemObject");
Файл = ФСО.CreateTextFile("E:\query.txt", 1); // 1 - перезапись файла
// Записываем открывающий блок
Файл.Write("^_Table=");
ВыбратьСтроки();
Пока ПолучитьСтроку() = 1 Цикл
СтрСотрудника = "Npp1=" + СокрЛП(НомерСтроки)
+ "~Name1=" + СокрЛП(Сотрудник)
+ "~Nch1="
+ "~Nch2=" + СокрЛП(Сотрудник.ЛицевойСчет)
+ "~Sum1=" + СокрЛП(Формат(Сумма, "Ч15.2.")) + "~";
// Записываем порцию данных без перевода строки
Файл.Write(СтрСотрудника);
КонецЦикла;
// Закрываем секцию и переводим строку
Файл.WriteLine("^");
// Далее можно записывать остальные параметры через WriteLine()
Файл.WriteLine("^AccountCUR=" + СокрЛП(Формат(Итог("Сумма"), "Ч016.2. ")) + "^");
Файл.Close();
Сообщить("Выгрузка успешно завершена потоковым методом!");
Выясним частые ошибки при выгрузке реквизитов, способные нарушить разбор файла банком:
СокрЛП(Число(Сумма)) для целых чисел отсекает нулевые копейки (получится 150 вместо 150.00). Для финансовых реестров критически важно сохранять разрядность копеек. Используйте функцию Формат(Сумма, "Ч15.2.") или специализированные шаблоны форматирования сумм, принятые банком.~ или циркумфлекс ^, структура файла нарушится. Перед добавлением значений рекомендуется экранировать или вырезать их через СтрЗаменить(СокрЛП(Сотрудник), "~", "").