Работа с внешними печатными формами в формате .odt (OpenDocument Text) через COM-соединение с LibreOffice или OpenOffice — это мощный инструмент, позволяющий пользователям легко редактировать сформированные документы. Однако при автоматизации заполнения табличных частей программисты часто сталкиваются с логической ловушкой: в документе появляется «лишняя» пустая строка. Разберем эту ситуацию подробно, проанализируем причины возникновения ошибки и изучим правильные методы программного управления таблицами Writer.
Рассмотрим ситуацию, с которой столкнулся автор темы. При заполнении таблицы в цикле используется метод Rows.insertByIndex(Итератор, 1). Выясним причину некорректного поведения программы. Дело в том, что в заранее подготовленном шаблоне .odt таблица уже имеет определенную структуру. Как правило, в ней есть строка-заголовок (шапка) и как минимум одна пустая строка, в которой настроены шрифты, отступы и границы — так называемая «строка-образец».
Проанализируем логику выполнения кода:
Для Каждого вызывается метод insertByIndex.Посмотрим на фрагмент исходного кода автора, содержащий ошибку:
// Ошибочный подход
Для Каждого СтруктураТовара Из МассивСтруктурТоваров Цикл
СтрокаДок = Rows.insertByIndex(Итератор, 1); // Вставка строки на каждой итерации
Table.getCellByPosition(0, Итератор - 1).setString(СтруктураТовара.Номер);
// ... заполнение остальных ячеек
Если НЕ (Счетчик2 = СчетчикКоличестваСтрокВТЧ) Тогда
Итератор = Итератор + 1;
КонецЕсли;
Счетчик2 = Счетчик2 + 1;
КонецЦикла;
Самый простой способ избежать появления лишней строки — это использовать уже существующую в шаблоне строку для первой записи и вставлять новые строки только начиная со второй итерации. Разберем, как правильно модифицировать алгоритм. Мы должны понимать, что API LibreOffice использует индексацию строк и столбцов, начинающуюся с 0. Если индекс 0 занят шапкой, то индекс 1 — это наша первая строка данных.
Выполним следующие шаги для исправления кода:
Рассмотрим пример исправленного кода:
Итератор = 1; // Индекс первой пустой строки данных в шаблоне
ВсегоСтрок = МассивСтруктурТоваров.Количество();
Для ИндексМассива = 0 По ВсегоСтрок - 1 Цикл
СтруктураТовара = МассивСтруктурТоваров[ИндексМассива];
// Если мы уже обработали первую строку, для последующих нужно создать место
Если ИндексМассива > 0 Тогда
Rows.insertByIndex(Итератор, 1);
КонецЕсли;
// Заполняем ячейки текущей строки
Table.getCellByPosition(0, Итератор).setString(СтруктураТовара.Номер);
Table.getCellByPosition(1, Итератор).setString(СтруктураТовара.Наименование);
Table.getCellByPosition(2, Итератор).setString(СтруктураТовара.Артикул);
Table.getCellByPosition(4, Итератор).setString(СтруктураТовара.Количество);
Table.getCellByPosition(5, Итератор).setString(Строка(СтруктураТовара.Цена));
Table.getCellByPosition(6, Итератор).setString(Строка(СтруктураТовара.СуммаСНДС));
Итератор = Итератор + 1;
КонецЦикла;
Проанализируем более надежный метод, который часто используют профессиональные разработчики. Вместо того чтобы привязываться к жестким индексам строк (getCellByPosition), можно использовать текстовые маркеры (плейсхолдеры) внутри ячеек таблицы, например: [ТоварНаименование], [ТоварКол] и так далее.
Рассмотрим алгоритм этого метода:
Этот подход исключает ошибки с «лишними строками», так как если в 1С данных нет, маркерная строка может быть просто удалена или скрыта.
Выясним несколько критических моментов, которые помогут сделать вашу печатную форму стабильной и быстрой:
1. Оптимизация скорости заполнения. Работа через COM-соединение с внешним приложением происходит медленно. Чтобы ускорить процесс, рекомендуется отключать визуальное обновление документа на время формирования таблицы. Используйте методы LockControllers() и UnlockControllers() объекта документа.
2. Принудительное завершение процессов. После того как документ сформирован и выведен на экран или сохранен, объект 1С должен освободить COM-ссылки. В противном случае в диспетчере задач сервера могут накапливаться «фантомные» процессы soffice.bin, что приведет к утечке памяти.
3. Типизация данных. Метод setString() ожидает строковое значение. При передаче чисел или дат из 1С обязательно используйте функцию Строка() или форматную строку, чтобы избежать ошибок типов на стороне COM-сервера.
4. Обработка пустых таблиц. Всегда предусматривайте проверку на наличие данных. Если табличная часть документа 1С пуста, решите заранее: нужно ли выводить пустую строку с рамками или полностью удалить таблицу из документа .odt. Для удаления строк используйте метод Rows.removeByIndex(НачальныйИндекс, Количество).
Подводя итог, можно сказать, что работа с insertByIndex требует внимательного отношения к структуре исходного шаблона. Основная ошибка — забывать о том, что шаблон уже содержит одну строку для данных, и вставлять лишнюю при первой же итерации цикла. Следуя предложенным рекомендациям по управлению индексами, вы сможете формировать безупречные печатные формы без лишних пустых строк.