Архив метки: 1c

Как постранично (порционно) листать результат запроса в 1С (ака LIMIT x,y в MySQL)

Большая беда MSSQL и как следствие 1С — отсутствие возможности порционно листать записи результата запроса как в MySQL. В результате рождаются такие монстроузные алгоритмы как ниже (код не мой):

Функция GetNewsList(body, answer) Экспорт
	
	answer.error = Истина;
	answer.errortext = "Что-то пошло не так..";
	answer.result = "";
	
	Попытка
		page = ?(ЗначениеЗаполнено(body.page), Число(body.page), 1);
		Если page < 1 Тогда
			page = 1;
		КонецЕсли;
		
		nums = ?(ЗначениеЗаполнено(body.nums), Число(body.nums), 5);
		Если nums < 5 Тогда
			nums = 5;
		КонецЕсли;
		
		ПредДата = ТекущаяДата();
		ПредКод = "";
		Если page > 1 Тогда
			Запрос = Новый Запрос;
			Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 100
			               |	Хрюкости.Дата КАК Дата,
			               |	Хрюкости.Код КАК Код
			               |ПОМЕСТИТЬ тПредыдущих
			               |ИЗ
			               |	Справочник.ПоследниеСплетни КАК Хрюкости
			               |
			               |УПОРЯДОЧИТЬ ПО
			               |	Хрюкости.Дата УБЫВ,
			               |	Хрюкости.Код УБЫВ
			               |;
			               |
			               |////////////////////////////////////////////////////////////////////////////////
			               |ВЫБРАТЬ ПЕРВЫЕ 1
			               |	тПредыдущих.Дата КАК Дата,
			               |	тПредыдущих.Код КАК Код
			               |ИЗ
			               |	тПредыдущих КАК тПредыдущих
			               |
			               |УПОРЯДОЧИТЬ ПО
			               |	тПредыдущих.Дата,
			               |	тПредыдущих.Код";
			Запрос.Текст = СтрЗаменить(Запрос.Текст, "100", Формат((page - 1) * nums, "ЧДЦ=0; ЧН=; ЧГ="));
			Выборка = Запрос.Выполнить().Выбрать();
			Если Выборка.Следующий() Тогда
				ПредДата = Выборка.Дата;
				ПредКод = Выборка.Код;
			КонецЕсли;
		КонецЕсли;
		
		Запрос = Новый Запрос;
		Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 100
		               |	Хрюкости.Код КАК news_code,
		               |	Хрюкости.Дата КАК date,
		               |	Хрюкости.Наименование КАК name,
		               |	Хрюкости.Содержание КОНЕЦ КАК content,
		               |	Хрюкости.Изображение КАК image
		               |ИЗ
		               |	Справочник.ПоследниеСплетни КАК Хрюкости
		               |ГДЕ
		               |	(Хрюкости.Дата < &ПредДата)
		               |	ИЛИ
					   |	(Хрюкости.Дата = &ПредДата И Хрюкости.Код < &ПредКод)
		               |
		               |УПОРЯДОЧИТЬ ПО
		               |	Хрюкости.Дата УБЫВ,
		               |	Хрюкости.Код УБЫВ";
		Запрос.Текст = СтрЗаменить(Запрос.Текст, "100", Формат(nums, "ЧДЦ=0; ЧН=; ЧГ="));
		Запрос.УстановитьПараметр("ПредДата", ПредДата);
		Запрос.УстановитьПараметр("ПредКод", ПредКод);
		Выборка = Запрос.Выполнить().Выбрать();
		
		РезМассив = Новый Массив;
		Пока Выборка.Следующий() Цикл
			РезСтрукт = Новый Структура("news_code, date, datestr, name, content, image");
			ЗаполнитьЗначенияСвойств(РезСтрукт, Выборка);
			РезСтрукт.datestr = Формат(Выборка.date, "ДФ='dd.MM.yyyy HH:mm:ss'");
			РезМассив.Добавить(РезСтрукт);
		КонецЦикла;
		
		ЕстьЕще = Ложь;
		Если РезМассив.Количество() > 0 Тогда
			КрайняяНовость = РезМассив[РезМассив.Количество() - 1];
			Запрос = Новый Запрос;
			Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1
			               |	Хрюкости.Код КАК news_code
			               |ИЗ
			               |	Справочник.ПоследниеСплетни КАК Хрюкости
			               |ГДЕ
			               |	(Хрюкости.Дата < &ПредДата)
			               |	ИЛИ
						   |	(Хрюкости.Дата = &ПредДата И Хрюкости.Код < &ПредКод)
			               |
			               |УПОРЯДОЧИТЬ ПО
			               |	Хрюкости.Дата УБЫВ,
			               |	Хрюкости.Код УБЫВ";
			Запрос.УстановитьПараметр("ПредДата", КрайняяНовость.date);
			Запрос.УстановитьПараметр("ПредКод", КрайняяНовость.news_code);
			ЕстьЕще = НЕ Запрос.Выполнить().Пустой();
		КонецЕсли;
		
		answer.result = Новый Структура("portion, havingmore", РезМассив, ЕстьЕще);
		answer.error = Ложь;
		answer.errortext = "";
		
	Исключение
		answer.errortext = ОписаниеОшибки();
	КонецПопытки;
	
	Возврат answer;
	
