Заметочки про 1С:Предприятие 8 (редакция 22.06.2012)

11.07.13

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

За время программирования на 8.х, накопилось пока немного материала, но как мне кажется очень интересного. Появились простые решения, которые в более сложной реализации встречаются в типовых конфигурациях и в некоторых публикациях на Infostart'е. Собственно в статье речь пойдет об этих решениях.

Скачать файлы

Наименование Файл Версия Размер
КодВОднуСтроку.epf
.epf 7,47Kb
626
.epf 7,47Kb 626 Скачать
Пример 1
.epf 7,28Kb
1229
.epf 7,28Kb 1229 Скачать
Пример 2
.epf 8,52Kb
542
.epf 8,52Kb 542 Скачать
Пример 3 без оптимизации
.epf 9,72Kb
475
.epf 9,72Kb 475 Скачать
Пример 3 с оптимизацией
.epf 10,34Kb
466
.epf 10,34Kb 466 Скачать
Гостинец от Ish_2
.epf 9,91Kb
421
.epf 9,91Kb 421 Скачать
Пример 4
.epf 8,13Kb
449
.epf 8,13Kb 449 Скачать
Пример 5
.epf 7,78Kb
375
.epf 7,78Kb 375 Скачать
COM MONITOR
.epf 23,63Kb
369
.epf 23,63Kb 369 Скачать
Пример 6 для COM Monitor
.epf 271,79Kb
511
.epf 271,79Kb 511 Скачать
Пример 7
.epf 9,47Kb
294
.epf 9,47Kb 294 Скачать
Пример 8
.erf 13,23Kb
270
.erf 13,23Kb 270 Скачать
Пример 9
.erf 12,69Kb
247
.erf 12,69Kb 247 Скачать
Пример 10
.epf 10,76Kb
52
.epf 10,76Kb 52 Скачать
Только качественный контент

Оглавление

Если вы это всё уже знаете, то, пожалуйста, не кидайте в автора грязью. Танки грязи не боятся. Smile

Но всё-таки я надеюсь вас чем-нибудь удивить.

В подтверждение заметок описанных в статье прикладываю примеры и материалы. Всегда можно проверить.

Для вступления думаю достаточно. Начнем.       


Про циклы в одну строку

Первым номером нашей программы выступает код добавления (копирования) строк из одной таблицы значений в другую ТЗ или из одной табличной части в другую ТЧ. Ну, и т.д. Т.е. строки из обоих источников объединяются, совпадающие по имени колонки заполняются.

Для каждого СтрокаТЗ Из Таблица1 Цикл ЗаполнитьЗначенияСвойств(Таблица2.Добавить(), СтрокаТЗ) КонецЦикла;


Соответственно код добавления элементов из массива в массив будет такой.

Для каждого ЭлементМассива Из Массив1 Цикл Массив2.Добавить(ЭлементМассива) КонецЦикла;


Всего одна команда в цикле - что может быть проще?

Наверное, вы уже обратили внимание на запись циклов в одну строку. Так программный код выполняется несколько быстрее. Всё дело в том, что в строках есть дополнительные данные, которые используются, например, при отладке. Меньше строк - меньше дополнительных данных. Это прекрасно видно, если смотреть замер производительности в режиме отладки - цикл в строке Для из 10000 повторов записанный обычной структурой будет выполнен 10001 раз, а записанный в 1 строку будет выполнен 1 раз. Разумеется, что при этом результат выполнения программного кода будет абсолютно одинаковый, а вот время выполнения будет разное. Не верится? Смотрим "Пример 1".
Скачать Пример 1...

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

Также "тонким" моментом будет использование команды ОбработкаПрерыванияПользователя(). Если в цикле, записанном в 1 строку, используется данная команда, то вероятность срабатывания прерывания выполнения программы по Ctrl+Break становится не четким. Ну, может за исключением тех случаев, когда в цикле кроме этой других команд нет. Smile

Хочу сразу обратить ваше внимание на комментарии awa к этой статье. Всё сразу станет понятнее.

Обработку для сворачивания программного кода в 1 строку можно скачать здесь.

Вернуться к оглавлению...


Про быстрые массивы

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

// РазбираемаяСтрока - строка исходного текста
// Разделитель - разделитель элементов строки

ЗначениеИзСтрокиВнутр("{""#"",51e7a0d2-530b-11d4-b98a-008048da3034,{0,{""S"",""" + СтрЗаменить(СтрЗаменить(РазбираемаяСтрока, """", """"""), Разделитель, """},{""S"",""") + """}}}");


Вот код для числовых значений.

ЗначениеИзСтрокиВнутр("{""#"",51e7a0d2-530b-11d4-b98a-008048da3034,{0,{""N""," + СтрЗаменить(РазбираемаяСтрока, Разделитель, "},{""N"",") + "}}}");


Посмотреть, как это работает можно здесь, здесь и здесь.
В (150) комментарии к статье было высказано предположение, что данный метод не эффективен, поэтому был добавлен "Пример 7". Действительно, на коротких строках предложенное в (150) комментарии решение с разбором строки эффективнее, но сложнее в исполнении. Ещё более эффективное решение и ещё более сложное в исполнении Smile читаем ниже...
Скачать Пример 7...

 

Так, так, так. А вот довольно шустренький программный код для сворачивания элементов массива. Результат записывается в НовыйМассив.

НовыйМассив = Новый Массив; Соответствие = Новый Соответствие;
Для каждого
ЭлементМассива Из Массив Цикл Соответствие.Вставить(ЭлементМассива) КонецЦикла;
Для каждого
КлючИЗначение Из Соответствие Цикл НовыйМассив.Добавить(КлючИЗначение.Ключ) КонецЦикла;


Для сравнения в "Пример 4" приведено 4 варианта реализации сворачивания массива: через массив, через таблицу значений, через соответствие и вариант, реализованный в типовых конфигурациях 1С. Поэкспериментируйте и выберите тот, что вам больше понравится.
Скачать Пример 4...

 

Если вдруг понадобится отсортировать элементы в массиве, то быстро это можно сделать так:

СписокЗначений = Новый СписокЗначений;
СписокЗначений.ЗагрузитьЗначения(Массив);
СписокЗначений.СортироватьПоЗначению();
Массив = СписокЗначений.ВыгрузитьЗначения();

В некоторых случаях больше подойдет сортировка не по значению, а по представлению.

Вернуться к оглавлению...


Про длинные строки

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

// Получаем строку пробелов длиной 10000 символов
СтрокаПробелов = СтрЗаменить(Формат(0, "ЧЦ=100; ЧН=; ЧВН=; ЧГ="), "0",
                
СтрЗаменить(Формат(0, "ЧЦ=100; ЧН=; ЧВН=; ЧГ="), "0", " ")); 


Интересное наблюдение при работе со строками большой длины можно сделать в "Пример 5". Использование трехуровневой буферизации может дать ускорение в десятки и даже тысячи раз. Код может выглядеть так:

Данные = "";
Результат = "";
Результат1 = "";
Результат2 = "";
// Получаем Данные и записываем в Результат
Пока ПолучитьДанные(Данные) Цикл
   
Результат2 = Результат2 + Данные;
    Если
СтрДлина(Результат2) > 100 Тогда
       
Результат1 = Результат1 + Результат2;
       
Результат2 = "";
        Если
СтрДлина(Результат1) > 10000 Тогда
           
Результат = Результат + Результат1;
           
Результат1 = "";
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

Результат = Результат + Результат1 + Результат2;


Конечно, и здесь цикл можно записать в одну строку, но это не сделано только для сохранения читаемости программного кода в статье.
Скачать Пример 5...

В (302) комментарии к статье приведен интересный код для разбора длинных текстовых строк, позволяющий проводить предварительную обработку данных, например, перед помещением их в массив. Применительно к задаче помещения данных в массив на больших объемах данных он работает конечно медленнее, чем код описанный в разделе Про быстрые массивы, но возможность предварительной обработки данных дорогого стоит. Предлагаю рассмотреть альтернативное решение без использования объекта ТекстовыйДокумент. Оно конечно сложнее в исполнении, но эффективнее в работе и также позволяет добавить предварительную обработку данных, например, перед помещением их в массив.

ДлинаСтроки = СтрДлина(РазбираемаяСтрока);

Если
ДлинаСтроки > 1000 Тогда
   
// Порежем строку на блоки для более эффективного поиска
   
МассивСтрок = Новый Массив;
   
Индекс = 1;
    Пока
Индекс <= ДлинаСтроки Цикл
       
МассивСтрок.Добавить(Сред(РазбираемаяСтрока, Индекс, 1000));
       
Индекс = Индекс + 1000;
    КонецЦикла;

   
мИсходныйКод = МассивСтрок[0];
   
ГраницаКода = МассивСтрок.ВГраница();
Иначе
   
мИсходныйКод = РазбираемаяСтрока;
   
ГраницаКода = 0;
КонецЕсли;


мСтрок = Новый Массив;
ИндексКода = 0;
ДлинаРазделителя = СтрДлина(Разделитель);
НеПоследняяСтрока = Истина;

Пока
НеПоследняяСтрока Цикл
   
Позиция = Найти(мИсходныйКод, Разделитель);
    Пока
Позиция = 0 Цикл
        Если
ИндексКода = ГраницаКода Тогда
           
