gifts2017

Универсальная таблица для ввода данных в 1С 7.7

Опубликовал Владимир (svsrus) в раздел Программирование - Практика программирования

Рассматривается способ хранения ТЗ в базе, а также ввод данных с использованием таблицы в 1С 7.7
Предыстория или нафиг все это нужно…

Встала передо мной тут задачка одна - автоматизировать работу контролеров на рыке. Рынок поделен на торговые зоны.
Каждая зона разбита на ряды и на места. Трудность заключается в том, что в каждой зоне разное количество рядов, как и мест
в рядах. Нужно, чтобы контролер мог наглядно (схематически) видеть состояние той или иной зоны. Видеть занятые/свободные
места, для чего предназначено каждое место. Кроме того требуется сделать это все «динамически». Т.е. каждый месяц
количество рядов, мест и их назначение может меняться.

На первый взгляд задача не такая и трудная. Главное - как-то сохранить структуру зоны в 1С. Но как? Структура зоны
представляет собой не что иное, как обычную двумерную таблицу «шахматку». По вертикали места, по горизонтали ряды. Т.е.
оптимальный вариант – использование таблицы значений в 1С. Но, к сожалению, 1С не умеет хранить ТЗ в составе базы. Есть
несколько вариантов хранить ТЗ. Во-первых, во внешнем файле. Во-вторых, во внешнем dbf’е. В-третьих, создать справочник
(несколько справочников). И последний вариант – документ с табличными реквизитами.

Первый способ отметаем сразу, второй немного лучше первого, но все равно хранить что-то отдельно от базы не всегда
удачное решение, да и трудностей больше. Третий способ предлагали многие, но он мне не понравился. Представьте себе зону
100 на 100… Пусть даже справочник будет заполняться программно. Геморрой… А еще если учесть что реквизиты справочника
должны быть периодическими, то хочется плакать. Четвертый вариант – вот оно! То что нужно! Точнее, это единственный верный
вариант в данном случае.

Итак, для хранения ТЗ используем документ с реквизитом шапки – Зона и табличными реквизитами – ряд, место,
назначение. Зона – справочник «Структура торговой зоны», где указано количество рядов в зоне и максимальное количество мест
в ряду. Но как заполнять такой документ? Согласитесь, очень неудобно десять раз указать ряд, десять раз выбрать место, а
потом еще и назначение этого места. Утомительно и трудно для восприятия. Отсюда возможные ошибки. Вот тут и возникла идея -
заполнять документ, используя таблицу! Таким образом, табличные реквизиты вообще можно не выводить в документе…

После начала реализации, понял, а ведь это очень удобно использовать таблицу для ввода всевозможных данных в 1С.
Кроме того ее можно использовать не только для ввода, но и для вывода, в том числе и динамического. Да и еще кучу
применений можно придумать!Так родилась идея создания универсальной таблицы для ввода данных. На входе указываем количество
рядов и мест, на выходе получаем ТЗ…


Делаем таблицу…

В свойствах формы обработки/отчета выбираем использовать таблицу для ввода данных (Положение: любое).
Для начала нам надо сформировать таблицу…

// Формирование произвольной таблицы.
// Параметры: КолвоРядов - кол-во рядов в зоне
//            КолвоМест - макс. кол-во мест в ряде.
//====================================================================
Процедура СформироватьСхему(КолвоРядов, КолвоМест) 

	//	Начальные значения координат первой(верхняя левая) ячейки
	x = 4;y =3;         
	НачалоТаблицы = "R"+x+"C"+y; 
	КоординатыЯчеек.УдалитьВсе(); 
        // КоординатыЯчеек – Список значений(как глобальная переменная модуля). Пригодиться в дальнейшем при обработке 
        // нажатия на ячейке мышкой. Чтобы не обрабатывались не входящие в схему ячейки.
	
	Ячейка = Таблица.Область("R"+(x-1)+"C"+(y-1));
	Ячейка.РамкаОбвести(,,3,3);
	Ячейка.Текст = "место №";
	Ячейка = Таблица.Область("R"+(x-2)+"C"+y);
	Ячейка.Текст = "ряд №";
	
	Для i = 0 По КолвоМест-1 Цикл
		Для j = 0 По КолвоРядов-1 Цикл
		
			// Формируем таблицу x/y
			АдресЯчейки = "R"+(x+i)+"C"+(y+j);
			Ячейка = Таблица.Область(АдресЯчейки);
			Ячейка.Контроль(4);  
			Ячейка.ЦветФона(255,255,128);
			Ячейка.РамкаОбвести(3,3,3,3);
			Ячейка.Текст = "-";     
			КоординатыЯчеек.ДобавитьЗначение(АдресЯчейки);
			
			// выводим ряды
			АдресЯчейки = "R"+(x-1)+"C"+(y+j);
			Ячейка = Таблица.Область(АдресЯчейки);   
			Ячейка.РамкаОбвести(3,3,3,);
			Ячейка.ЦветФона(192,192,192);
			Ячейка.Текст = j+1;			
			
		КонецЦикла;    
		
		// выводим места
		АдресЯчейки = "R"+(x+i)+"C"+(y-1);
		Ячейка = Таблица.Область(АдресЯчейки);   
		Ячейка.РамкаОбвести(3,,,3);
		Ячейка.ЦветФона(192,192,192);
		Ячейка.Текст = i+1;
		КонецТаблицы = "R"+(x+КолвоМест-1)+"C"+(y+КолвоРядов-1); //обводим поученную таблицу рамкой
		
	КонецЦикла;
		
	Область = Таблица.Область(НачалоТаблицы+":"+КонецТаблицы);   
	Область.РамкаОбвести(3,3,3,3);
	Таблица.Опции(0,,3,2,"СхемаТоргМест","СхемаТоргМест");

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