КонецФункции

Если вкратце, то алгоритм следующий:

  1.  Делаем выборку ВСЕХ записей, определяя, с какой записи было начало предыдущей страницы
  2. Начиная с этой записи, делаем выборку N записей
  3. Передаем результат

Интересно будет посмотреть как этот алгоритм будет вести себя при миллионах записей..

 

1С: Выбор адреса в форме документа

Исходные данные: 1С Бухгалтерия 3.0.75.100, платформа 8.3.16.1063

В одной из задач, понадобилось вбивать валидный адрес (на основе КЛАДР) в одно из полей документа. Было принято решения использовать для этого стандартный функционал 1С.

Результат работы будет выглядеть как-то так:

Итак, последовательность работ:

1) В справочнике «Виды контактной информации», добавляем предопределенный значения «ДокументАбоненты» и «АдресТочкиПодключения». Собственно первое, это название документа в котором будет отображаться форма, и второе — что именно мы храним:

2) В документе создаем табличную часть «Контактная информация» (можно скопировать например из справочника «Торговые точки»)

3) На форме документа располагаем пустую группу с именем «ГруппаКонтактнаяИнформация»

4) В модуль формы копируем:

// СтандартныеПодсистемы.КонтактнаяИнформация

&НаКлиенте
Процедура Подключаемый_КонтактнаяИнформацияПриИзменении(Элемент)
	УправлениеКонтактнойИнформациейКлиент.НачатьИзменение(ЭтотОбъект, Элемент);
	
КонецПроцедуры

&НаКлиенте
Процедура Подключаемый_КонтактнаяИнформацияНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	УправлениеКонтактнойИнформациейКлиент.НачатьВыбор(ЭтотОбъект, Элемент, , СтандартнаяОбработка);
КонецПроцедуры

&НаКлиенте
Процедура Подключаемый_КонтактнаяИнформацияПриНажатии(Элемент, СтандартнаяОбработка)
	УправлениеКонтактнойИнформациейКлиент.НачатьВыбор(ЭтотОбъект, Элемент,, СтандартнаяОбработка);
КонецПроцедуры

&НаКлиенте
Процедура Подключаемый_КонтактнаяИнформацияОчистка(Элемент, СтандартнаяОбработка)
	УправлениеКонтактнойИнформациейКлиент.НачатьОчистку(ЭтотОбъект, Элемент.Имя);
КонецПроцедуры

&НаКлиенте
Процедура Подключаемый_КонтактнаяИнформацияВыполнитьКоманду(Команда)
	УправлениеКонтактнойИнформациейКлиент.НачатьВыполнениеКоманды(ЭтотОбъект, Команда.Имя);
КонецПроцедуры

&НаСервере
Процедура ОбновитьКонтактнуюИнформацию(Результат)		
	УправлениеКонтактнойИнформацией.ОбновитьКонтактнуюИнформацию(ЭтотОбъект, Объект, Результат);

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

&НаКлиенте
Процедура Подключаемый_ПродолжитьОбновлениеКонтактнойИнформации(Результат, ДополнительныеПараметры) Экспорт
	
	ОбновитьКонтактнуюИнформацию(Результат);
	
КонецПроцедуры

&НаКлиенте
Процедура Подключаемый_КонтактнаяИнформацияАвтоПодбор(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, Ожидание, СтандартнаяОбработка)
	
	УправлениеКонтактнойИнформациейКлиент.АвтоПодборАдреса(Элемент, Текст, ДанныеВыбора, ПараметрыПолученияДанных, Ожидание, СтандартнаяОбработка);
	