// Последний элемент
           
Позиция = СтрДлина(мИсходныйКод);
           
НеПоследняяСтрока = Ложь;
            Прервать;
        КонецЕсли;

       
ИндексКода = ИндексКода + 1;
       
мИсходныйКод = мИсходныйКод + МассивСтрок[ИндексКода];
       
Позиция = Найти(мИсходныйКод, Разделитель);
    КонецЦикла;

   
мСтрок.Добавить(Лев(мИсходныйКод, Позиция));
   
мИсходныйКод = Сред(мИсходныйКод, Позиция + ДлинаРазделителя);
КонецЦикла;

Возврат
мСтрок;


Посмотреть как это работает можно здесь и здесь.

 

Если вы подумали, что эта статья только об оптимизации производительности, то это не так. Статья об оптимизации производительности здесь, и не смотря на то, что статья посвящена 7.7, многие приемы оптимизации работают и в 8.х.

Вернуться к оглавлению...


Про типы данных. Динамическая настройка колонок табличного поля

Иногда бывает нужно проверить тип данных какого-либо ревизита. Для типов данных без квалификаторов проверку типа данных легко сделать с помощью ОписаниеТипов. А вот для типов данных Число, Строка и Дата можно использовать другую конструкцию с использованием массива типов. Вот пример для динамической настройки табличного поля. В примере использованы оба способа сравнения типов.

ТипЧисло = Тип("Число");
ОписаниеТипаБулево = Новый ОписаниеТипов("Булево");

мВыводитьПодвал = Ложь;
ТабличноеПоле.СоздатьКолонки();
КолонкиИсточника = ТабличноеПоле.Значение.Колонки;

// Отобразим булево как галочки, а отрицательные числа красным
Для каждого КолонкаТЧ Из ТабличноеПоле.Колонки Цикл
   
ИмяКолонкиТЧ = КолонкаТЧ.Имя;
   
ТипЗначенияКолонки = КолонкиИсточника[ИмяКолонкиТЧ].ТипЗначения;
    Если
ТипЗначенияКолонки = ОписаниеТипаБулево Тогда
       
КолонкаТЧ.ДанныеФлажка = КолонкаТЧ.Данные;
       
КолонкаТЧ.Данные = "";
    ИначеЕсли
ИмяКолонкиТЧ <> "НомерСтроки" Тогда
       
МассивТипов = ТипЗначенияКолонки.Типы();
        Если
МассивТипов.Количество() = 1 и МассивТипов[0] = ТипЧисло Тогда
           
КолонкаТЧ.ВыделятьОтрицательные = Истина;
           
КолонкаТЧ.ОтображатьИтогиВПодвале = Истина;
           
КолонкаТЧ.ГоризонтальноеПоложениеВПодвале = ГоризонтальноеПоложение.Право;
           
мВыводитьПодвал = Истина;
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

ТабличноеПоле.Подвал = мВыводитьПодвал;


К вопросу "Почему не воспользоваться методом СодержитТип?". Метод СодержитТип не дает однозначного ответа на вопрос "Какой тип реквизита?". Он только подтверждает, что реквизит может быть, например, числом. А если реквизит составного типа?

Как это работает можно посмотреть здесь.

Вернуться к оглавлению...


Про типы данных. Расчет сумм по выделенным ячейкам табличного поля

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

Предлагаю простенькую функцию, в которой данный "эффект" устранен.

Функция РасчетСуммыПоЯчейкам(ТабличноеПоле) Экспорт

   
Сумма = 0;
   
КоличествоСумм = 0;
   
СоответствиеЯчеек = Новый Соответствие;
   
ОписаниеТипов = Новый ОписаниеТипов("Число");

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

    Для каждого
Ячейка Из СоответствиеЯчеек Цикл
       
Значение = Ячейка.Значение;
        Если
Значение <> 0 Тогда
           
Сумма = Сумма + Значение;
           
КоличествоСумм = КоличествоСумм + 1;
        КонецЕсли;
    КонецЦикла;

   
КоличествоВыделено = СоответствиеЯчеек.Количество();
    Если
КоличествоВыделено > 1 Тогда
       
ТекстИтогов = " Выделено ячеек: " + КоличествоВыделено
            + "    Просуммировано ячеек: " + КоличествоСумм
            + "    Итого по выделенным ячейкам: " + Сумма;
    Иначе
       
ТекстИтогов = "";
    КонецЕсли;

    Возврат
ТекстИтогов;

КонецФункции
// РасчетСуммыПоЯчейкам()


Использование метода ПривестиЗначение вместо встречающегося в типовых конфигурациях преобразования через Попытка, дает в среднем ускорение на преобразовании типов в 4 раза. А использование отложенного вызова функции расчета суммы всего лишь на 0.2 секунды с легкостью решает проблему с задержками при выделении пользователем большого количества ячеек.

Посмотреть как это работает можно здесь и здесь.

Ещё про работу с типами данных можно почитать ниже...

Вернуться к оглавлению...


Про хитрые запросы. Не стандартное использование итогов

А что сейчас? А сейчас запросы. Не все конечно, а несколько каких-нибудь простеньких и интересненьких. Например, построение запросом двухуровневого дерева структуры задолженности для формы элемента справочника Контрагенты. Исходим из того, что чем меньше команд, тем быстрее работает. Ну, обычно быстрее. Ведь 1С это все-таки интерпретатор.

Итак, строим запросом дерево по структуре задолженности как на картинке ниже, смотрим закладку Задолженность. На закладке добавлено табличное поле с деревом значений Задолженность.

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

Запрос = Новый Запрос(
   
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
    | ДоговорыКонтрагентов.Организация КАК Организация,
    | ДоговорыКонтрагентов.Ссылка КАК СтруктураДоговоров,
    | -ЕСТЬNULL(ВзаиморасчетыОстатки.СуммаВзаиморасчетовОстаток, 0) КАК Сумма
    |ИЗ
    | Справочник.ДоговорыКонтрагентов КАК ДоговорыКонтрагентов
    |  ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ВзаиморасчетыСКонтрагентами.Остатки(
    |       , Контрагент = &Контрагент) КАК ВзаиморасчетыОстатки
    |  ПО ДоговорыКонтрагентов.Ссылка = ВзаиморасчетыОстатки.ДоговорКонтрагента
    |ГДЕ
    | ДоговорыКонтрагентов.Владелец = &Контрагент
    |
    |УПОРЯДОЧИТЬ ПО
    | Организация,
    | СтруктураДоговоров
    |ИТОГИ
    | Организация КАК СтруктураДоговоров,
    | СУММА(Сумма)
    |ПО
    | Организация"
);
Запрос.УстановитьПараметр("Контрагент", Ссылка);
Задолженность = Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам);


Получилось простенько и симпатично.

В итогах Организация используется без агрегатной функции - это возможно потому, что по Организации выполняется группировка. Ещё примеры построения двухуровневого дерева можно посмотреть здесь.

Вернуться к оглавлению...


Про хитрые запросы. Тэта-соединения 1

Кажется тема с запросами получилась интересной. Тогда ещё один примерчик "Пример 2", который можно подержать в руках - изменение курсов валют с группировкой по месяцам.

 

Запрос = Новый Запрос(
   
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
    |   КурсыВалют.Период КАК Период1,
    |   МАКСИМУМ(ЕСТЬNULL(КурсыВалют1.Период, КурсыВалют.Период)) КАК Период2
    |ПОМЕСТИТЬ Соединения
    |ИЗ
    |   РегистрСведений.КурсыВалют КАК КурсыВалют
    |       ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК КурсыВалют1
    |       ПО КурсыВалют.Валюта = КурсыВалют1.Валюта
    |           И КурсыВалют.Период > КурсыВалют1.Период
    |           И (КурсыВалют1.Валюта = &Валюта)
    |ГДЕ
    |   КурсыВалют.Валюта = &Валюта
    |
    |СГРУППИРОВАТЬ ПО
    |   КурсыВалют.Период
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ РАЗРЕШЕННЫЕ
    |   КурсыВалют.Период КАК Период,
    |   НАЧАЛОПЕРИОДА(КурсыВалют.Период, МЕСЯЦ) КАК ПериодДляИтогов,
    |   КурсыВалют.Курс,
    |   КурсыВалют.Курс - КурсыВалют1.Курс КАК ИзменениеКурса
    |ИЗ
    |   РегистрСведений.КурсыВалют КАК КурсыВалют
    |       ВНУТРЕННЕЕ СОЕДИНЕНИЕ Соединения КАК Соединения
    |           ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК КурсыВалют1
    |           ПО Соединения.Период2 = КурсыВалют1.Период
    |               И (КурсыВалют1.Валюта = &Валюта)
    |       ПО КурсыВалют.Период = Соединения.Период1
    |           И (КурсыВалют.Валюта = &Валюта)
    |ИТОГИ
    |   ПериодДляИтогов КАК Период,
    |   СУММА(ИзменениеКурса)
    |ПО
    |   ПериодДляИтогов"
);
Запрос.УстановитьПараметр("Валюта", Валюта);
КурсыВалют = Запрос.Выполнить().Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкам); 


Аналогично можно построить и другие запросы, в которых отслеживается изменение значений показателей, например, изменение цен.
Скачать Пример 2...

Вернуться к оглавлению...