Вот что у нас получилось (рядов 10, мест 10): рис. 1

Теперь надо сделать так, чтобы в ячейки можно было вносить какие-то данные, например из справочника. Замечу, что
ячейки таблицы в режиме ввода данных могут быть любого типа (по умолчанию у всех стоит тип «строка»). Т.е. если мы в
конфигураторе укажем заранее, что ячейка имеет тип Справочник.XXX. То при работе в эту ячейку можно вносить элементы из
указанного справочника. А саму таблицу потом выгружать в список значений методом Выгрузить(). Тут меня ждало первое
разочарование…

Поскольку заранее мы не знаем количество рядов/мест, то какие ячейки будут иметь нужный нам тип надо сделать
программно. Да и метод такой имеется УстановитьТип(). Но этот метод применим, если на этапе конфигурирования ячейке
назначен тип – «Неопределенный», а по умолчанию, как я уже писал, у всех ячеек тип «строка». Предположив, что на практике
вряд ли будет существовать зона 100 рядов на 100 мест, я, не долго думая, выделил в конфигураторе область 100 на 100 и
назначил всем ячейкам тип «Неопределенный». Сохранил отчет и … отчет стал весить 64(!!!) Мегабайта….) Мда, так не пойдет… и
я придумал другой выход...

При открытии обработки формируем таблицу значений, которая по структуре идентична нашей таблице. Т.е. количество
строк будет равно количеству мест, а количество колонок – количеству рядов. Тип колонок выбираете произвольно, или
«неопределенный». Таким образом, эта ТЗ будет являться своего рода «подложкой» нашей таблицы и полностью дублировать ее. Эту ТЗ мы и передаем во внешний документ, вызвавший эту обработку.

Теперь напишем обработку ячейки таблицы. Замечу, что в моем примере, значение пользователем выбирается из списка
значений (меню), т.к. возможных значений у меня немного. Вы можете сделать выбор значения как угодно: открывать справочник
для подбора, открывать СЗ в любом доступном виде или вообще сварганить многоуровневое меню, как описал Che Burshka там - http://infostart.ru/profile/174/articles/178/.

Процедура ПриВыбореЯчейкиТаблицы(Адрес,Значение)   
	Перем х,у; //координаты ячейки	
	Если КоординатыЯчеек.Принадлежит(Адрес) = 0 Тогда
		Возврат;
	КонецЕсли;
	
		Элемент = "";
		Если СЗ.ВыбратьЗначение(Элемент,,,,1) = 1 Тогда
			Ячейка = Таблица.Область(Адрес); 
			ПолучитьКоординатыЯчейки(Адрес,х,у);
			Попытка
		    	Ячейка.Значение = СокрЛП(Элемент.Наименование);
				Ячейка.ЦветФона(128,255,128); 
				Ячейка.РамкаОбвести(3,3,3,3);   
				ТЗ.УстановитьЗначение(х,у, Элемент);
			Исключение // все элементы СЗ имеют тип Справочник.ХХХ, т.е. имеют реквизит «Наименование», 
                                  //если такого реквизита нет – значит этот пункт меню служит для удаления значения ячейки.                                        
				Ячейка.Значение = "-";   
				Ячейка.ЦветФона(255,255,128);       
				ТЗ.УстановитьЗначение(х,у, "");
			КонецПопытки;	
		КонецЕсли;	
КонецПроцедуры


Получаем вот такое меню: рис.2

Итоговый вид таблицы после заполнения оператором: рис.3

Демонстрационная обработка здесь -> http://infostart.ru/projects/1299/
В демонстрационной обработке используются значения типа "Строка".

Рис.1

Рис. 2

