В статье рассмотрены варианты загрузки файлов Excel и табличных документов в объекты 1С, на примере таблиц значений. Если вам нужно загрузить файл Excel с одним или несколькими листами (не важно, xls или xlsx, или даже ods), или прочитать средствами 1С табличный документ mxl – читайте эту статью. Приводятся примеры кода, которые вы можете адаптировать под ваши задачи. Материал вышел большой, для удобства пользуйтесь навигацией по содержанию.
Содержание
Зачем писать свою загрузку? Ведь есть же типовые?
Во многих типовых конфигурациях на базе БСП имеется подсистема “Загрузка данных из файла”, кроме того, на ИТС можно найти обработку загрузки данных из табличного документа. Они позволяют загружать из внешних файлов данные во многие объекты: табличные части документов, справочники, регистры сведений. Кроме того, у этих обработок достаточно мощный функционал по сопоставлению данных из файла с объектами в базе 1С, разнообразные настройки, возможность создания элементов, в случае если они не найдены…
Так в чем же необходимость “изобретать велосипед”? На то несколько причин.
- Излишняя сложность. Ради универсальности приходится жертвовать простотой, и для рядового пользователя универсальные обработки могут оказаться сложнее, чем узкоспециализированная обработка, написанная под конкретный формат файла.
- Как ни странно, не стопроцентная универсальность. Действительно, как быть, если нам нужно загрузить не справочники, а планы видов характеристик? Или план расчета? Или на основании одного файла заполнить сразу несколько документов?
- Необходимость в специфичных алгоритмах. Например, при создании контрагента создавать также строго определенные договоры, или при загрузке в документ выполнять заполнение дополнительных, рассчетных колонок
- Сложные форматы исходных файлов. Например, исходный файл содержит несколько листов, и каждый из этих листов следует отдельно обработать. Второй пример – данные на листе сложно структурированы, и на одном листе могут содержаться несколько табличных частей, разделенных пустыми строками или колонками. Такие форматы встречаются, в частности, в отчетах зарубежных брокеров. На одном листе содержится информация и о сделках с финансовыми инструментами, и о движении денежных средств, и информация о ценных бумагах, и т.д.
В каком случае хороши универсальные загрузки из табличного документа?
Различные обработки загрузки из табличного документа отлично подходят, когда формат загружаемого файла не слишком сложный, а загрузка не предполагает множества дополнительных действий. Типичные примеры: загрузка прайс-листов, загрузка заказов, загрузка начальных остатков.
Подходящих случаев использования универсальных механизмов загрузки действительно много, иначе их не стали бы включать в библиотеку стандартных подсистем. Но если функциональности стандартных средств недостаточно, всегда можно создать свою собственную обработку. Ниже рассмотрены несколько приемов, которые можно использовать при загрузке файлов Excel и других табличных документов в 1С.
Особенности загрузки из файлов Excel с несколькими листами
При использовании метода табличного документа Прочитать(), файл Excel с несколькими листами читается так, что каждый лист помещается в отдельную именованную область ячеек, но при этом весь файл выводится в один табличный документ.
&НаКлиенте
Процедура ПрочитатьФайл(Команда)
ОбработкаОкончанияПомещения = Новый ОписаниеОповещения("ОбработчикОкончанияПомещения", ЭтотОбъект);
ПараметрыДиалога = Новый ПараметрыДиалогаПомещенияФайлов;
ПараметрыДиалога.Фильтр = "Excel файлы(*.xls;*.xlsx)|*.xls;*.xlsx";
НачатьПомещениеФайлаНаСервер(ОбработкаОкончанияПомещения, , , АдресВХ, ПараметрыДиалога, ЭтотОбъект.УникальныйИдентификатор);
КонецПроцедуры
&НаКлиенте
Процедура ОбработчикОкончанияПомещения(ОписаниеПомещенногоФайла, ДополнительныеПараметры) Экспорт
АдресФайла = ОписаниеПомещенногоФайла.Адрес;
ПрочитатьИзВХНаСервере(АдресФайла);
КонецПроцедуры
&НаСервере
Процедура ПрочитатьИзВХНаСервере(АдресВХ)
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xlsx");
ДД = ПолучитьИзВременногоХранилища(АдресВХ);
ДД.Записать(ИмяВременногоФайла);
СпособЧтения = СпособЧтенияЗначенийТабличногоДокумента.Текст;
//Рассмотрим пример, когда загружаем в 1С файл xlsx с листами
// Лист1, Лист2, Лист3, Лист4, Лист5
Попытка
ТабДок.Прочитать(ИмяВременногоФайла, СпособЧтения);
МассивИмен = Новый Массив;
Для Каждого Область Из ТабДок.Области Цикл
МассивИмен.Добавить(Область.Имя);
КонецЦикла;
Элементы.ИмяЛиста.СписокВыбора.ЗагрузитьЗначения(МассивИмен);
Исключение
КонецПопытки;
КонецПроцедуры
Загрузка с обходом строк и колонок
Для первого примера используем решение “в лоб”. Предположим, что количество и порядок колонок в файле известно заранее, и не меняется. Также будем считать постоянной и известной заранее первую строку, с которой следует начинать загрузку. Тогда нам достаточно в цикле пройти от первой строки до конца табличного документа.
Не следует путать методы табличного документа Область() и ПолучитьОбласть(). Первый возвращает область ячеек, а второй – новый табличный документ.
Если структура колонок таблицы, в которую мы загружаем, полностью идентична структуре колонок файла, мы можем загрузить данные, используя индексы.
&НаСервере
Процедура ПрочитатьВТаблицуЗначенийНаСервере()
//Работает и на сервере, и в тонком клиенте, возвращает область ячеек
ОбластьТЗ = ТабДок.Области.Лист2;
ОбластьТЗ = ТабДок.Область("Лист2");
//Работает только на сервере, возвращает табличный документ
Лист2 = ТабДок.ПолучитьОбласть("Лист2");
ТаблицаЗначений.Очистить();
ТЗ = ТаблицаЗначений.Выгрузить();
Для НомерСтроки = 6 По Лист2.ВысотаТаблицы Цикл
СтрТЗ = ТЗ.Добавить();
Для НомерКолонки = 2 По Лист2.ШиринаТаблицы Цикл
СтрТЗ[НомерКолонки-2] = Лист2.Область(НомерСтроки, НомерКолонки, НомерСтроки, НомерКолонки).Текст;
КонецЦикла;
КонецЦикла;
ТаблицаЗначений.Загрузить(ТЗ);
КонецПроцедуры
Если же состав колонок отличается, предпочтительнее использовать имена колонок. Обратите внимание, что при получении текста области, мы используем четыре параметра, чтобы получить область в виде конкретной ячейки. Но также можно указывать два параметра, если вы уверены, что в файле не будет объединенных ячеек, либо наоборот, указывать прямоугольную область объединенных ячеек – все зависит от конкретной задачи.
ТаблицаЗначений.Очистить();
ТЗ = ТаблицаЗначений.Выгрузить();
Для НомерСтроки = 6 По Лист2.ВысотаТаблицы Цикл
СтрТЗ = ТЗ.Добавить();
Наименование = Лист2.Область(НомерСтроки, 2, НомерСтроки, 2).Текст;
Количество = Лист2.Область(НомерСтроки, 3, НомерСтроки, 3).Текст;
Цена = Лист2.Область(НомерСтроки, 4, НомерСтроки, 4).Текст;
Сумма = Лист2.Область(НомерСтроки, 5, НомерСтроки, 5).Текст;
СтрТЗ.Наименование = Наименование;
СтрТЗ.Количество = Количество;
СтрТЗ.Цена = Цена;
СтрТЗ.Сумма = Сумма;
КонецЦикла;
ТаблицаЗначений.Загрузить(ТЗ);
С полученными данными можно дальше работать как угодно. Например, выполнить поиск товара по наименованию, и если он не найден – создать такой товар. Либо наоборот – вывести пользователю ошибку, что товар не удалось найти. Выбор подходящей бизнес-логики выходит за рамки данной статьи.
Загрузка табличного документа при помощи построителя отчета
В случае, когда у загружаемого файла есть строка с заголовками, можно выполнить загрузку из файла Excel, используя построитель отчета. В этом случае следует задать прямоугольную область ячеек, включая строку заголовков. В результате получится объект РезультатЗапроса, который далее можно обрабатывать как обычно – например, выгрузить в таблицу значений, поместить во временную таблицу и использовать в других запросах, и т.д.
&НаСервере
Процедура ПрочитатьПриПомощиПостроителяНаСервере()
Лист3 = ТабДок.ПолучитьОбласть("Лист3");
ОбластьЯчеек = Лист3.Область(5, 2, Лист3.ВысотаТаблицы, Лист3.ШиринаТаблицы);
ИсточникДанных = Новый ОписаниеИсточникаДанных(ОбластьЯчеек);
ПостроительОтчета = Новый ПостроительОтчета;
ПостроительОтчета.ИсточникДанных = ИсточникДанных;
ПостроительОтчета.Выполнить();
ТЗ = ПостроительОтчета.Результат.Выгрузить();
ТаблицаЗначений2.Загрузить(ТЗ);
КонецПроцедуры
Важно! В случае, если заголовки колонок в файле не соответствуют правилу именования переменных в 1С, они будут изменены компоновщиком – некорректные символы и пробелы будут заменены на знак подчеркивания “_”.
Динамическое сопоставление данных при загрузке
Предыдущие примеры ориентированы на работу с известным и неизменным составом колонок в исходном файле. Но что, если формат файла может меняться? Чтобы каждый раз не переписывать код, можно сделать его более гибким. Рассмотрим более сложный пример.
Предположим, есть несколько прайс-листов от разных поставщиков. Эти файлы имеют похожие, но не одинаковые форматы. Колонки могут располагаться в разном порядке, по-разному называться, шапка файла также имеет разное количество строк. В этом случае можно создать обработку, которая пусть и не будет универсальной, но будет достаточно гибко настраиваемой.
Добавим реквизит для указания имени области (чтобы можно было выбирать конкретный лист для чтения). Также добавим реквизит для указания пользователем номера первой строки. И основная часть настроек – таблица сопоставления колонок. Минимально достаточно будет сделать две колонки – номер исходный и номер принимающий. Такой прием распространен достаточно широко, и называется маппингом. Кроме маппинга по номерам существуют и другие варианты маппинга – например, по именам колонок.
&НаСервере
Процедура ПрочитатьСДинамическимиНастройкамиНаСервере()
НужныйЛист = ТабДок.ПолучитьОбласть(ИмяЛиста);
ТаблицаЗначений3.Очистить();
ТЗ = ТаблицаЗначений3.Выгрузить();
Для НомерСтроки = НомерПервойСтроки По НужныйЛист.ВысотаТаблицы Цикл
СтрТЗ = ТЗ.Добавить();
Для Каждого СтрСопоставления Из ТаблицаСопоставления Цикл
НомерКолонки = СтрСопоставления.НомерКолонкиИсходный;
СтрТЗ[СтрСопоставления.НомерКолонкиПринимающий-1] = НужныйЛист.Область(НомерСтроки, НомерКолонки, НомерСтроки, НомерКолонки).Текст;
КонецЦикла;
КонецЦикла;
ТаблицаЗначений3.Загрузить(ТЗ);
КонецПроцедуры
Более сложные сценарии
Не всегда форматы получаемых файлов удобны для загрузки. И не всегда есть возможность попросить передающую сторону обработать файл перед отправкой. Например, файл формируется каким-нибудь веб-ресурсом, либо присылается брокером по электронной почте. Можно конечно, посадить отдельного человека на обработку таких файлов и приведение их к единому формату – но это не самое рациональное и экономически оправданное решение.
Универсального “рецепта” нет, и далее будут только мои рекомендации и подходы, которые сформировались за годы практики.
Выше приведен специально усложненный формат файла, но на практике встречаются гораздо более неудобные файлы excel, которые нужно загрузить в 1С. Итак, с чем можно столкнуться, и что можно попробовать предпринять?
- “Плавающая” шапка. В зависимости от каких-нибудь условий, первая строка значимой информации может изменяться. Решение – динамически определять начало таблицы для загрузки – по тексту шапки таблицы, по цвету ячеек, и т.п.
- Несколько таблиц на одном листе. Решение – динамически определять начало и окончание каждой таблицы. В качестве окончания могут служить строки с текстом “Итого”, “Всего”. Также определять начало следующей таблицы и отнимать определенное количество строк, которое разделяет одну и другую таблицы в файле.
- Неподходящий формат ячеек. Текст “100 500.50” не является числом, и необходимо выполнить ряд действий, чтобы преобразовать его к числу – удалить разделитель разрядов, заменить точку на запятую, при необходимости удалить символ валюты, если он также присутствует в ячейке.
- Объединенные ячейки. Решение – анализируйте формат, используйте соответствующие параметры при задании области ячеек.
- Пустые строки, пустые колонки. Встречаются решения, когда файл анализируется с определенной строки и до первой встретившейся пустой ячейки – предполагается, что достигнут конец файла. Но такой подход не всегда корректен. Возможны случаи, когда после пустой строки или колонки продолжаются значимые строки. Решение – использовать более точный способ определения конца таблицы: метод ВысотаТаблицы, ячейки с ключевыми словами, ячейки с ключевым оформлением цветом.
Если вас не испугал последний раздел, и вы дочитали до конца – поздравляю и благодарю! Мне доводилось загружать файлы excel на китайском языке, загружать отчеты брокеров с самыми дикими форматами, загружать xls-файлы, полученные путем распознавания отсканированного изображения, и бороться с кучей ошибок.
Верьте в себя, не опускайте руки перед лицом проблем, и все получится!
+3
Иногда требуется разобрать данные из Excel в 1С.
Я считаю что легче и быстрей поместить все данные в ТаблицуЗначений и уже там ими манипулировать.
Пример 2-х функций которые я использую:
ИзExcelВТаблицу – Читает Excel в ТаблицуЗначений
ЭлементСправочника – Создает или находит элемент справочника.
Теперь сам код:
Код 1C v 8.х
// Загрузка данных из Excel файла в ТаблицуЗначений
// Возвращает ТаблицуЗначений с данными
// ПутьДоExcel - путь до Excel файла
// НомерСтраницы - Номер страницы в Excel
// ПерСтрокаЗаголовок - первая строка Excel содержит имена столбцов
// ФормаИндикатора - Стандартная форма прогресса работы
Функция ИзExcelВТаблицу(ПутьДоExcel, НомерСтраницы = 1, ПерСтрокаЗаголовок = Ложь , ФормаИндикатора = Неопределено)
Попытка
Док = ПолучитьCOMОбъект(ПутьДоExcel);
Исключение
Сообщить("Произошла ошибка при обращение к Excel:" + Символы.ПС + ОписаниеОшибки());
Возврат Неопределено;
КонецПопытки;
ЗакрытьФормуИндиктаора = Ложь;
Если ФормаИндикатора = Неопределено тогда
ЗакрытьФормуИндиктаора = Истина;
ФормаИндикатора = ПолучитьОбщуюФорму("ХодВыполненияОбработкиДанных");
ФормаИндикатора.Открыть();
КонецЕсли;
ФормаИндикатора.КомментарийЗначения = "Загрузка данных из Excel...";
ТЗ = Новый ТаблицаЗначений();
Страница = Док.Sheets(НомерСтраницы);
МакСтрок = Страница.UsedRange.Rows.Count; // макс. колич. строк
МакСтолб = Страница.UsedRange.Columns.Count; // макс. колич. столбцов
Для Столбец = 1 по МакСтолб цикл
ИмяСтолбца = "Столбец_" + Столбец;
Если ПерСтрокаЗаголовок тогда
ИмяСтолбца = Страница.Cells(1,Столбец).Value;
ИмяСтолбца = СокрЛП(ИмяСтолбца);
ИмяСтолбца = СтрЗаменить(ИмяСтолбца," ","_");
КонецЕсли;
ТЗ.Колонки.Добавить(ИмяСтолбца, Новый ОписаниеТипов("Строка"));
КонецЦикла;
НачальнаяСтрока = 1;
Если ПерСтрокаЗаголовок тогда
НачальнаяСтрока = 2;
КонецЕсли;
Для НомСтрока = НачальнаяСтрока по МакСтрок цикл
СтрТЗ = ТЗ.Добавить();
Для НомСтолбец = 1 по МакСтолб цикл
Данные = Страница.Cells(НомСтрока,НомСтолбец).Value;
СтрТЗ[НомСтолбец-1] = Данные;
КонецЦикла;
ФормаИндикатора.ЭлементыФормы.Индикатор.Значение = НомСтрока/МакСтрок * 100;
КонецЦикла;
Если ЗакрытьФормуИндиктаора тогда
ФормаИндикатора.Закрыть();
КонецЕсли;
Возврат ТЗ;
КонецФункции
Пример вызова:
Код 1C v 8.х
ФормаИндикатора = ПолучитьОбщуюФорму("ХодВыполненияОбработкиДанных");
ФормаИндикатора.НаименованиеОбработкиДанных = "Загрузка данных...";
ФормаИндикатора.Открыть();
ТЗ = ИзExcelВТаблицу(ФайлExcel,1,Истина,ФормаИндикатора);
Если ТЗ = Неопределено тогда
ФормаИндикатора.Закрыть();
Возврат;
КонецЕсли;
ФормаИндикатора.Закрыть();
или
Код 1C v 8.х
ТЗ = ИзExcelВТаблицу(ФайлExcel);
Если ТЗ = Неопределено тогда
Возврат;
КонецЕсли;
Теперь функция которой я использую когда надо создать элемент справочника из полученных данных.
Код 1C v 8.х
// Создаем в справочнике "ИмяСправочника" элемент
// ИмяЭлемента - Имя созданного элемента в справочнике "ИмяСправочника"
// ИмяРодителя - Имя родительского элемента (отсутствует если не древовидный).
// Разделитель \ позволяет писать древовидный путь родителя из нескольких элементов
// Параметры - Соответствие содержащие список параметров для элемента
// СоздатьЕслиНетЭлемента - Создает элемент если нет. Иначе ищет и обновляет
Функция ЭлементСправочника(ИмяСправочника = "",ИмяЭлемента, ИмяРодителя = Неопределено, Параметры = Неопределено, СоздатьЕслиНетЭлемента=Истина)
Если ИмяСправочника = "" тогда
Сообщить("Укажите имя спрачоника - ЭлементСправочника()");
Возврат Неопределено;
КонецЕсли;
Если ПустаяСтрока(ИмяЭлемента) тогда
Возврат Неопределено;
КонецЕсли;
// Создаем или ищем родителя
Родитель = Неопределено;
Если ИмяРодителя <> Неопределено тогда
ОбрабатИмяРодителя = ИмяРодителя;
РодительГруппы = Справочники[ИмяСправочника].ПустаяСсылка();
Пока НЕ ПустаяСтрока(ОбрабатИмяРодителя) цикл
ПозРазделителя = Найти(ОбрабатИмяРодителя,"\");
Если ПозРазделителя = 0 тогда
ИмяГруппы = ОбрабатИмяРодителя;
ОбрабатИмяРодителя = ""
Иначе
ИмяГруппы = Сред(ОбрабатИмяРодителя,1, ПозРазделителя-1);
ОбрабатИмяРодителя = Сред(ОбрабатИмяРодителя,ПозРазделителя+2);
КонецЕсли;
ТексЗапроса = "ВЫБРАТЬ
| Данные.Ссылка
|ИЗ
| Справочник."+ИмяСправочника+" КАК Данные
|ГДЕ
| Данные.Родитель = &Родитель
| И Данные.Наименование = &Наименование
| И Данные.ЭтоГруппа";
ЗапросРодителя = Новый Запрос(ТексЗапроса);
ЗапросРодителя.УстановитьПараметр("Родитель", РодительГруппы);
ЗапросРодителя.УстановитьПараметр("Наименование", ИмяГруппы);
РезультатРодителя = ЗапросРодителя.Выполнить().Выгрузить();
// Создаем родителя в случае необходимости
Если РезультатРодителя.Количество() <> 0 тогда
РодительГруппы = РезультатРодителя[0].Ссылка
Иначе
ОбъектРодитель = Справочники[ИмяСправочника].СоздатьГруппу();
ОбъектРодитель.Родитель = РодительГруппы;
ОбъектРодитель.Наименование = ИмяГруппы;
ОбъектРодитель.Записать();
РодительГруппы = ОбъектРодитель.Ссылка;
КонецЕсли;
КонецЦикла;
Родитель = РодительГруппы;
КонецЕсли;
// Создаем или ищем элемент
Элемент = Справочники[ИмяСправочника].НайтиПоНаименованию(ИмяЭлемента);
ОбъектЭлемент = Неопределено;
Если Элемент.Пустая() тогда
Если СоздатьЕслиНетЭлемента тогда
ОбъектЭлемент = Справочники[ИмяСправочника].СоздатьЭлемент();
ОбъектЭлемент.Наименование = ИмяЭлемента;
Иначе
Элемент = Неопределено
КонецЕсли;
Иначе
ОбъектЭлемент = Элемент.ПолучитьОбъект();
КонецЕсли;
Если ОбъектЭлемент <> Неопределено тогда
// Устанвалвиаем доп. параметры
Если Параметры <> Неопределено тогда
Для каждого СтрПараметр из Параметры цикл
ОбъектЭлемент[СтрПараметр.Ключ] = СтрПараметр.Значение;
КонецЦикла;
КонецЕсли;
Если Родитель <> Неопределено тогда
ОбъектЭлемент.Родитель = Родитель;
КонецЕсли;
ОбъектЭлемент.Записать();
Элемент = ОбъектЭлемент.Ссылка;
КонецЕсли;
Возврат Элемент;
КонецФункции
Автор: borismor
23.04.2019
Получение таблицы значений из excel в 1С v8, без COM, внешних источников данных и т.д.
EXCELВТаблицуЗначений() — За 10 строчек кода!
Реализация протестирована на 1С 8.3.12.1714 (x64).
WARNING
Данная статья не претендует на оригинальность и не является конечным решением.
Подходы решения задач и примеры программного кода несут исключительно обучающий характер.
Существует масса подходов загрузки данных из EXCEL в 1С. Большинство решений основаны на COM или еще более сложных возможностях платформы.
Для себя разработал наиболее оптимальный вариант:
EXCEL -> Табличный документ -> Построитель запроса -> Таблица значений
Итак, приступим:
- Прочитать Excel файл на клиенте, для передачи на сервер:
&НаКлиенте Процедура ЗагрузитьEXCEL(Команда) Файл = Новый Файл(ПутьКEXCEL); Если НЕ Файл.Существует() Тогда Возврат; КонецЕсли; ДвоичныеДанные = Новый ДвоичныеДанные(ПутьКEXCEL); ДокументРезультат = EXCELВТаблицуЗначений(ДвоичныеДанные, Файл.Расширение); ДокументРезультат.Показать(); КонецПроцедуры
- Выполнить чтение Excel в таблицу значений:
&НаСервере Функция EXCELВТаблицуЗначений(ДвоичныеДанные, Расширение) ФайлEXCELНаСервере = ПолучитьИмяВременногоФайла(Расширение); ДвоичныеДанные.Записать(ФайлEXCELНаСервере); ТабличныйДокумент = Новый ТабличныйДокумент; ТабличныйДокумент.Прочитать(ФайлEXCELНаСервере); УдалитьФайлы(ФайлEXCELНаСервере); ОбластьТаблицы = ТабличныйДокумент.Область(8, 1, ТабличныйДокумент.ВысотаТаблицы, ТабличныйДокумент.ШиринаТаблицы); ПостроительЗапроса = Новый ПостроительЗапроса; ПостроительЗапроса.ИсточникДанных = Новый ОписаниеИсточникаДанных(ОбластьТаблицы); ПостроительЗапроса.Выполнить(); ТаблицаДанных = ПостроительЗапроса.Результат.Выгрузить(); // теперь поссмторим что в Таблице Возврат ТаблицаЗначенийВТабличныйДокумент(ТаблицаДанных); КонецФункции
-
Визуализировать таблицу значений:
&НаСервереБезКонтекста Функция ТаблицаЗначенийВТабличныйДокумент(ТаблицаДанных) ПостроительОтчета = Новый ПостроительОтчета; ПостроительОтчета.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТаблицаДанных); ДокументРезультат = Новый ТабличныйДокумент; Построительотчета.Вывести(ДокументРезультат); Возврат ДокументРезультат; КонецФункции
Описание преобразования данных:
- Получаем исходный файл на клиенте;
- На основании файла создаем двоичные данные и получаем расширение файла;
- Передаем двоичные данные на сервер;
- Создаем дубль файла excel на сервере;
- Читаем файл в новый табличный документ;
- Получаем область табличного документа, где находятся полезные данные (ТабличныйДокумент.Область(8, 1, ТабличныйДокумент.ВысотаТаблицы, ТабличныйДокумент.ШиринаТаблицы));
- Создаем новый построитель запроса и установим в качестве источника данных — область полезных данных;
- Выполним построитель и получим результат запроса;
- Результат запроса выгрузим в таблицу значений.
Плюсы реализации:
- Скорость работы по сравнению с COM EXCEL
- Возможно выполнять загрузку где EXCEL нет вообще (MAC | LINUX | etc…)
- Простота реализации
&НаСервере
Функция Конвертация_Excel_в_ТЗ(АдресВХранилище)ИмяФайлаExcel = ПолучитьИмяВременногоФайла(«.xlsx»); // или реквизит с выбором файла .xlsx
ФайлИмпортаExcel = ПолучитьИзВременногоХранилища(АдресВХранилище);
ФайлИмпортаExcel.Записать(ИмяФайлаExcel);ТабличныйДокумент = Новый ТабличныйДокумент;
Попытка
ТабличныйДокумент.Прочитать(ИмяФайлаExcel, СпособЧтенияЗначенийТабличногоДокумента.Текст);
Исключение
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = ОписаниеОшибки();
Сообщение.Сообщить();
КонецПопытки;//Автоматически именует столбцы таблицы по первой строке файла. Пробелы заменяются на «»
ПЗ = Новый ПостроительЗапроса;
ПЗ.ИсточникДанных = Новый ОписаниеИсточникаДанных(ТабличныйДокумент.Область());
ПЗ.ДобавлениеПредставлений = ТипДобавленияПредставлений.НеДобавлять;
ПЗ.ЗаполнитьНастройки();
ПЗ.Выполнить();ТаблицаСДанными = ПЗ.Результат.Выгрузить();
Возврат
ТаблицаСДанными;
КонецФункции
Excel — это сторонняя программа, ее можно запускать из 1С в невидимом и видимом режиме и пользоваться всеми возможностями. Excel должен быть установлен на компьютере. Для примера приведено чтение таблицы в из файла Excel на клиенте, передача на сервер и создание на сервере таблицы значений с данными из файла. Такую задачку любят давать на собеседованиях на должность программиста 1С.
&НаКлиенте
Процедура НажатиеКноки()
// обращаемся к Excel
Попытка
Эксель = новый COMОбъект(«Excel.Application»);
Исключение
Сообщить(ОписаниеОшибки());
Возврат;
КонецПопытки;
ПутьКФайлу = «C:Некоторый файл.xlsx»;
// открываем ексель файл
Книга = Эксель.WorkBooks.Open(ПутьКФайлу);
// переходим на первую страницу
Лист = Книга.WorkSheets(1);
// для количества колонок и строк в экселе есть специальные ячейки
ВсегоКолонок = Лист.Cells(1,1).SpecialCells(11).Column;
ВсегоСтрок = Лист.Cells(1,1).SpecialCells(11).Row;
// сохраняем файл в массив строк, где строка это так же массив (на клиенте
// нельзя создавать таблицу значений
НаборСтрокФайла = новый массив;
для Строка = 1 по ВсегоСтрок цикл
МассивСтрока = новый массив;
для Колонка = 1 по ВсегоКолонок цикл
// получаем значение из ячейки excel
Значение = СокрЛП(Лист.Cells(Строка,Колонка).Value);
МассивСтрока.Добавить(Значение);
КонецЦикла;
НаборСтрокФайла.Добавить(МассивСтрока);
КонецЦикла;
// запишем файл с другим именем
Эксель.SaveAs(«C:ФайлСДругимИменем.xlsx»);
// закрываем ексель, иначе он останется висеть в памяти
Эксель.Application.Quit();
КонецПроцедуры
&НаСервере
Процедура СоздатьИОбработатьТаблицуЗначений(НаборСтрокФайла, ВсегоКолонок)
ТЗ = новый ТаблицаЗначений;
// создаем колонки таблицы значений (столько сколько в файле ексель)
для й=1 по ВсегоКолонок цикл
ТЗ.Колонки.Добавить(«кол» + Формат(й,«ЧЦ=4; ЧГ=»));
КонецЦикла;
// переносим строки из массива в таблицу значений
для каждого МассивСтрока из НаборСтрокФайлацикл
НовСтрока = ТЗ.Добавить();
для Колонка = 1 по ВсегоКолонок цикл
// переносим значение из массива в таблицу
НовСтрока[Колонка — 1] = МассивСтрока[Колонка — 1];
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Далее приводятся наиболее частые ситуации, возникающие на
Поиск и замена текста в ячейках файла Excel
//Выбираем область поиска — весь лист
ОбластьПоиска = Лист.Cells;
// Начинаем поиск с левого верхнего угла
НачалоЛиста =Лист.Cells(1, 1);
// Ищем ячейку с текстом «привет»
ОбластьПараметр = ОбластьПоиска.Find(«привет», НачалоЛиста);
// Если нашли вывсодим найденую строку
Если ОбластьПараметр <> неопределено Тогда
Сообщить(ОбластьПараметр.Value);
КонецЕсли;
Работа со строками в Excel
//Выбираем первую строку
НачальнаяСтрока = Лист.Cells(1, 1);
// Выделяем всю строку
НачальнаяСтрока .EntireRow.Select();
// Копируем выделенное
НачальнаяСтрока .EntireRow.Copy();
// Вставляем (новая строка будет вставлена тут же)
НачальнаяСтрока .EntireRow.Insert();
// Удалим строку
НачальнаяСтрока .EntireRow.Delete();
Прочие полезные методы Excel
Эксель.Visible = Видимость; | 0 — Excel не виден, 1 — виден. |
Книга = Эксель.WorkBooks.Add(); | Создание новой книги (файла) Excel. |
Книга.SaveAs(ИмяФайла); | Сохранение книги Excel. |
Лист = Книга.WorkSheets.Add(); | Добавление нового листа в книгу. |
Книга = Эксель.WorkBooks.Open(ИмяФайла); | Открытие существующей книги (файла) Excel. |
Лист = Книга.WorkSheets(НомерЛиста); | Установка листа в качестве рабочего с номером НомерЛиста. |
Лист.Name = ИмяЛиста; | Задание рабочему листу имени ИмяЛиста |
Лист.PageSetup.Zoom = Масштаб; | Задание параметра страницы «Масштаб» (от 10 до 400). |
Лист.PageSetup.Orientation = Ориентация; | Ориентация: 1 — книжная, 2 — альбомная. |
Лист.PageSetup.LeftMargin = Эксель.CentimetersToPoints(Сантиметры); | Задание левой границы (в сантиметрах). |
Лист.PageSetup.TopMargin = Эксель.CentimetersToPoints(Сантиметры); | Задание верхней границы (в сантиметрах). |
Лист.PageSetup.RightMargin = Эксель.CentimetersToPoints(Сантиметры); | Задание правой границы (в сантиметрах). |
Лист.PageSetup.BottomMargin = Эксель.CentimetersToPoints(Сантиметры); | Задание нижней границы (в сантиметрах). |
Лист.Columns(НомерКолонки).ColumnWidth = Ширина; | Задание ширины колонке. |
Лист.Cells(НомерСтроки, НомерКолонки).Value = Значение; | Ввод данных в ячейку. |
Лист.Cells(НомерСтроки,НомерКолонки).Font.Name = ИмяШрифта; | Установка шрифта в ячейке. |
Лист.Cells(НомерСтроки,НомерКолонки).Font.Size = РазмерШрифта; | Установка размера шрифта в ячейке. |
Лист.Cells(НомерСтроки,НомерКолонки).Font.Bold = Жирный; | 1 — жирный шрифт, 0 — нормальный. |
Лист.Cells(НомерСтроки,НомерКолонки).Font.Italic = Курсив; | 1 — наклонный шрифт, 0 — нормальный. |
Лист.Cells(НомерСтроки,НомерКолонки).Font.Underline = Подчеркнутый; | 2 — подчеркнутый, 1 — нет. |
Лист.Cells(НомерСтроки, НомерКолонки).NumberFormat = Формат; | Установка формата данных ячейки. |
Лист.Cells(НомерСтроки,НомерКолонки).Borders.Linestyle = ТипЛинии; | Установка рамок ячейки. 1 — тонкая сплошная. |
Лист.Protect(); | Установка защиты на лист |
Лист.UnProtect(); | Снятие защиты с листа |
Лист.Cells(Строка, Столбец).Locked=0; | Ячейка будет доступной (и после установки защиты на лист) |
Эксель.DisplayAlerts = False; | Убрать все сообщение при открытии файла. Сообщения останавливают выполнения кода до реакции пользователя |