Про хитрые запросы. Тэта-соединения 2

"Продолжаем разговор". В качестве ещё одного примера работы с запросами добавлен "Пример 3", в котором реализовано получение периодов действия установленных значений периодических регистров сведений. Перечитал предыдущее предложение - получилось немного тяжеловато, ну, да ладно. Предложенное решение в "Пример 3" может быть использовано, например, при решении задач по расчету заработной платы или при начислениях в ЖКХ.

Пример 3

Фишка этого запроса в том, чтобы убрать повторяющиеся данные из цепочки, а оставить только точки перехода с датами, когда данный переход был выполнен.
Т.е. для цепочки значений 0, 0, 1, 1, 1, 0, 0, 0, 1
должны остаться только значения 0, 1, 0, 1 и соответственно даты, когда значения в цепочке поменялись.

И несколько слов об оптимизации тэта-соединений. Во вложении 3 варианта реализации с использованием запросов, поэтому в статье текстов этих запросов нет - очень объемно получается. При больших объемах информации оптимизированный вариант запросов дает значительное ускорение, особенно в файловой версии. Это собственно и не удивительно, оптимизатор SQL сервера делает своё дело. Автором одного из вариантов является Ish_2 - это вариант "Гостинец".

Скачать Пример 3 без оптимизации...
Скачать Пример 3 с оптимизацией...
Скачать Гостинец от Ish_2...

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

Также интересный эффект получается при использовании индексов для временных таблиц. Попробуйте поиграть с объемами данных и галочками "Использовать индексы в запросе". Обещаю весьма неожиданный результат. Smile

Так уж получилось, что большинство комментариев к данной статье посвящено именно этому запросу. Видимо в нем есть тайное знание доступное теперь всем желающим.

Ещё про запросы можно посмотреть здесь, а про запросы с датами можно посмотреть здесь.

Вернуться к оглавлению... 


Про хитрые запросы. Тэта-соединения 3. Строки неограниченной длины

Делал загрузку прайсов из Excel. Если прайс и справочник Номенклатура маленькие, то конечно всё работает сравнительно быстро. Несколько секунд и сопоставление выполнено вне зависимости от того выполняется ли поиск в одном запросе или используется поиск по реквизитам справочника в цикле. Но в моём случае и справочник и прайс содержат десятки тысяч позиций. Всё бы ничего, но уж очень медленно получается при поиске соответствий Номенклатуры по полному наименованию.

Постановка задачи: найти элементы справочника Номенклатура, полное наименование которых совпадает с наименованием в прайсе поставщика. При больших объемах данных решение напрашивается само собой - использовать запрос.

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

Запрос = Новый Запрос(
   
"ВЫБРАТЬ
    |   ПОДСТРОКА(ТаблицаДляПоиска.НоменклатураXLS, 1, 40) КАК НоменклатураXLS_Индекс,
    |   ТаблицаДляПоиска.НоменклатураXLS КАК НоменклатураXLS
    |ПОМЕСТИТЬ ТаблицаДляПоиска
    |ИЗ
    |   &ТаблицаДляПоиска КАК ТаблицаДляПоиска
    |
    |ИНДЕКСИРОВАТЬ ПО
    |   НоменклатураXLS_Индекс
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |   СправочникНоменклатура.Ссылка КАК Номенклатура,
    |   СправочникНоменклатура.НаименованиеПолное КАК НоменклатураНаименование
    |ИЗ
    |   Справочник.Номенклатура КАК СправочникНоменклатура
    |       ВНУТРЕННЕЕ СОЕДИНЕНИЕ ТаблицаДляПоиска КАК ТаблицаДляПоиска
    |       ПО ПОДСТРОКА(СправочникНоменклатура.НаименованиеПолное, 1, 40) = ТаблицаДляПоиска.НоменклатураXLS_Индекс
    |           И ПОДСТРОКА(СправочникНоменклатура.НаименованиеПолное, 1, 1000) = ТаблицаДляПоиска.НоменклатураXLS
    |ГДЕ
    |   СправочникНоменклатура.ЭтоГруппа = ЛОЖЬ
    |   И СправочникНоменклатура.Услуга = ЛОЖЬ"
);

Запрос.УстановитьПараметр("ТаблицаДляПоиска", ТаблицаДляПоиска);
РезультатЗапроса = Запрос.Выполнить();

Решение лежало на поверхности. Правда?

Вернуться к оглавлению... 


Про пакетные запросы. Индексы во временных таблицах

Сегодня с утра была пятница. Пришло время открыть великую тайну-у-у-у.

В пакетных запросах в качестве источника данных часто выступает временная таблица. У временной таблицы есть возможность создавать индексы. В каких случаях создание индекса может ускорить выполнение запроса, а в каких наоборот?

Начнем с того, что посмотрим, когда не нужно создавать индексы. Ведь на создание индекса тратится время и ресурсы. Если индекс не будет использоваться, то его создание только замедлит выполнение запроса. Нет смысла создавать индексы, если временная таблица очень маленькая. Нет смысла создавать индексы, если временная таблица соединяется с другой таблицей по полям, которые во второй таблице уже проиндексированы.

Так когда же имеет смысл создавать индексы? Оказывается всё очень просто. Индексы имеет смысл создавать в случае, если выполняется условие сравнения на равенство. В качестве примера можно посмотреть запрос в предыдущем пункте Заметочек. Там как раз используется индекс именно в подобной ситуации.

Возможно со временем индексы будут использоваться и при других вариантах сравнения. Поживем, увидим.

Вернуться к оглавлению...


Про СКД и запросы с итогами

В комментариях к публикациям Как выгрузить итоги запроса в одну колонку ? и Запросики для восьмерочки развернулась настоящая битва между Ish_2 и tango. Просто жуть какая-то. Но вопросы были подняты очень интересные. Я очень внимательно следил за ходом обсуждения и после очередного комментария с примером обработки от Ish_2, появилась обработка, которая демонстрирует построение многоуровнего дерева в одной колонке "Поле4" с использованием как запроса с итогами, так и СКД. За основу была взята обработка, приложенная к комментарию.

 

Ах, да. "В чем же фишка?" - спросите вы. Всё просто. Из СКД сложное многоуровневое дерево в дерево значений выгружается быстрее. На контрольном примере разница составила в 30 раз. При использовании запроса сам запрос выполняется сравнительно быстро, а вот скорость выгрузки результата запроса в дерево значений оставляет желать лучшего.

Так как программного кода как такового при использовании СДК нет, то не совсем очевиден способ реализации. Куда смотреть? Смотреть нужно в пользовательских полях. 

 

Собственно весь вывод данных в обработке при использовании СКД построен на пользовательских полях. Это сделано для того, чтобы сохранить нужную последовательность колонок в дереве значений. Если порядок следования реквизитов не важен или реквизиты не нужны в результирующем дереве значений, то и добавлять реквизиты в пользовательские поля не нужно.
Скачать Пример 8...

Но как вы, наверное, догадываетесь, "Пример 8" это не единственный вариант реализации многоуровневого дерева в одной колонке с использованием СКД. Поэтому был добавлен "Пример 9", в котором "Поле4" строится не через пользовательские поля, а через ресурсы. Чем он лучше варианта в "Пример 8"? Работает немного быстрее предыдущего примера и названия колонок в результирующем дереве значений получаются более "ожидаемые".

Особенностью реализации "Пример 9" является расположение ресурсов в группировках. Это сделано только для того, чтобы управлять порядком следования колонок в результирующем дереве значений. Иначе колонки с группировками будут расположены впереди, а уже за ними колонка "Поле4". Чтобы можно было управлять порядком расположения реквизитов необходимо вначале сформировать группировки по реквизитам, а затем реквизиты описать как ресурсы. При необходимости формирования определенного порядка следования колонок в результирующем дереве необходимо для некоторых группировок заменить состав выбранных полей с Авто на требуемый. Если порядок следования реквизитов не важен или реквизиты не нужны в результирующем дереве значений, то и добавлять реквизиты в ресурсы не нужно.
Скачать Пример 9...

Возможность выбора варианта реализации многоуровнего дерева в одной колонке дерева значений есть. В данной публикации приведено 4 способа. Выбирайте. Реализуйте.

Вернуться к оглавлению...


Про дерево значений

Уже были рассмотрены примеры заполнения дерева значений с использованием запроса и СКД. Сейчас предлагаю рассмотреть несколько иной вариант работы с деревом значений.

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

Что мы получаем при использовании такого варианта работы с деревом? Быстрое первоначальное отображение дерева для пользователя. Что ещё? Немного больше кода при работе с деревом.

Вот тут мы и попляшем немного вокруг вопроса: "Как поместить необходимый набор данных в строки второго уровня?" Есть варианты.

Наиболее очевидный вариант описан в начале этой статьи в части "Про циклы в одну строку". Но он не единственный. Предлагаю рассмотреть ещё один кусочек кода, который намного производительнее при большом количестве строк в необходимом наборе данных.

Процедура ДеревоЗначенийПередРазворачиванием(Элемент, СтрокаДереваЗначений, Отказ)

    Если
СтрокаДереваЗначений.УровеньРазвернут Тогда
        Возврат;
    КонецЕсли;

   
СтрокиГруппировки = СтрокаДереваЗначений.Строки;
   