КонецПроцедуры

&НаКлиенте
Процедура Подключаемый_КонтактнаяИнформацияОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
	
	УправлениеКонтактнойИнформациейКлиент.ОбработкаВыбора(ЭтотОбъект, ВыбранноеЗначение, Элемент.Имя, СтандартнаяОбработка);
	
КонецПроцедуры

&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)

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

&НаСервере
Процедура ПриЗакрытииНаСервере()	
	Адрес = УправлениеКонтактнойИнформацией.КонтактнаяИнформацияОбъекта(Объект.Ссылка,Справочники.ВидыКонтактнойИнформации.АдресТочкиПодключения);
	если Адрес<>"" тогда
		об=Документы.Абоненты.НайтиПоНомеру(объект.Номер).ПолучитьОбъект();		
		об.АдресПодключения=Адрес;
		об.Записать();
		объект.АдресПодключения=Адрес;			
	конецесли;	
КонецПроцедуры

&НаКлиенте
Процедура ПриЗакрытии(ЗавершениеРаботы)
	ПриЗакрытииНаСервере();
КонецПроцедуры

// Конец СтандартныеПодсистемы.КонтактнаяИнформация

1С: Ошибка при выполнении файловой операции 1cv8.cfu. Неожиданный вызов метода MemoryMappedFileObject :: write

Неожиданно при попытке обновления вылезла такая ошибка. Гугленье давало противоречивые результаты. Как лечил?

1) Достал оригинальный cf файл от релиза совпадающего с тем, который хотел обновлять (orig.cf)

2) Выгрузил в файл cf текущую конфигурацию (cur.cf)

3) Создал Новую БД, загрузил в неё orig.cf, объеденил, предварительно сняв с поддержки, с cur.cf, выгрузил файл cur_orig.cf

4) В текущую базу БД загрузил файл cur_orig.cf

5) Поставил на поддержку, изменив комментарий в любом реквизите, и обьеденив с конфигурацией orig.cf Перед началом объединения будет вопрос «поставить на поддержку?». Отвечаем Да, и выбираем галочки «Объект редактируется с сохранением поддержки»

6) Штатно обновил до следующего релиза..

Надеюсь косяков и глюков не будет.. Сильно надеюсь…

Снижения приоритета для определенных процессов в Windows

Ситуация: сервер RDP, где люди работают в 1С. Часть пользователей к сожалению не удается переубедить НЕ пользоваться браузерами на удаленном рабочем столе, в результате иногда получаются ситуации что процессор забит на 100% из-за открытых firefox и chrome в ущерб работе непосредственно 1С.

Выход: принудительное понижение приоритета выполнения браузеров при помощи скрипта PowerShell

Скрипт prior.ps1:

#PowerShell
function set-ProcessPriority { 
    param($processName = $(throw "Enter process name"), $priority = "Normal")
    get-process -processname $processname | foreach { $_.PriorityClass = $priority }
    write-host "`"$($processName)`"'s priority is set to `"$($priority)`""
}

set-ProcessPriority chrome BelowNormal
set-ProcessPriority firefox BelowNormal
set-ProcessPriority sbis3plugin BelowNormal
Start-Sleep -Seconds 3

Для того, чтобы он без проблемно выполнялся через планировщик заданий, так-же необходимо задать групповые политики для PowerShell

 

Диалоговое окно в 1С

Можно реализовать стандартным способом, что-то типа:

&НаКлиенте
Процедура ВыключитьИнтернет(Команда)
	Оповещение = Новый ОписаниеОповещения("ПослеЗакрытияВопроса",ЭтотОбъект);	
	ПоказатьВопрос(Оповещение,
        "Вы убеждены что хотите отключить несчастного контрагента?",
        РежимДиалогаВопрос.ДаНет,
        0, // таймаут в секундах
        КодВозвратаДиалога.нет, // (необ.) кнопка по умолчанию
        "Хороший вопрос" // (необ.) заголовок
    );    
КонецПроцедуры
&НаКлиенте
Процедура ПослеЗакрытияВопроса(Результат,Параметры)  Экспорт
	если Результат=КодВозвратаДиалога.Да тогда
		сообщить("--жаль..");
	иначе
		сообщить("");
	конецесли;	
КонецПроцедуры