При работе с файлами, например, Microsoft Excel, часто возникает задача загрузить данные в 1С, но не из всего файла целиком, а только с одного конкретного листа. Стандартный метод Прочитать() объекта ТабличныйДокумент загружает все листы файла. В этой статье мы подробно разберем, как после загрузки такого многостраничного документа извлечь из него нужный лист и сформировать на его основе совершенно новый, одностраничный табличный документ.
Проанализируем несколько подходов, от самого простого и лаконичного до более гибких, а также рассмотрим важные рекомендации по стилю кода, которые помогут сделать вашу разработку более качественной и читаемой.
ПолучитьОбласть() по имени листаЭто самый прямой и элегантный способ для решения нашей задачи. Разберемся в механике его работы. Когда платформа 1С читает файл Excel с помощью метода Прочитать(), она не просто загружает ячейки. Каждый лист исходного файла автоматически преобразуется в именованную область внутри объекта ТабличныйДокумент. Имя этой области в точности соответствует названию листа в Excel (например, "Лист1", "Sheet1", "Отчет по продажам" и т.д.).
Эти именованные области хранятся в коллекции Области табличного документа. Мы можем обратиться к конкретной области по ее индексу (нумерация начинается с 0) и получить объект типа ОбластьЯчеекТабличногоДокумента. У этого объекта есть свойство Имя, которое нам и нужно.
Метод ПолучитьОбласть(ИмяОбласти), вызванный у исходного табличного документа с передачей ему имени нужного листа, возвращает совершенно новый объект типа ТабличныйДокумент, который содержит только копию указанной именованной области. Это именно то, что нам требуется.
Посмотрим на пример кода:
Представим, что у нас есть функция, которая должна прочитать файл и вернуть табличный документ, содержащий только первый лист.
&НаСервере
Функция ПолучитьПервыйЛистИзФайла(ИмяФайла)
// 1. Создаем объект для чтения исходного файла
ИсходныйДокумент = Новый ТабличныйДокумент;
ИсходныйДокумент.Прочитать(ИмяФайла);
// 2. Проверяем, есть ли в документе вообще области (листы)
Если ИсходныйДокумент.Области.Количество() = 0 Тогда
// Возвращаем пустой документ или вызываем исключение
Возврат Новый ТабличныйДокумент;
КонецЕсли;
// 3. Получаем объект области первого листа по индексу 0
ОбластьПервогоЛиста = ИсходныйДокумент.Области[0];
// 4. Получаем имя этой области
ИмяПервогоЛиста = ОбластьПервогоЛиста.Имя;
// 5. Вызываем метод ПолучитьОбласть() с этим именем
// Метод вернет НОВЫЙ табличный документ
Результат = ИсходныйДокумент.ПолучитьОбласть(ИмяПервогоЛиста);
Возврат Результат;
КонецФункции
Этот код можно сделать более лаконичным, объединив шаги 3, 4 и 5 в одну строку, как это в итоге и было сделано в обсуждаемой теме на форуме:
&НаСервере
Функция ПолучитьПервыйЛистИзФайла(ИмяФайла)
ИсходныйДокумент = Новый ТабличныйДокумент;
ИсходныйДокумент.Прочитать(ИмяФайла);
Если ИсходныйДокумент.Области.Количество() > 0 Тогда
// Сразу получаем имя области по индексу и передаем в метод
ДокументСОднимЛистом = ИсходныйДокумент.ПолучитьОбласть(ИсходныйДокумент.Области[0].Имя);
Возврат ДокументСОднимЛистом;
Иначе
Возврат Новый ТабличныйДокумент;
КонецЕсли;
КонецФункции
Преимущества этого подхода:
Этот подход более "ручной" и многословный, но он дает больше гибкости. Например, если нам нужно не просто скопировать один лист, а собрать итоговый документ из нескольких областей разных листов. Существует два основных способа скопировать область в новый документ: через метод Вывести() и через ВставитьОбласть().
Вывести()Метод Вывести() предназначен для последовательного добавления областей в табличный документ, обычно одна под другой. Чтобы использовать его для копирования целого листа, нам нужно сначала получить область этого листа, а затем вывести ее в новый, пустой документ.
Рассмотрим по шагам:
Верх, Низ, Лево, Право), получаем саму область ячеек через метод ПолучитьОбласть() с координатами.Вывести() и передаем ему полученную область.Пример кода:
&НаСервере
Функция ПолучитьЛистЧерезВывод(ИмяФайла)
// 1. Читаем исходный файл
ИсходныйДокумент = Новый ТабличныйДокумент;
ИсходныйДокумент.Прочитать(ИмяФайла, СпособЧтенияЗначенийТабличногоДокумента.Значение);
Если ИсходныйДокумент.Области.Количество() = 0 Тогда
Возврат Новый ТабличныйДокумент;
КонецЕсли;
// 2. Получаем объект области первого листа
ОбластьПервогоЛиста = ИсходныйДокумент.Области[0];
// 3. Получаем область ячеек по координатам
ОбластьДляВывода = ИсходныйДокумент.ПолучитьОбласть(
ОбластьПервогоЛиста.Верх,
ОбластьПервогоЛиста.Лево,
ОбластьПервогоЛиста.Низ,
ОбластьПервогоЛиста.Право
);
// 4. Создаем новый пустой документ для результата
ДокументРезультат = Новый ТабличныйДокумент;
// 5. Выводим область в новый документ
ДокументРезультат.Вывести(ОбластьДляВывода);
Возврат ДокументРезультат;
КонецФункции
Важное замечание: Как показывает практика, метод Вывести() иногда может вести себя непредсказуемо при работе с большими и сложными областями, например, добавлять пустые строки или столбцы. Его основное предназначение — последовательный вывод макетов при формировании отчетов.
ВставитьОбласть()Метод ВставитьОбласть() работает более предсказуемо, так как он предназначен для точного копирования одной области в другую с указанием координат целевой ячейки. Этот метод идеально подходит, когда нужно точно сохранить геометрию исходного листа.
Пример кода:
&НаСервере
Функция ПолучитьЛистЧерезВставку(ИмяФайла)
// 1. Читаем исходный файл
ИсходныйДокумент = Новый ТабличныйДокумент;
ИсходныйДокумент.Прочитать(ИмяФайла);
Если ИсходныйДокумент.Области.Количество() = 0 Тогда
Возврат Новый ТабличныйДокумент;
КонецЕсли;
// 2. Получаем область первого листа
ОбластьПервогоЛиста = ИсходныйДокумент.Области[0];
// 3. Создаем новый пустой документ для результата
ДокументРезультат = Новый ТабличныйДокумент;
// 4. Определяем целевую область в новом документе (начиная с ячейки R1C1)
ЦелеваяОбласть = ДокументРезультат.Область(1, 1);
// 5. Вставляем область исходного листа в новый документ
ДокументРезультат.ВставитьОбласть(ОбластьПервогоЛиста, ЦелеваяОбласть);
Возврат ДокументРезультат;
КонецФункции
Этот вариант является надежной альтернативой первому решению, хотя и требует больше строк кода.
В ходе обсуждения на форуме были высказаны справедливые замечания по поводу качества кода. Давайте их учтем, чтобы писать не просто работающий, а профессиональный код.
Файл сначала хранила полный документ, а затем — только извлеченный лист. Это плохая практика, так как она затрудняет чтение кода и может привести к ошибкам. Всегда создавайте новые переменные для хранения результатов обработки: ИсходныйДокумент, ДокументЛиста и т.п.ТабличныйДокумент именем "Файл" — некорректно. В 1С есть отдельный объект Файл для работы с файловой системой. Такое именование может запутать другого программиста, который будет разбираться в вашем коде.ИсходныйДокумент.Области[0], он бы сразу увидел все его свойства (Имя, Верх, Низ и т.д.) и быстро нашел бы решение. Умение пользоваться отладчиком — ключевой навык разработчика, экономящий часы работы.