Управляемые формы: чтение макетов с объединенными ячейками (в частности, и из экселей)

28.10.17

Разработка - Механизмы платформы 1С

При чтении данных из файлов через табличный документ у начинающих и продолжающих специалистов по платформе иногда возникают трудности. Например, с тем, как прочитать данные из объединенных ячеек один раз. Статья прояснит некоторые детали.

Всем добрый период времени!

Суть задачи, которую мы разберем, в том, как прочитать данные из объединенных ячеек табличного документа с помощью объекта "ТабличныйДокумент". Также коснемся того, как пройтись по выделенным данным. Итак, приступим.

ЧТЕНИЕ ТАБЛИЧНОГО ДОКУМЕНТА

Для чтения табличного документа в 1С можно использовать как ни странно объект "ТабличныйДокумент". С версии 8.3.7 (если не изменяет память) данный объект способен читать не только MXL-файлы, но и XLS/XLSX/ODT и какие-то еще варианты таблиц (а также, кстати, и писать).

Но как всегда есть одна малюсенькая проблемка - объект создается только на сервере. Но 1С попыталась решить данную проблему создав потоки в памяти и предоставив программисту возможность использовать их вместо пути к файлу в конструкторе объекта, но при этом необходимо указать тип читаемого файла. Правда у меня на платформе Windows 7 pro x64 c 1C 8.3.10.2466 эксель таким образом прочитать не получилось, а вот MXL читает замечательно, поэтому для екселевский файлов все-равно придется создать временный файл.

Итак, код чтения файлов:

&НаСервере
Процедура ЗагрузитьФайлНаСервере(ДД, Расширение)

	Если Расширение = "xml" Тогда 
		ЧД = Новый ЧтениеДанных(ДД);
		Таб.Прочитать(ЧД, СпособЧтенияЗначенийТабличногоДокумента.Значение, ТипФайлаТабличногоДокумента.MXL);
	Иначе
		ИмяФайла = ПолучитьИмяВременногоФайла(Расширение);
		ДД.Записать(ИмяФайла);
		Таб.Прочитать(ИмяФайла);
		УдалитьФайлы(ИмяФайла);
	КонецЕсли;

КонецПроцедуры

&НаКлиенте
Процедура ЗагрузитьФайл(Команда)
	
	Длг = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
	Длг.Фильтр = "MXL-files (*.mxl)|*.mxl|XLS-files (*.xls)|*.xls|XLSX-files (*.xlsx)|*.xlsx|ODS-files (*.ods)|*.ods";
	Длг.Показать(Новый ОписаниеОповещения("ПриВыбореФайла", ЭтаФорма));
	
КонецПроцедуры

&НаКлиенте
Процедура ПриВыбореФайла(Рез, Доп) Экспорт 
	
	Если Рез = Неопределено Тогда 
		Возврат
	КонецЕсли;
	
	фл = Новый Файл(Рез[0]);

	ЗагрузитьФайлНаСервере(
			Новый ДвоичныеДанные(Рез[0]),
			НРег(фл.Расширение)
		);

КонецПроцедуры

Создадим форму с табличным документом и кнопкой "Загрузить файл" и получим фот такую формочку, которая сможет прочитать MXL, XLS, XLSX и ODS файлы в табличный документ.

ВЫДЕЛЕННЫЕ ЯЧЕЙКИ

Давайте разберемся, где тут у нас находятся выделенные пользователем ячейки. И вот тут интересная странность платформы в том, что эти выделенные ячейки доступны только на клиенте в соответствующем элементе формы. Давайте пробежимся по выделенным ячейкам и распечатаем результат в строку сообщений:

&НаКлиенте
Процедура СообщитьВыделенное(Команда)
	
	Для Каждого Область ИЗ Элементы.Таб.ПолучитьВыделенныеОбласти() Цикл 
		Для Х = Область.Лево ПО Область.Право Цикл 
			Для У = Область.Верх ПО Область.Низ Цикл 
				Сообщить(Таб.Область(У,Х).Текст);
			КонецЦикла;
		КонецЦикла;
	КонецЦикла;
	
КонецПроцедуры

Если мы выделим теперь первую строку без объединенных ячеек, то получим следующий результат:

Т.е. тут у нас напечаталось А, Б и В. Если же мы выберем вторую строку, то получим иную картину:

Как видите, наличие объединения никоим образом не мешает нам получить данные из строки [2;2], которая у нас объединена со строкой [2;1], При том в обоих этих строках будет находиться значение "А". Если мы выделим третью строку, то получим вывод "А А А" (ну вы уже поняли, почему, да?)

ОБЪЕДИНЕННЫЕ ЯЧЕЙКИ

Для того, чтобы исправить проблему с объединенными ячейками, нужно просто узнать одну подробность: каждая ячейка имеет реквизиты "Лево", "Право", "Верх" и "Низ". И для объединенных ячеек они не будут равны. Для простого объединения по оси Х произвести чтение с учетом объединения будет достаточно просто:

	Для Каждого Область ИЗ Элементы.Таб.ПолучитьВыделенныеОбласти() Цикл 
		Для Х = Область.Лево ПО Область.Право Цикл 
			Для У = Область.Верх ПО Область.Низ Цикл 
				Сообщить(Таб.Область(У,Х).Текст);
				Х = Х + Таб.Область(У,Х).Право - Таб.Область(У,Х).Лево;
			КонецЦикла;
		КонецЦикла;
	КонецЦикла;