СтрокиГруппировки.Очистить();

   
ТаблицаЗначений = ПолучитьНаборНеобходимыхДанных(СтрокаДереваЗначений);

    Если
ТаблицаЗначений.Колонки.Количество() * 2 > ТаблицаЗначений.Количество() Тогда
        Для каждого
СтрокаТаблицыЗначений Из ТаблицаЗначений Цикл
           
ЗаполнитьЗначенияСвойств(СтрокиГруппировки.Добавить(), СтрокаТаблицыЗначений);
        КонецЦикла;
    Иначе
        Для
Индекс = 1 По ТаблицаЗначений.Количество() Цикл
           
СтрокиГруппировки.Добавить();
        КонецЦикла;

        Для каждого
Колонка Из ТаблицаЗначений.Колонки Цикл
           
СтрокиГруппировки.ЗагрузитьКолонку(ТаблицаЗначений.ВыгрузитьКолонку(Колонка.Имя), Колонка.Имя);
        КонецЦикла;
    КонецЕсли;

   
СтрокаДереваЗначений.УровеньРазвернут = Истина;

КонецПроцедуры
// ДеревоЗначенийПередРазворачиванием()

Циклы также можно оформить в одну строку, но для сохранения читаемости кода этого не сделано. На контрольном примере предложенный вариант заполнения был производительнее в 4 раза. Конечно же всё зависит от исходных данных и на других данных результаты могут быть другие, но о том, что 1С всё таки интерпретатор не стоит забывать. Правило "Чем меньше команд, тем быстрее работает программа" остается актуальным и по сей день.

Скачать пример...
Ещё про дерево значений можно посмотреть здесь...

Вернуться к оглавлению...


Про таблицу значений

Увидел публикацию Преобразование ТаблицыЗначений во Временную таблицу автора sashapere, в которой ТаблицаЗначений с колонками неопределенного типа подготавливается для использования в запросах. Т.е. проверяются типы значений в колонках, а затем создается новая таблица значений с колонками нужного типа и данные переносятся в неё. Такую таблицу значений уже можно использовать в запросах, передавая её в качестве параметра или источника данных для ПостроителяЗапросов и ПостроителяОтчетов.

Мне показалось, что код не очень эффективен и это можно сделать быстрее. Вот что из этого получилось.

КолонкиТаблицыЗначений = ТаблицаЗначений.Колонки;
Для
Индекс = 0 По КолонкиТаблицыЗначений.Количество() - 1 Цикл
   
МассивЗначений = ТаблицаЗначений.ВыгрузитьКолонку(0);

   
// Получаем типы значений, которые используются в колонке
   
Соответствие = Новый Соответствие;
   
СтТипЗначения = ТипЗнч(Неопределено);
    Для каждого
Значение Из МассивЗначений Цикл
       
ТипЗначения = ТипЗнч(Значение);
        Если
СтТипЗначения <> ТипЗначения Тогда
           
СтТипЗначения = ТипЗначения;
           
Соответствие.Вставить(ТипЗначения);
        КонецЕсли;
    КонецЦикла;

   
// Преобразуем соответствие в массив типов значений
   
МассивТипов = Новый Массив;
    Для каждого
КлючИЗначение Из Соответствие Цикл
       
МассивТипов.Добавить(КлючИЗначение.Ключ);
    КонецЦикла;

   
// Удаляем старую колонку без установленного типа значения
   
ИмяКолонки = КолонкиТаблицыЗначений[0].Имя;
   
КолонкиТаблицыЗначений.Удалить(0);
    Если
МассивТипов.Количество() = 0 или МассивТипов.Количество() = 1 и МассивТипов[0] = ТипЗнч(Неопределено) Тогда
       
// Устанавливаем тип значения по умолчанию для колонок, в которых не установлены значения
        // По умолчанию Строка
       
КолонкиТаблицыЗначений.Добавить(ИмяКолонки, Новый ОписаниеТипов("Строка"));
    Иначе
       
// Создаем и заполняем колонку с установленным типом
       
ТаблицаЗначений.ЗагрузитьКолонку(МассивЗначений,
           
КолонкиТаблицыЗначений.Добавить(ИмяКолонки, Новый ОписаниеТипов(МассивТипов)));
    КонецЕсли;
КонецЦикла;

Допускаю, что и этот код тоже можно оптимизировать. Нет предела совершенству. Поэтому предлагаю сравнить с другими вариантами в "Примере 10". Авторы двух добавленных вариантов sashapere и i132.

Скачать Пример 10...

Вернуться к оглавлению...


Про работу с COMОбъект("V81.Application") или как разогнать 1С в 1000 раз

Очень интересная публикация OLE - монитор автора ghostishe, в которой приложена обработка COM MONITOR. Мне как раз необходимо было сверить справочники в двух базах данных. В предложенной обработке всё понятно, но скорость получения данных из подключенной базы мне показалась крайне низкой. После небольшого эксперимента удалось получить такие же данные как в этой обработке, только в 30 раз быстрее, а после небольшой модификации удалось поднять скорость получения данных из подключенной базы ещё в 5 раз. Добавил "Пример 6". В предлагаемом примере разница во времени выполнения по сравнению с исходным образцом может составить от 15 до 1500 раз - это зависит от состояния базы данных и от объема получаемых данных. Чем больше данных нужно получить, тем больше может получиться разница.

Итак, что и как сравниваем. Во вложении 2 обработки: COM MONITOR и Пример 6 для COM Monitor.

COM MONITOR - во вложении, это почти оригинальная обработка, в которую добавлены команды для выполнения замера времени получения данных из подключенной базы. COM MONITOR работает в двух режимах: с закрытым окном подключенной базы данных и с открытым. Т.к. с открытым окном обработка работает очень медленно, то для сравнения берем только замер с закрытым окном.

Пример 6 для COM Monitor - эта обработка построена на основе COM MONITOR, ну, или почти так. Во всяком случае основной функционал (идею) постарался сохранить. Пример 6 для COM Monitor работает в двух режимах: с использованием дополнительной обработки и без неё. При установке соответствующего флажка используется дополнительная внешняя обработка, которая запускается в подключенной базе данных. Данные внешней обработке передаются через COMSafeArray, который в дальнейшем и обрабатывается. Обратно данные передаются аналогичным образом. Ни каких внешних компонент, всё по честному. AutoIt используется только чтобы вернуть фокус в 1С:Предприятие, а WScript для замера времени выполнения.

Скачать COM MONITOR от ghostishe...
Скачать Пример 6 для COM Monitor...

А теперь главный вопрос: за счет чего получается столь значительное ускорение? Ответ прост: за счет снижения количества разыменований. Да, да. На такой пустяковой операции как разыменование можно добиться столь значительного ускорения. Чем меньше точек в тексте модуля, тем выше скорость его выполнения. Разница особенно заметна при использовании COMОбъект(). Т. к. кроме разыменования здесь немаловажную роль играет передача данных между приложениями, то именно этот момент и решает применение дополнительной обработки. Данные между приложениями передаются всего 2 раза: туда и обратно.

Запускайте, тестируйте, удивляйтесь. Smile

Вернуться к оглавлению...


Про работу с НастройкаПериода, ЗаполнитьЗначенияСвойств и вообще

Вводные данные, ну, или описание исходной задачи были следующие:

  • Есть форма Основная, в которой есть возможность настраивать период. Для настройки периода используется объект НастройкаПериода, который вызывается на редактирование по кнопке.
  • Также ещё есть форма Настройка, в которой также можно редактировать период, но не только через объект НастройкаПериода, а ещё и через поля ввода дат начала и окончания периода.
  • Необходимо чтобы настройки указанные в форме Настройка можно принять и перенести в форму Основная или отказаться от сделанных изменений.

Казалось бы, всё просто, нужно в форме Настройка создать ещё один объект НастройкаПериода и заполнить его свойства. Например, так:

Функция СкопироватьНустройкуПериода(НастройкаПериодаИсходный)
   
НастройкаПериодаРезультат = Новый НастройкаПериода;
   
ЗаполнитьЗначенияСвойств(НастройкаПериодаРезультат, НастройкаПериодаИсходный);
    Возврат
НастройкаПериодаРезультат;
КонецФункции

Вот тут и начинается самое интересное. При использовании команды ЗаполнитьЗначенияСвойств свойства объекта НастройкаПериодаРезультат заполняются неверно, т.е. свойства, конечно, заполняются, но не так как в исходном объекте. А в некоторых случаях вообще возникает ошибка.

Почему нельзя просто присвоить? НастройкаПериодаРезультат = НастройкаПериодаИсходный; Потому, что получится не новый объект, а ссылка на исходный объект.

Один из вариантов создания нового объекта НастройкаПериода может быть таким:

Функция СкопироватьНустройкуПериода(НастройкаПериодаИсходный)
    Возврат
ЗначениеИзСтрокиВнутр(ЗначениеВСтрокуВнутр(НастройкаПериодаИсходный));
КонецФункции

С этим разобрались и новый объект НастройкаПериода у нас есть - можно редактировать. Теперь в случае отказа можно просто ничего не делать. Закрыть форму Настройка и всё.

Теперь рассмотрим сохранение (перенос) измененных данных периода в основную форму. Если редактирование периода было выполнено через объект НастройкаПериода, то всё просто.