Рис. 3

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Владимир (svsrus) 29.09.07 10:59
Вот собственно. Плюсуйте или минусуйте ) Блин как не удобно сделано добавление статьи. Подскажите, как вставить рисунок в то место, где он должен быть.
2. Сhe Burashka (CheBurator) 29.09.07 12:41
Блин, как эту таблицу-то делать? нифига не втыкаю - с чего это MXL будет весить 64 мега?
назначь самым распространенным типоместам возможность назначать свою окраску ячейки - тогда визуально можно будет положение дел оценить..
3. Владимир (svsrus) 29.09.07 13:09
Во-первых, я не говорил про таблицу MXL. Я говорю про таблицу в режиме ввода данных. В режиме ввода данных каждой ячейке таблицы можно присвоить любой тип. С абсолютно пустой таблицей(ничего не меняя) отчет весит 166 кб. Выделив 500 на 500 ячеек и назначив им тип "неопределеныый" отчет уже весит 15 Мб. А назначив тип Справочник.XXX - уже 20 Мб. 65 мегабайт это когда 1000 на 1000).

А что тебе не понятно? именно... Таблица сама делается, функция вверху, остается только эту функцию воткнуть в ПриОткрытии() или еще куда. Главное не забыть что таблица в режиме ввода, а ставится это в свойствах формы.

На счет раскраски ты прав. Функция есть, раскраска в функции есть, остается только подставлять туда значения для распространенных типомест. Тут я не счел необходимым это делать, дальше додумывайте/придумывайте что хотите с этой таблицей. Хоть пусть как новогодняя елка мигает:) У меня к тем цветам что на рисунке добавится еще один - "ЗАНЯТО". Т.е. занятое место будет выделено другим цветом. Зеленое - свободные места. Т.е. визуально сразу видно будет:)
4. Владимир (svsrus) 29.09.07 13:12
Позже выложу готовую обработку, если интересует...
5. Владимир (svsrus) 30.09.07 22:22
ну, если не интересует не буду выкладывать значит...
6. Сhe Burashka (CheBurator) 01.10.07 01:30
положи, пусть будет...
мне такой подход нравится.. имхается мне что РМ таким образом написаны должны быть.. нафиг куча закладок и полей... ;-)
7. Владимир Костецкий (astonvilla) 01.10.07 09:35
8. Владимир (svsrus) 01.10.07 22:25
Che, извиняй возможно за глупый вопрос, но что такое РМ?
9. Михаил (mdzen) 01.10.07 22:27
Круто. Писал для автостоянки конфу использовал таблицу в режиме ввода даных, действительно получается тяжелая. Будет время надо попробовать такой вариант....
10. Владимир (svsrus) 02.10.07 10:10
Mdzen, попробуй. Я когда начал делать таблицу, понял что варианты ее применения очень разнообразные. Позже, когда выложу саму обработку, постараюсь привести примеры применения.
11. Ilya (ivisor_fil) 02.10.07 13:12
А че не использовать просто таблицу значений? Ложишь на документ вместо табличной части и обрабатываешь клик по таблице через текущую строку и колонку? Правда раскрасить так красиво не удастся, зато гимора меньше!
12. ВторНик (ВторНик) 02.10.07 15:37
Люди добрые! Где в свойствах формы обработки устанавливается использовать таблицу для ввода данных? Ну, не могу найти чесное слово! Объясните тупому! :)
13. Poppy (poppy) 02.10.07 15:53
(12)
Меню\Действия\Свойства формы
14. ВторНик (ВторНик) 02.10.07 15:58
poppy - Спасибо! Ни разу не приходилось сталкиваться.
15. Владимир (svsrus) 02.10.07 16:02
А ты попробуй 50 на 50 хотя бы ТЗ сделать... Удобно? Красиво? )))
16. Владимир (svsrus) 02.10.07 16:57
17. ВторНик (ВторНик) 02.10.07 18:52
ПолучитьКоординатыЯчейки - это функция? Как она работает? Прошу не шпинять сильно, я еще не волшебник а только учусь.
18. Михаил (mdzen) 02.10.07 20:36
Нормально.
Теперь думаю как и где сохранять структуру 100x35 (или 35x100, как угодно) попробую на текущую дату в справочнике использовать строку неограниченной длины (если влезет).
19. Владимир (svsrus) 02.10.07 22:03
ВторНик, в данном модуле это процедура. Причем моя. Разрешаю пользоваться) На входе в процедуру имеем адрес ячейки, как принято в 1С, т.е. формата R#C#. На выходе получаем нормальные координаты x,у(строка,столбец), чтобы можно было работать с ТЗ. Пример. На входе адрес ячейки R3C5, на выходе x = 3, y = 5.