Мы просто добавляем к "Х" "право" и вычитаем "лево".

А для оси "У" предлагаю разобраться самостоятельно (в качестве домашнего задания).

Всех благ!

макеты управляемые формы объединение ячеек чтение xls

См. также

Сервисы интеграции без Шины и интеграции

Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Пример использования «Сервисов интеграции» без подключения к Шине и без обменов.

13.03.2024    2561    dsdred    16    

59

Поинтегрируем: сервисы интеграции – новый стандарт или просто коннектор?

Обмен между базами 1C Администрирование СУБД Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

В платформе 8.3.17 появился замечательный механизм «Сервисы интеграции». Многие считают, что это просто коннектор 1С:Шины. Так ли это?

11.03.2024    5897    dsdred    53    

83

Как готовить и есть массивы

Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

Все мы используем массивы в своем коде. Это один из первых объектов, который дают ученикам при прохождении обучения программированию. Но умеем ли мы ими пользоваться? В этой статье я хочу показать все методы массива, а также некоторые фишки в работе с массивами.

24.01.2024    5846    YA_418728146    25    

68

Планы обмена VS История данных

Обмен между базами 1C Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

Вы все еще регистрируете изменения только на Планах обмена и Регистрах сведений?

11.12.2023    6964    dsdred    36    

113

1С-ная магия

Механизмы платформы 1С Бесплатно (free)

Язык программирования 1С содержит много нюансов и особенностей, которые могут приводить к неожиданным для разработчика результатам. Сталкиваясь с ними, программист начинает лучше понимать логику платформы, а значит, быстрее выявлять ошибки и видеть потенциальные узкие места своего кода там, где позже можно было бы ещё долго медитировать с отладчиком в поисках источника проблемы. Мы рассмотрим разные примеры поведения кода 1С. Разберём результаты выполнения и ответим на вопросы «Почему?», «Как же так?» и «Зачем нам это знать?». 

06.10.2023    19054    SeiOkami    46    

118

Дефрагментация и реиндексация после перехода на платформу 8.3.22

Механизмы платформы 1С Платформа 1С v8.3 Бесплатно (free)

Начиная с версии платформы 8.3.22 1С снимает стандартные блокировки БД на уровне страниц. Делаем рабочий скрипт, как раньше.

14.09.2023    12764    human_new    27    

76

Валидация JSON через XDTO (включая массивы)

WEB-интеграция Универсальные функции Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    9385    YA_418728146    6    

143

Внешние компоненты Native API на языке Rust - Просто!

Механизмы платформы 1С Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Внешние компоненты для 1С можно разработывать очень просто, пользуясь всеми преимуществами языка Rust - от безопасности и кроссплатформенности до удобного менеджера библиотек.

20.08.2023    6527    sebekerga    54    

95
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. bulpi 215 29.10.17 13:51 Сейчас в теме
1)В тексте ЗагрузитьФайлНаСервере ошибка, замените xml на mxl
2)А если не выделенные ячейки ? При чем тут выделение на форме к проблеме чтения объединенных ячеек ?
+
2. starik-2005 3036 29.10.17 16:31 Сейчас в теме
(1) 1. Ну это, как я понял, не мешает верно прочитать.
2. А в чем разница? С выделенными интереснее, а не выделенные и сами прочитаете теперь.
+
3. shurik_shurik 01.11.17 21:28 Сейчас в теме
Х = Х + Таб.Область(У,Х).Право - Таб.Область(У,Х).Лево;

Может это нужно вынести с цикла по Y ?
И второй момент, зачем вычитать разницу, если можно сделать типа так:
Х =  Таб.Область(У,Х).Право
+
4. starik-2005 3036 02.11.17 16:38 Сейчас в теме
(3)
зачем вычитать разницу, если можно сделать типа так:
Можно. Цикл в таком случае можно заменить на Пока Х < ...
+
5. dajen 09.11.17 11:55 Сейчас в теме
Ну не то чтобы очень просто. Если выделять 2 строки, где объединение не тривиально, пример во вложении (если в нижней строке объединение шире и перекрывает что-то из верхней - программа не вернется туда и не выведет).

Почему не поставить просто условие:
Если Таб.Область(У,Х).Верх = У и
Таб.Область(У,Х).Лево = Х Тогда

Сообщить(Таб.Область(У,Х).Текст);
КонецЕсли;

Обходя таким образом выводится все и по одному разу при любых извращениях с объединением, по-моему.
Прикрепленные файлы:
+
6. starik-2005 3036 09.11.17 13:38 Сейчас в теме
(5)
Таб.Область(У,Х).Верх = У и
Таб.Область(У,Х).Лево = Х
В принципе имеет право на существование. Проблема только в том, что лишние Х и У выбираются, но этим при небольших размерах файла можно пренебречь.
+
Оставьте свое сообщение