НастройкаПериодаИсходный = НастройкаПериодаРезультат;

А вот в случае редактирования дат периода не всё так однозначно. Потому что способ, который используется в типовых конфигурациях, в некоторых случаях опять же дает неожиданный результат. Т.е. иногда срабатывает, а иногда нет. Вот код с заплаткой.

НастройкаПериодаИсходный = НастройкаПериодаРезультат;

Если
ДатаНачала <> НастройкаПериодаИсходный.ПолучитьДатуНачала()
    или
ДатаОкончания <> НастройкаПериодаИсходный.ПолучитьДатуОкончания() Тогда
   
НастройкаПериодаИсходный.УстановитьПериод(ДатаНачала, ?(ДатаОкончания = '00010101', ДатаОкончания, КонецДня(ДатаОкончания)));

   
// Заплатка
   
Если ДатаНачала <> НастройкаПериодаИсходный.ПолучитьДатуНачала()
        или
ДатаОкончания <> НастройкаПериодаИсходный.ПолучитьДатуОкончания() Тогда
       
НастройкаПериодаИсходный = Новый НастройкаПериода;
       
НастройкаПериодаИсходный.ВариантНачала = ВариантГраницыИнтервала.КонкретнаяДата;
       
НастройкаПериодаИсходный.ВариантОкончания = ВариантГраницыИнтервала.КонкретнаяДата;
       
НастройкаПериодаИсходный.ДатаНачала = ДатаНачала;
       
НастройкаПериодаИсходный.ДатаОкончания = ДатаОкончания;
    КонецЕсли;
КонецЕсли;

Как видно из кода, заплатка в качестве периода устанавливает ПроизвольныйПериод. Ах, да. Не видно. Но всё равно в качестве периода устанавливается ПроизвольныйПериод.

Я прекрасно понимаю, что здесь рассмотрен некоторый частный случай, который в типовых конфигурациях не встречается. Но. Есть ли что-то особенное в постановке задачи? По моему нет. Так почему же такой подход не используется в типовых конфигурациях? Не связано ли это с тем, что разработчики типовых конфигураций фирмы 1С не смогли победить объект НастройкаПериода. Smile

В качестве примера приведу "Универсальный отчет", в котором также есть как Основная форма, так и форма Настройки. При этом если изменить период в форме Настройки, он тут же изменяется и в Основной форме. Т.е. закрыв форму Настройки можно отказаться от всех сделанных изменений кроме изменений периода. Вот такие пироги.

Скачать пример...

Вернуться к оглавлению...


Про итоги в регистрах накопления

Пришло время испытать публикацию MMF на довольно большой базе данных. Обнаружился очень интересный факт. Таблица итогов по регистру остатков ЗаказыПокупателей была больше таблицы самого регистра в 50 раз и составляла 20% от всей базы УПП. Все попытки побороть это явление "цивилизованными" способами привели к уменьшению таблицы итогов лишь в 2.5 раза, при этом таблица самого регистра накопления выросла в 2 раза. Тогда было принято решение отключить расчет итогов по этому регистру. На производительности и функциональности это ни как не сказалось, а вот на размерах базы данных и на размерах архивных копий отразилось самым положительным образом.

Т.к. через интерфейс это сделать не получилось, то вот, собственно, код:

РегистрыНакопления.ЗаказыПокупателей.УстановитьПериодРассчитанныхИтогов('00010101');

С методической точки зрения, возможно, это не самое лучшее решение. Но меня поразила его эффективность и простота.

Скачать пример...

Для просмотра внутренней структуры файловой базы данных 1С:Предприятия 8 предлагаю обратить внимание на Tool_1CD.

Вернуться к оглавлению...


Про танцы с бубном

Пришло время разучить новый танец. Ни когда раньше такого не делал, но вот пришлось.

Что есть? Конфигурация на базе типового решения 1С:Бухгалтерия предприятия 8 (2.0.31.36) - Учет в МФО (релиз 2.0.31.36), разработчик Фирма "Альянс-Информ". База работает на платформе 8.2.13.219.

Что хотим? Перейти на платформу 8.2.15.294.

Казалось бы, что ничего сложного нет. Установить платформу, запустить базу, сконвертировать базу при запуске и работать в своё удовольствие. Но не тут то было. После конвертации база почему-то начинает падать при запуске на любой версии платформы, начиная с 8.2.14.519. При этом на 8.2.13.219 всё работало как в режиме Конфигуратор, так и в режиме 1С:Предприятие.

Восстанавливаем архив, лезем в конфигуратор и видим, что конфигурация на поддержке без возможности изменения, т.е. типовая. Нужно что-то делать. Но что? Тестирование/исправление, реструктуризация, выгрузка/загрузка - все ранее применявшиеся движения шаманского танца не помогли. После конвертации база падает при запуске.

Что дальше? Разучим новые движения незамысловатого шаманского танца. Начинаем сначала. Заходим в конфигуратор платформы 8.2.13.219 пустой базы. Восстанавливаем архив базы данных из DT-файла. Сохраняем конфигурацию в CF-файл в меню Конфигурация - Сохранить конфигурацию в файл. Включаем возможность изменения в меню Конфигурация - Поддержка - Настройка поддержки. Обновляем конфигурацию базы данных (F7) или в меню Конфигурация - Обновить конфигурацию базы данных. Выходим из конфигуратора. Заходим в конфигуратор платформы 8.2.15.294. Выбираем ту же базу. Соглашаемся с предложением сконвертировать базу данных. Загружаем выгруженный ранее CF-файл в меню Конфигурация - Загрузить конфигурацию из файла. Обновляем конфигурацию базы данных (F7) или в меню Конфигурация - Обновить конфигурацию базы данных. Вот собственно и всё. Получаем работающую базу под платформой 8.2.15.294 с типовой конфигурацией на поддержке без возможности изменения. Т.е. всё то, что и хотелось получить первоначально.

Вывод. В арсенале настоящего шамана может быть много разных танцев, но архивную копию делать нужно.

Вернуться к оглавлению...


Про использованные материалы

При подготовке статьи использованы также материалы других авторов. Если вам понравились их обработки, то можете поставить плюсик на их публикациях. Думаю, что они не будут против. Все ссылки есть в статье.

Вернуться к оглавлению...


Про Разукрашку

Для раскрашивания текстов модулей в статье была использована Разукрашка.
Пользуйтесь Разукрашкой для раскрашивания кода и запросов 1С:Предприятия, а также кода Delphi. Smile
Прошу воспринимать это не как рекламу, а как добрый совет для авторов других публикаций.

Вернуться к оглавлению...


Последний штрих

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

07.09.2010. Добавил в заметочки "Про получение строки пробелов длиной 10000 символов"

12.10.2010. Добавил в заметочки "Про работу с COMОбъект("V81.Application") или как разогнать 1С в 1000 раз

12.01.2011. Добавил в заметочки "Про СКД и запросы с итогами" и два примера реализации многоуровнего дерева значений в одной колонке с помошью СКД

03.08.2011. Добавил в заметочки "Про дерево значений"

29.08.2011. Добавил в заметочки "Про типы данных. Расчет сумм по выделенным ячейкам табличного поля". Обновил Пример3_2.epf. Теперь Гостинец.epf "отдыхает"

05.10.2011. Добавил в заметочки "Про типы данных. Динамическая настройка колонок табличного поля"

12.10.2011. Добавил в заметочки к разделу "Про циклы в одну строку" обработку для формарования программного кода в одну строку.

13.10.2011. Добавил в заметочки "Про итоги в регистрах накопления"

17.11.2011. Добавил про разбор длинных строк в массив с возможностью предварительной обработки данных. Обновил Пример 7.

19.01.2012. Добавил в заметочки "Про работу с НастройкаПериода, ЗаполнитьЗначенияСвойств и вообще"

31.01.2012. Добавил в заметочки "Про танцы с бубном"

09.03.2012. Добавил в заметочки "Про хитрые запросы. Тэта-соединения 3. Строки неограниченной длины"

23.03.2012. Добавил в заметочки "Про пакетные запросы. Индексы во временных таблицах"

22.06.2012. Добавил в заметочки "Про таблицу значений"

Вернуться к оглавлению...

 

01.06.2010 /Константинов Алексей Викторович/
Редакция от 22.06.2012

См. также

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

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

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

11.03.2024    4516    dsdred    53    

71

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

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

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

24.01.2024    5291    YA_418728146    25    

63

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

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

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

11.12.2023    6409    dsdred    36    

111

1С-ная магия

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

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

06.10.2023    18473    SeiOkami    46    

118

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

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

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

14.09.2023    12087    human_new    27    

74

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

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

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

28.08.2023    8820    YA_418728146    6    

141

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

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

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

20.08.2023    6279    sebekerga    54    

94

Все скопируем и вставим! (Буфер обмена в 1С 8.3.24)

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

Рассмотрим новую возможность 8.3.24 и как её можно эффективно использовать

27.06.2023    15986    SeiOkami    31    

103
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
78. пользователь 07.06.10 15:40
Сообщение было скрыто модератором.
...
79. пользователь 07.06.10 15:43
Сообщение было скрыто модератором.
...
80. пользователь 07.06.10 15:45
Сообщение было скрыто модератором.
...
81. пользователь 07.06.10 15:47
Сообщение было скрыто модератором.
...
83. пользователь 07.06.10 15:54
Сообщение было скрыто модератором.
...
84. пользователь 07.06.10 15:58
Сообщение было скрыто модератором.
...
86. пользователь 07.06.10 16:05
Сообщение было скрыто модератором.
...
87. пользователь 07.06.10 16:07
Сообщение было скрыто модератором.
...
88. пользователь 07.06.10 16:09
Сообщение было скрыто модератором.
...
91. пользователь 07.06.10 16:16
Сообщение было скрыто модератором.
...
93. пользователь 07.06.10 16:21
Сообщение было скрыто модератором.
...
97. пользователь 07.06.10 16:26
Сообщение было скрыто модератором.
...
94. пользователь 07.06.10 16:21
Сообщение было скрыто модератором.
...
96. пользователь 07.06.10 16:25
Сообщение было скрыто модератором.
...
89. пользователь 07.06.10 16:11
Сообщение было скрыто модератором.
...
86. пользователь 07.06.10 16:05
Сообщение было скрыто модератором.
...
77. пользователь 07.06.10 15:32
Сообщение было скрыто модератором.
...
74. пользователь 07.06.10 15:01
Сообщение было скрыто модератором.
...
75. пользователь 07.06.10 15:12
Сообщение было скрыто модератором.
...
90. пользователь 07.06.10 16:13
Сообщение было скрыто модератором.
...
92. пользователь 07.06.10 16:20
Сообщение было скрыто модератором.
...
95. пользователь 07.06.10 16:25
Сообщение было скрыто модератором.
...
98. пользователь 07.06.10 16:29
Сообщение было скрыто модератором.
...
99. пользователь 07.06.10 16:33
Сообщение было скрыто модератором.
...
100. пользователь 07.06.10 16:43
Сообщение было скрыто модератором.
...
102. Ish_2 1104 07.06.10 18:37 Сейчас в теме
И вот еще что .
Алексей , оно ,конечно, дело твоё - имеешь право скрывать чужие комментарии в своей теме. Но комментарии vip'a ты скрыл зря. У меня остался какой-то гаденький привкус.
103. Abadonna 3958 07.06.10 19:49 Сейчас в теме
(102) Закрыл Арчи. Так что к Алексею ты не по адресу ;)
Ежели честно: там был околотемный флад. Хотя и не такой уж фладистый ;)
Короче: стандартный спор упертых семерочников со мной широкообразованным ( :D ), начиная от 2.0 до 8.2 ;)
107. vip 08.06.10 05:56 Сейчас в теме
(102) Чтобы не оставалось привкуса, скопировал удаленные посты тебе в личку.
Как видишь, ничего особенного, кроме отхода от темы ветки, который поддержали кстати и ув. модераторы.
Приношу автору извинения.
А мысли мои по поводу 8.2 повторяются здесь http://infostart.ru/public/71438/?PAGEN_1=1#comm
110. Ish_2 1104 08.06.10 07:44 Сейчас в теме
108. Арчибальд 2706 08.06.10 07:39 Сейчас в теме
(102)(107) Реально, конечно, это был не совсем флуд, а один из аспектов темы 8. Но раз автор возразил (и обоснованно) - мои действия считаю правильными.
109. Ish_2 1104 08.06.10 07:42 Сейчас в теме
105. Ish_2 1104 07.06.10 22:17 Сейчас в теме
Алексею- пардон.
Арчибальду - Фи..
106. alexk-is 6533 08.06.10 00:01 Сейчас в теме
(105) Вот вариант, который показал наилучший результат в файловой версии для 8491 записей. Убрал все индексы. Этот вариант ещё меньше и работает правильно :)

Время выполнения Пример3_3.epf - ~ 1.7 сек
Прикрепленные файлы:
Пример3_3.epf
112. Ish_2 1104 08.06.10 07:50 Сейчас в теме
114. Ish_2 1104 08.06.10 08:08 Сейчас в теме
(106) Бегло всё-таки посмотрел.
Кроме последнего запроса - это Гостинец.epf.
Хм. Странно. За счет чего тогда ускорение в 8 раз (я проверил)?
Подскажи.
111. Арчибальд 2706 08.06.10 07:44 Сейчас в теме
(105) Радуйся, что в правилах ИС отсутствует прямой запрет на обсуждение действий модераторов :evil:
113. alexk-is 6533 08.06.10 07:51 Сейчас в теме
Народ, вы что, опять начинаете?
115. Ish_2 1104 08.06.10 08:26 Сейчас в теме
Не удержался- копнул.
Последний запрос ( чем отличается Пример3_3 от гостинца)- никакой прибавки к быстродействию не даёт.
Львиную долю времени (90%) занимает запрос соединения по неравенству.
Если из первого запроса "Гостинца" убрать строку "Индексировать по Период1,Период2"
то мы и получим быстродействие 1.5 сек.
В свою очередь , если мы добавим строку "Индексировать по Период1,Период2" в твой Пример 3_3 ,то получим те самые 11.7 сек (т.е. запрос из-за этой строки выполнился медленне в 8 раз ).
И честно говоря - это очень и очень странно.
Явное создание необходимого индекса многократно тормозит общий пакет запроса. Получается , что оптимизатор запроса лучше создает тот самый индекс.
117. artbear 1448 08.06.10 09:38 Сейчас в теме
(115) Ага, я сам в последнее время разочаровываюсь во временных таблицах 1С :(
Очень часто обычный запрос, без временных таблиц, реально быстрее, в несколько раз, чем запрос, построенный на ВТ
119. Ish_2 1104 08.06.10 10:50 Сейчас в теме
(117) Вопрос несколько в другом.
Явное использование во временной таблице Опции "Индексировать" (т.е. создание индекса) приводит в дальнейшем к очень серьезному замедлению при обращении к этой таблицы. Казалось бы , этого в принципе быть не должно.
122. alexk-is 6533 08.06.10 11:43 Сейчас в теме
(119) Возможно потеря времени не приобращении к ВТ, а при построении индекса?
424. daho 8 03.11.12 16:44 Сейчас в теме
(119) Ish_2, Это логично, но может еще от скул-сервака зависит. В Мелкософтовых всегда были проблемы с индексацией и высвобождением памяти от всякого старого мусора..
118. alexk-is 6533 08.06.10 10:48 Сейчас в теме
(115) В (106) я сразу написал, что убрал все индексы. Да, это "Гостинец", я уже писал об этом, но видимо где-то потерялось. Ещё раз: "Да, это Гостинец", только из первого запроса убрал лишнюю операцию с датами, объединил 6 и 7 пакет и исправил ошибку в первой записи.

Я выложил новые "Пример3" и "Пример3_2". На небольших объемам данных "Пример3" показывает изумительные результаты, а на больших объемах "Пример3_2" держит паритет с "Гостинец". :)

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

В таком случае, принудительная индексация имеет смысл только для таблиц без индексов, например, табличных частей документов или для таблиц значений.

Но это пока только догадки. Нужно тестировать.
120. alexk-is 6533 08.06.10 10:55 Сейчас в теме
(115) Даже так. :)

Время выполнения Гостинец.epf - ~ 1.7 сек
Время выполнения Пример3_2.epf - ~ 1.5 сек
116. Ish_2 1104 08.06.10 08:31 Сейчас в теме
И где Артур Artbear ? Он как-то меня убедил, что явное создание необходимых индексов для временной таблицы есть благо. Пусть ответит перед "доверчивыми людями" !
133. anig99 2843 08.06.10 15:58 Сейчас в теме
Спор на самом деле немного не спор...
У Гилева есть статьи на эту тему. Быстродействие запроса зависит от слишком многих факторов, т.к. 1с ПЕРЕВОДИТ свои запросы в запросы SQL. А что там дальше будет... Нужно препарировать выполнение запросов на каждой отдельной конфигурации ПО.
1с в этом случае даёт лишь рекомендации...не использовать соединение вложенных запросов, т.к. это может транслироваться в неоптимальный запрос.
cool.vlad4; +1 Ответить
134. axae 109 06.08.10 15:25 Сейчас в теме
Мне кажется надо исправить пример со сверткой массива:
НовыйМассив = Новый Массив; Соответствие = Новый Соответствие;
Для каждого ЭлементМассива Из Массив Цикл Соответствие.Вставить(ЭлементМассива) КонецЦикла;
Для каждого КлючИЗначение Из Соответствие Цикл НовыйМассив.Добавить(КлючИЗначение.Значение) КонецЦикла;

Кусок
Соответствие.Вставить(ЭлементМассива)
вставляет один лишь ключ, а значение-то останется Неопределено. Надо ведь
Соответствие.Вставить(ЭлементМассива, ЭлементМассива)
, либо
НовыйМассив.Добавить(КлючИЗначение.Ключ)
, так?
Поручик; alexk-is; +2 Ответить
135. alexk-is 6533 07.09.10 10:41 Сейчас в теме
Добавил про получение строки пробелов длиной 10000 символов.
136. Ish_2 1104 08.10.10 19:22 Сейчас в теме
Ты написал в другой теме , что увеличил быстродействие в 90раз для подключаемой базы
Я правильно понял ? И где у тебя в теме об этом ?
137. Ish_2 1104 08.10.10 19:33 Сейчас в теме
+136 Ты в заметочках столько написал - в глазах рябит.
Я про "ускорение в 90 раз"(!) хотел бы почитать отдельно. Хм... и пристрастно.
138. alexk-is 6533 10.10.10 20:06 Сейчас в теме
(137) Ничего нового, это второй прием http://www.infostart.ru/public/18924/ пример использования здесь http://www.infostart.ru/public/19021/
Ну, и конечно же, это работает как в 7.7, так и в 8.х

...или обязательно нужны ещё доказательства?
140. alexk-is 6533 12.10.10 07:14 Сейчас в теме
(137) Добавил в конце статьи про "ускорение в 100 раз" или 200. Как получится :)
Ну, и как обычно жду комментариев
139. пользователь 12.10.10 06:39
Сообщение было скрыто модератором.
...
141. Ish_2 1104 12.10.10 07:29 Сейчас в теме
А что комментировать ?
Скачал две обработки.
1. COM Monitor
2. Пример 6 для COM Monitor

Посмотрел последний п.2.
А почему модуль закрыт в п.1 ?
Можно подтвердить факт про разное быстродействие п.1 и п.2 .
Но как я проверю открытый тобой секрет :
ускорение за счет снижения количества разименований ?
142. alexk-is 6533 12.10.10 07:48 Сейчас в теме
(141)
А почему модуль закрыт в п.1 ?
Ну, это не ко мне, а к автору обработки. Ссылка на автора есть. Я выложил обработку "как есть", только добавил замер времени выполнения
Но как я проверю открытый тобой секрет
Разве это секрет? Вот здесь http://www.infostart.ru/public/18924/ про это написано почти 2 года назад
Можно подтвердить факт про разное быстродействие п.1 и п.2
Сколько получилось?
143. Ish_2 1104 12.10.10 16:53 Сейчас в теме
1. У автора закрытый код , вот я и хотел увидеть его секрет и в чём он.
2. Результаты тестирования .
Основная база файловая , подключаемая SQL.
Справчочник КОнтрагенты. 5230 объектов.
Время загрузки :
1. COM Monitor ------------------------- 132сек
2. Пример 6 для COM Monitor -------- 21 сек.
Если в п.2 применить дополнительную обработку (извращение по-моему)
то
2. Пример 6 для COM Monitor -------- 9 сек.

144. alexk-is 6533 14.10.10 07:07 Сейчас в теме
(143) В комментариях к своей публикации ghostishe писал, что может открыть код, если очень надо. Мне было не нужно, поэтому я не просил.
145. alexk-is 6533 14.10.10 15:02 Сейчас в теме
(143) Немного подправил Пример 6 для COM Monitor. Теперь работает ещё быстрее.

Почему вариант с обработкой "извращение"? Это позволяет сократить издержки на передаче данных.

Вообще-то, если бы данные собирались на постоянной основе, то для SQL версии лучше было бы использовать привелегированный общий модуль, чтобы вся обработка данных прошла на сервере, а клиент получил уже готовый результат. Тогда обработка данных прошла бы ещё быстрее.

Я тестировал всё на файловых базах и разница в результатах была гораздо значительнее.
146. Ish_2 1104 15.10.10 16:03 Сейчас в теме
(145) У меня перестали приходить сообщения на e-mail с инфостарта. IE8. Не знаешь в чем тут дело ?
Новый пример по тесту в (143) дал -------- 17.5 сек.
147. alexk-is 6533 15.10.10 17:29 Сейчас в теме
(146) Мне тоже не приходят. Возможно после переезда ещё не все сервисы запущены.

Мне вот что интересно: на чем выполнены твои тесты и почему столь существенная разница в результатах по сравнению с моими?

У меня базы файловые УПП 1.2.29.1, объем каждой базы 13 Гб, платформа 1С 8.1.15.14
ОС Widows XP Pro SP2
ПК CPU IntelCore2 Duo E6750 2.66GHz RAM 4 Гб HDD RAID 0 SATA 2x160 Гб
Тестировал справочник Номенклатура 22000 элементов
148. Ish_2 1104 15.10.10 20:02 Сейчас в теме
(147) В понедельник попробую и опишу другой опыт (на большем объеме)
149. Ish_2 1104 18.10.10 09:27 Сейчас в теме
Основная база БП 1.6 файловая (копия), Подключаемая база - SQL(основная).
Справочник ДоговорыКонтрагентов . Количество объектов 16 665шт.

1. COM Monitor ------------------------- 406сек
(в процессе загрузки интерактивно закрываю открывщееся окно 1сПредприятия SQL-базы)
2. Primer_6_ COM_ Monitor.epf -------- 90 сек.
(без дополнительной обработки)
150. Fragster 1138 20.10.10 11:18 Сейчас в теме
Вариант про строку в массив через ЗначениеИзСтрокиВнутр - работает медленнее, чем
Код
   мСтрока = Новый Массив;
   Если Не ТипЗнч(Строка) = Тип("Строка") Тогда Возврат мСтрока; КонецЕсли;
   Стр = СокрЛП(Строка);
   Если Стр="" Тогда Возврат мСтрока; КонецЕсли;
   
   Длина = СтрДлина(Разделитель);
   Пока Истина Цикл Поз = Найти(Стр,Разделитель); Если Поз = 0 Тогда мСтрока.Добавить(СокрЛП(Стр)); Прервать; КонецЕсли; Нашли = СокрЛП(Лев(Стр, Поз-1)); Если Не ПустаяСтрока(Нашли) Тогда мСтрока.Добавить(Нашли); КонецЕсли; Стр = СокрЛП(Сред(Стр,Поз+Длина)); КонецЦикла;
Показать полностью


у меня - прочти в 4 раза
molodoi1sneg; +1 Ответить
151. alexk-is 6533 21.10.10 15:44 Сейчас в теме
(150) Откуда такие данные? Как тестировали? Предлагаю посмотреть Пример 7

Вот мои результаты:
Длина тестовой строки: 608207
Количество строк тестовой строки: 12848
Код из комментария. Элементов в массиве: 10 106. Завершено за 9,812 сек.
Код из статьи. Элементов в массиве: 12 848. Завершено за 0,094 сек.
152. Fragster 1138 22.10.10 10:32 Сейчас в теме
(151) да, на длинный строках - пример из статьи лучше, на коротких - лучше цикл... Опытным путем подобрал - больше 1000 символов (там серийники по 24-32 символа через запятую) - используем ваш вариант, меньше - цикл. на моих данных - получилось оптимально
153. alexk-is 6533 22.10.10 13:30 Сейчас в теме
(152) А где доказательная база? Как проверяли результат?
310. alexk-is 6533 17.11.11 09:28 Сейчас в теме
(150) (302) Добавил про разбор длинных строк в массив с возможностью предварительной обработки данных.
Обновил Пример 7.
154. Ish_2 1104 29.12.10 19:34 Сейчас в теме
Слушай , хочу при выгрузке из запроса получить не двууровневое дерево , чтобы в одной колонке выдавалось
+Организации
-- Договоры

а, скажем , 4- уровневое дерево , чтобы при выгрузке из запроса в одной колонке дерева иметь :
+Контрагент
--Договор
---Номенклатура
----Характеристика

Делал такое ?
155. alexk-is 6533 29.12.10 20:49 Сейчас в теме
(154) Пытался, но не получилось. Посмотреть результат было бы очень интересно.
156. Ish_2 1104 29.12.10 21:10 Сейчас в теме
(155) Да вот сижу, дергаю - дай, думаю, спрошу. Если получится - сообщу.
157. Ish_2 1104 30.12.10 08:32 Сейчас в теме
Итак , выводим в одной колонке дерева все итоги при выгрузке из запроса.
См. демо пример.
Прикрепленные файлы:
158. alexk-is 6533 30.12.10 09:25 Сейчас в теме
(157) Прикольно. Видимо я чего-то в прошлый раз не докрутил. Всё получилось даже с разными типами данных.
159. KapasMordorov 428 30.12.10 10:23 Сейчас в теме
(157)
Может, я ошибаюсь, но
в исходном примере данные разных типов были в одной колонке,
а в новом примере иерерахия есть только в первой колонке и в ней же одно повторяющееся значение.
И колонок стало 4 против прежних 2. Под условия в 154 не подходит.
160. Ish_2 1104 30.12.10 10:31 Сейчас в теме
(159) В текущей теме автора приведен пример как в одной колонке вывести разнотиповые итоги в одной колонке.
и рассматривается ТОЛЬКО двухуровневое дерево после выгрузки из запроса :
+Организации
--Договоры

В (157) приведен пример как в одном запросе получить 4-уровневое дерево.
Для простоты и наглядности все колонки в (157) одного типа.
(157) говорит также о том , что можно в одной колонке выводить итоги и для дерева ЛЮБОГО уровня.

Как вывести разнотиповые итоги в одной колонке в теме автора раскрыто хорошо и понятно.
161. KapasMordorov 428 30.12.10 11:11 Сейчас в теме
(160)
Похоже, это уже неважно.
У меня пример автора не повторяется. Либо в дереве три колонки, либо при настройке колонок нет иерархии.
162. Ish_2 1104 30.12.10 11:18 Сейчас в теме
(161) Так у автора , в ДеревоЗначений выгружаются 3 колонки. Но так как ЭлементФормы имеет 2 колонки , то пользователю видны только эти две колонки !
Если после выгрузки из запроса сделать Дерево.СоздатьКолонки() , то пользователь увидит 3 колонки.
163. KapasMordorov 428 30.12.10 11:21 Сейчас в теме
(162)
В том и дело, если я делаю две колонки и не использую "СоздатьКолонки", то в дереве нет иерархии.
164. Ish_2 1104 30.12.10 11:23 Сейчас в теме
(163) Не понял. У первой колонки табличного поля в свойствах должен стоять флаг "Иерархия"
166. KapasMordorov 428 30.12.10 11:32 Сейчас в теме
(164)(165)
Ага, свойство "Иерархия" как раз и не стояло.
Теперь всё понятно стало. (157) полностью решает задачу.
167. Ish_2 1104 30.12.10 11:37 Сейчас в теме
(166) А вообще , мне кажется перспективным выводить некоторые отчеты с группировками не в табличный документ , а в 3-4 уровневое дерево в табличном поле.
Удобнее для корректировок, быстрее, с пересчетом итогов по группировкам и т.д.
Доп. Функционал накручивается на дерево проще , чем на табличный документ.
169. ILM 240 30.12.10 22:50 Сейчас в теме
(167) А если добавить поле сумма для подсчета итогов, то как получится сделать: Дерево + итоги по группировкам?
171. alexk-is 6533 04.01.11 15:52 Сейчас в теме
(169) Пример расчета итогов можно посмотреть здесь http://infostart.ru/public/69707/
170. alexk-is 6533 31.12.10 07:24 Сейчас в теме
(166) Как хорошо, что сами разобрались. Хотя во вложении есть работающий "Пример 2", который собирает результат в одну колонку из двух.
(168) Да.
(169) Легко. Итоги расчитываются в итогах.
165. Ish_2 1104 30.12.10 11:26 Сейчас в теме
(163) А вот пусть автор и расскажет нам ,
как он получил свой пример с 2-уровневым деревом.
Таскаю , понимаешь, каштаны..
168. ILM 240 30.12.10 22:33 Сейчас в теме
(157) Вот как раз такую задачу решал, но не смог решить. Теперь ход мыслей понятен куда копать. Но более подробный пример такого запроса, очень помог бы мне.
А дерево из ААА->БББ->ВВВ->ГГГ выведется в поле 4?
172. ILM 240 04.01.11 19:16 Сейчас в теме
Алексей, я видел, это двухуровневое дерево. А вот если у меня количество вложенности дерева 10 и строится по паре полей, предок, родитель. То так просто не получается.
Код1 Код2
1
2 1
3 1
4 2
5 4
6 3

1->
+->2->4->5
+->3->6

Вот такое только вручную.
173. alexk-is 6533 04.01.11 19:28 Сейчас в теме
(172) Можно взглянуть на текст запроса разворачивающий этот список в дерево?
174. ILM 240 05.01.11 14:40 Сейчас в теме
(173) Как-то такой пакетик ))

ВЫБРАТЬ 1 КАК Код1, NULL КАК Код2
ПОМЕСТИТЬ ТМП_ИСХ
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 2 КАК Код1, 1 КАК Код2
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 3 КАК Код1, 1 КАК Код2
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 4 КАК Код1, 2 КАК Код2
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 5 КАК Код1, 2 КАК Код2
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 6 КАК Код1, 3 КАК Код2
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ 7 КАК Код1, 6 КАК Код2
;
ВЫБРАТЬ Т0.Код1 КАК Код0, Т1.Код1 КАК Код1, Т2.Код1 КАК Код2, Т3.Код1 КАК Код3
ПОМЕСТИТЬ ТТТ
ИЗ ТМП_ИСХ КАК Т0
ЛЕВОЕ СОЕДИНЕНИЕ ТМП_ИСХ КАК Т1
ПО Т0.Код1 = Т1.Код2
ЛЕВОЕ СОЕДИНЕНИЕ ТМП_ИСХ КАК Т2
ПО Т1.Код1 = Т2.Код2
ЛЕВОЕ СОЕДИНЕНИЕ ТМП_ИСХ КАК Т3
ПО Т2.Код1 = Т3.Код2
ГДЕ Т0.Код2 ЕСТЬ NULL
;
ВЫБРАТЬ
ВЫБОР
Когда Код1 Есть NULL Тогда Код0
Когда Код2 Есть NULL Тогда Код1
Когда Код3 Есть NULL Тогда Код2
Иначе Код3
КОНЕЦ КАК Код33,
Код0, Код1, Код2, Код3
ИЗ ТТТ
ИТОГИ
ВЫБОР
Когда Код1 Есть NULL Тогда Код0
Когда Код2 Есть NULL Тогда Код1
Когда Код3 Есть NULL Тогда Код2
Иначе Код3
КОНЕЦ КАК Код33
ПО Код0, Код1, Код2, Код3 АВТОУПОРЯДОЧИВАНИЕ
;


Еще бы дубли строк убрать и вообще красота
175. CheBurator 3119 05.01.11 14:50 Сейчас в теме
(174) это какое-то умножение сдвигом на разряд.. ;-)
176. ILM 240 05.01.11 15:27 Сейчас в теме
(175) А что делать? Есть другие предложения? :D
177. alexk-is 6533 05.01.11 15:46 Сейчас в теме
(174) Это не дубли строк. Это пустые уровни итогов.
178. ILM 240 05.01.11 15:50 Сейчас в теме
(177) Хочу убрать пустые дубли итогов)
Мне только структура нужна, только дерево и чтобы заканчивалось на нужном уровне без пустых строк итогов.
Сильно хочу, однако )))
179. ILM 240 05.01.11 15:52 Сейчас в теме
А то выводится структура изделия, а в ней куча дублей.
180. alexk-is 6533 05.01.11 17:03 Сейчас в теме
(179) Как мне кажется, здесь нужно смотреть в другую сторону.
http://infostart.ru/public/78285/
http://infostart.ru/public/78371/
181. ILM 240 05.01.11 20:49 Сейчас в теме
(180) Видел оба. Из первого и взял запрос, а второе вообще не в тему. Думаю Игорь подтянется и подскажет.
182. Ish_2 1104 05.01.11 21:51 Сейчас в теме
(181) Подтянулся. Посмотрел и запустил запрос (174). Давай так . Правильно ли я тебя понял :
Дано : Граф описан с помощью таблицы "Граф" с колонками Сын,Родитель (Код1,Код2).
Априорно известен уровень графа =4 (такое редко встечается, но пусть)
Нужно : получить в виде дерева на форме изображение графа .
Замечание : быстродействие неважно - Таблица "Граф" очень небольшая(до 100 строк).
Если количество узлов в графе более 100 000 и уровень 5-10 , тогда такое построение запроса неприменимо.

Так ?

Результат твоего запроса (174) изображен на рисунке. Ты бы хотел избавиться от плвторений выделенных красным цветом ?
Так ?
Прикрепленные файлы:
183. Ish_2 1104 05.01.11 23:18 Сейчас в теме
(181)Завтра уеду.
Поэтому см. прикрепленную обработку с твоим и моим вариантом запроса.
Прикрепленные файлы:
СравнениеТвоёМоё.epf
184. ILM 240 06.01.11 09:04 Сейчас в теме
(183) Спасибо, Игорь. В твоём варианте тоже получаются пустые строки. Наверное от них не избавится никак.
Как я понял существуют всего три варианта получить дерево:
1) Формировать программно через код,
2) запросом через итоги,
3) Как иерархический справочник.

В СКД, тоже получаются пустые строки.
186. Ish_2 1104 06.01.11 21:30 Сейчас в теме
(184) От пустых строк в табличном поле избавится очень просто, используя обработчик ПриВыводеСтроки() , в котором свойство "Видимость" для ячеек с пустыми значениями устанавливается в "Ложь". Другими словами , такие ячейки просто не видны. См . рисунок.
В теме "Запрос против рекурсии.." применен именно такой приём и дерево ошибок выводится без пустых строк.
Минус же построения дерева из запроса с итогами - один : чрезвычайно низкое быстродействие.

(185) Вообще говоря, возможны варианты ,и варианты ,и варианты...
Но как только возникает условие : НУЖЕН абсолютный контроль зацикливания - то вариант только один.
Кхе..Кхе..
Я извиняюсь.В чужой теме я задудел в свою любимую дуделку.
Прикрепленные файлы:
185. ILM 240 06.01.11 09:28 Сейчас в теме
(183) Это всё равно лучше, чем было.
Про граф и уровень его, можно сказать, что максимальный уровень графа равен 4-м, это для примера. Ничто не мешает сделать вложенность и 10 ... 20. По поводу быстродействия нужно проверять.
Ведь запрос не обязательно делать для одной таблицы с данными графа и связывать её саму с собой.
Как вариант можно сформировать последовательные отрезки с наборами графа с увеличением уровня вложености (0-1, 1-2, 2-3, 3-4 ... 19-20 и так далее), а потом все отрезки объединить в один набор, и уже по нему пройтись запросом с итогами.
Хотя скорее всего вариант рекурсии с подзапросами будет выигрывать по скорости.
Не знаю существует ли другой вариант сформировать дерево структуры запросами. Очень, очень жаль что в 1С нет рекурсивных запросов.
Оставьте свое сообщение