mdzen, именно по этому я и отказался от справочника и других вариантов. Т.к. заранее неизвестно, какая структура может быть. Поэтому было принято решение использовать в качестве "хранилища" структуры документ с табличной частью. Об этом написано в статье.
20. Михаил (mdzen) 03.10.07 15:36
Да с документом оказалось динамичнее и показательно. Спасибо за идею. Будем пользовать
21. Владимир (svsrus) 03.10.07 15:57
22. Владимир (svsrus) 10.10.07 08:29
Все конечно хорошо. Столько похвальных комментов! Здорово!Но давайте вернемся на землю.
Почему, никто не поинтересовался, как передать таблицу значений в документ, вызывающий эту обработку? Сейчас бьюсь над этим. Вариантов несколько, пытаюсь найти самый простой и оптимальный. К сожалению, через параметр формы не удастся. Т.к. форму в модальном режиме использовать нельзя. Предлагайте свои варианты.
23. Владимир Костецкий (astonvilla) 10.10.07 09:32
Понимаешь, пока нет реальной необходимости в использовании, решать возникающие проблемы при интеграции никто не будет.
24. Владимир (svsrus) 10.10.07 09:38
У меня реальная необходимость)))
25. Михаил Семенов (Shaman100M) 24.10.07 21:47
Я так понял, ТЗ в качестве "подложки" использовано только из-за "громоздкости" назначить тип "неопределенный" для ячеек таблицы. Но можно же хранить значение, тип которого пока неопределен как строку через ЗначениеВСтрокуВнутр(объект). А?
26. Владимир (svsrus) 24.10.07 22:03
(25) Правильно понял. Поскольку таблица задумывалась как универсальная, то на теоритических примерах при размере 1000 на 1000 и более обработка просто "неподъемная" и не летающая). Но практически редко бывает более 50 на 50, так что вполне свободно можно использовать и какой-то тип. НО, использование подложки в виде ТЗ имеет свои плюсы. Скоро увидишь.
Хранить можно, а представлять в таблице как?
27. Михаил Семенов (Shaman100M) 25.10.07 09:10
(26) Представление. Должно работать:
Код
Ячейка.Текст = СокрЛП(Элемент);
Ячейка.Значение = ЗначениеВСтрокуВнутр(Элемент);
Показать полностью


Хранение в ТЗ: согласен, удобно.
Посмотрел, установка большого кол-ва строк и столбцов 10т х 10т память почти не кушает. :0 Приходится бороться со своим рационализмом: по старинке сделал бы типа, "4-ой формы нормализации": ТЗ с 4 колонками "НомСтроки","НомСтолбца","Значение","Индекс". В первой строке ТЗ хранить размерность, а Индекс - порядковый номер ячейки при проходе слева - направо, сверху-вниз.
28. Владимир (svsrus) 25.10.07 10:06
(27) Нет. Не работает. В режиме ввода Ячейка.Текст = Ячейка.Значение;

Гы. Запустил 10т на 10т. 5 минут подождал, не дождался ))) Прервал. Комп, правда, слабенький.

Рационализм? В итоге у тебя получится в 3 раза больше ТЗ. А надо оно?

29. Михаил Семенов (Shaman100M) 25.10.07 13:02
(27) Да, действительно Текст = Значение.

Перепроверил еще раз. Память кушает. Создал ТЗ 1т колонок и 1т столбцов - 80мб. Видимо, забыл обозначить ТЗ как переменную модуля...
Рационализм относился к задаче "редкой" посадки на большом поле. Можно использовать и список значений с представлением-составным адресом... но при макс. наполнении память еще больше, а поиск значения по представлению вообще ни в какие рамки... Так что, остается единственный вариант.
30. Владимир (svsrus) 25.10.07 13:43
(29) На чсет "редкой посадки ты прав однако ) Для моей задачи так даже удобнее наверное будет. Подумаю над этим.

Запустил 1000 на 1000. Жду 5 минут. Пока не вывелось ( Уже съело 170 Мб оперативки и фаул подкачки увеличился на 50 Мб... ((( ТЗ идет как переменная модуля. Наверно связано с расскраской таблицы.
31. Михаил Семенов (Shaman100M) 25.10.07 17:11
+(29) Единственный вариант имелся ввиду твой.
Тестил не в проге:
ТЗ.КоличествоКолонок(1000);
ТЗ.КоличествоСтрок(1000);

Можно также использовать массив, инициализация "весит" те же 80мб
Перем ВместоТЗ[1000000]; ;)

но ТЗ интереснее - можно задать размер динамически.
34. dswfsw dsfsd (juk12345) 23.05.16 18:33
Не очень практично. А если СЗ будет под 1000 значений? Пролистаешь? А разнотипные данные? По сути в данном случае не используется таблица для ввода данных по назначению да и сама табличка суто однотипные данные без какого-либо подсчета.
Таблицы ввода в 7.7 извратные по причине невозможности присвоения имен области таблицы программным методом, к сожалению. Мне сейчас это так необходимо, как воздух. Приходится извращаться с ВК.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа