Пример преобразования дерева значений в таблицу значений и обратно в 1Cv8




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

68 Comments

  1. Поручик

    Программный код не хотите разукрасить?

    http://infostart.ru/public/19856/

    Reply
  2. Sintson

    (1) Спасибо за наводку, разукрасил 🙂

    Reply
  3. Арчибальд

    Меня бы больше порадовал алгоритм представления дерева в виде таблицы значений в «чистом виде», без привязки к восьмерке. Ну, хоть так…

    Reply
  4. Yashazz

    А ещё такие фишки можно проделывать, используя построитель или СКД. Иной раз гибче выходит, хотя с оформлением источника данных, конечно, морока.

    Reply
  5. Sintson

    (3) Если Вы поясните, что имеется в виду под «чистым видом», можно подумать, хотя рекурсия — она и в Африке рекурсия 🙂 .

    (4) Абсолютно согласен, можно и ПостроительОтчетов использовать.

    Reply
  6. Арчибальд

    (5) Дерево и таблица существуют независимо от восьмерочной платформы. Соответственно и алгоритм представления дерева таблицей не имеет отношения к восьмерочной платформе. Т.е. задача, решенная в публикации, сильно заужена, является очень частным случаем.

    Это не в укор, а мечтательно.

    Reply
  7. venger

    (6)

    Это не в укор, а мечтательно

    Присоединяюсь, даешь универсальный алгоритм;-)

    Reply
  8. Sintson

    (6)(7) Вызов принимается, как прикажете оформить?

    Reply
  9. Sergey K

    (0) Задача тривиальная.. добавить КлючСтроки и КлючСвязи (я использую даже точно такие же наименования — совпадение?)

    Но данная реализация — достаточно медленная..

    можно обойтись без использования метода «Найти», «СортироватьПоЗначению» — очень замедляет весь процесс

    но, всеравно поставлю + 🙂

    Reply
  10. Арчибальд

    (8) Лучше всего (наглядней и прозрачней) — в виде комикса.

    Reply
  11. venger

    (10) Это как? В виде алгоритма — знаю, в виде комикса — это как?;-)

    Reply
  12. Sintson

    (9) Реверанс

    Reply
  13. Sintson

    (9) Реверанс

    (10) Я пас, алгоритмы в виде комикса для меня слишком 😎

    Reply
  14. venger

    (10) (13) Вот, спугнули;-) Хорошо хоть не в виде мульта;-)

    Reply
  15. Sintson

    (9) может поделитесь реализацией? Хотелось бы взглянуть так сказать в метадле…

    Reply
  16. Sergey K

    Пример выгрузка Таблицы в Дерево..

    1. в твой код необходимо вставить:

    Таблица.Сортировать(«КлючСтроки»);

    т.к. если в таблице строки не будут упорядочены по КлючуСтроки, то у тебя дерево построится неправильно

    2. СтрокаГруппировки = Дерево.Строки.Найти(СтрокаТаблицы[КлючСвязи], КлючСтроки,Истина);

    достаточно медленая, тем более ты ищешь по всем уровням дерева..

    мой вариант:

    числоЭлементов = Таблица.Количество();

    Если числоЭлементов = 0 Тогда

    Возврат;

    КонецЕсли;

    МассивСтрок = Новый Массив(Таблица[числоЭлементов-1][«КлючСтроки»]);

    Для каждого Строка Из Таблица Цикл

    Если Строка.КлючСвязи = 0 Тогда

    МассивСтрок.Вставить(КлючСтроки,Дерево.Строки.Добавить());

    Иначе

    МассивСтрок.Вставить(КлючСтроки,МассивСтрок[Строка.КлючСвязи.Строки.Добавить());

    КонецЕсли;

    ЗаполнитьЗначенияСвойств(МассивСтрок[«КлючСтроки»], Строка);

    Reply
  17. Sintson

    (16) С первым согласен, однако если таблицу мы получаем из дерева — она так и так будет отсортирована. В моем случае в качестве таблицы выступала табличная часть документа для хранения данных.

    Со вторым полностью согласен, достойный вариант построения.

    Reply
  18. Asdam

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

    Reply
  19. Asdam

    (9) Sergey K, выложите, плиз, Ваш пример реализации преобразования дерева значений в таблицу значений и обратно.

    Reply
  20. Sintson

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

    (16) Проблем с построением ни разу за все время не было, во всяком случае если применять так как в конфигурации с примером 😉 .

    Reply
  21. kisyalort

    Спасибо большое! 🙂

    Reply
  22. Sintson

    (21) Пожалуйста, заходите еще 😉

    Reply
  23. vitaliy.ermolenko

    а как заставить заработать сабж в 1С: Предприятие 8.2 (управляемое приложение)?

    Reply
  24. 1malder1

    Может у кого есть пример вывода дерева в печатную форму(в виде дерева), нужно сделать для обычной и управляемой формы

    Reply
  25. Sintson

    (23) В 1С: Предприятие 8.2, как вариант рекомендую создать реквизит с типом хранилище значения и восстанавливать перед открытием и сохранять при закрытии формы.

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

    Reply
  26. Sintson

    (24) Вывод в печатную форму из дерева значений осуществляется с использованием рекурсии.

    Можно также запихнуть его в СКД, используя как внешние данные.

    Reply
  27. Kotta

    Спасибо, очень пригодилось.

    Reply
  28. adhocprog

    Большое спасибо!

    Картинка тоже порадовала! 🙂

    Reply
  29. Sintson

    (28) Ценю чувство юмора, спасибо!

    Reply
  30. takeshi3

    Спасибо!Поставил плюсик!

    Reply
  31. EfremoVich

    Вот бы ещё получилось бы скачать конфу для изучения.. ;(

    Reply
  32. orefkov

    (11)

    Для универсального алгоритма достаточно ключи назвать id и parentid 🙂

    Reply
  33. tindir

    Отличное подспорье для новичков. Сидел и печально придумывал хитрые рекурсии на листочке, пока не наткнулся на ваш пример. Кстати, по поводу оптимизации на сколько пример с массивами будет работать быстрее. вопрос не пустой, мне в дерево надо будет перегонять таблицу с количеством строк от 10 до 6000 ( ух и огромная организационная структура у этой организации 🙂 )

    Reply
  34. tindir

    (16) Sergey K, пока не разорался как ваш кусок кода работает. и думаю стоит ли (в целях самообразованя -да, а вот в целях разработки..). на сколько он будет эффективнее, чем поиск с «найти» и «сортировать» ? (дерево будет строиться минимум из 10-15 элементов, максимум 6000.

    Reply
  35. Sintson

    (34) Спасибо за комментарий, однако, задачка у Вас!

    А может, пока на берегу, пересмотрите подходы к реализации?

    Дерево это конечно интересно, но 6000 элементов!!!

    Не лучше ли попробовать использовать динамические списки?

    А то, опираясь на личный опыт, с такими объемами легко словить «ошибку памяти по адресу»

    или «неизвестную ошибку компоненты C++»
    , а то и банальное «недостаточно памяти»…

    Reply
  36. Sergey K

    (34) Чем больше элементов в дереве, тем в разы быстрее будет работать вариант в (16)

    С вариантом в (16) выводил деревья в сотни тыс. строк.

    Reply
  37. tindir

    (35) да. после прочтения вашего комментария начал смотреть в сторону дим.спискоков, но пришел начальник, настучал по головушке, без того опухшей, за неправильное соединение таблиц и теперь работаем с таблице в максимум 100 строк. Производительность посмотрел. Да чем больше объем, тем более явно выражается производительность (16).

    Кстати, нет ли возможности напрямую передать через ком-соединение дерево? Т.к. первоначально стоит задача сделать дерево с возможность множественного выбора как в примере. Но есть одна беда — Ком-соединение.

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

    По этому и вопрос — есть ли варианты напрямую передавать дерево (может не в явном, но с меньшим количество шагов) ?

    Reply
  38. Sergey K

    (37)ЗначениеВСтрокуВнутр()

    Reply
  39. tindir

    (38) Sergey K, XML!!! ДА! как раньше сам до этого не додумался! Спасибо!

    Reply
  40. stalker18

    Хочу предложить свою реализацию перевода таблицы в дерево значений:

    Функция тз_в_дз(тз_Ссылка, дз_Ссылка, КлючСвязи=0)

    м_Строки=тз_Ссылка.НайтиСтроки(Новый Структура(«КлючСвязи», КлючСвязи));

    Для Каждого ъ_Строка Из м_Строки Цикл

    ъ_Строка_ДЗ=дз_Ссылка.Строки.Добавить();

    ЗаполнитьЗначенияСвойств(ъ_Строка_ДЗ, ъ_Строка);

    тз_в_дз(тз_Ссылка, ъ_Строка_ДЗ, ъ_Строка_ДЗ.КлючСтроки);

    КонецЦикла;

    КонецФункции

    Предварительно в таблице необходимо добавить индекс для ускорения поиска строк:

    тз_Ссылка.Индексы.Добавить(«КлючСвязи»);

    Вызов:

    тз_в_дз(тз_Источник, дз_Приемник);

    Reply
  41. UJF

    Конфа пустая

    Reply
  42. UJF

    конфа нормальная

    Reply
  43. Sintson

    (42) в контексте публикации, предлагаю ознакомиться с рабочей конфигурацией, где этот модуль является центральным для визуализации http://infostart.ru/public/205664/

    Reply
  44. yandextesting

    похожее решение — http://infostart.ru/public/281131/

    Reply
  45. KroVladS

    (0) Ещё бы найти пример как в ТЧ загнать справочник номенклатуры с иерархией из запроса.

    Reply
  46. ChelyapinDemlink

    (29) а подскажите, что передавать в качестве КлючСвязи?

    Функция ВыгрузитьТаблицуЗначенийВДеревоЗначений(Таблица, КлючСтроки = «КлючСтроки», КлючСвязи = «КлючСвязи»)

    Reply
  47. Sintson

    (46) Это название реквизита, близкий по смыслу к аналогу «родитель» в иерархическом справочнике.

    Reply
  48. SvetaS2014

    не открывается -«Невосстановимая ошибка

    Ошибка при выполнении запроса GET к ресурсу /e1cib/userSettings:

    по причине:

    Ошибка SDBL:

    В схеме базы данных нет таблицы с именем SystemSettings (pos=20)»

    Reply
  49. Sintson

    (48) Возможно требуется конвертация, конфигурация по-моему 8.1.

    Reply
  50. SvetaS2014

    конфигуратор пишет «Невосстановимая ошибка» и вылетает…. Как её открыть??

    Reply
  51. SvetaS2014

    чем её конвертировать? конфигуратор вылетает…

    Reply
  52. Alister

    Попробуйте не 8.3.9, а 8.3.8 или сначала 8.2, а потом уже 8.3

    Reply
  53. Sintson

    (51) Коллега Alister прав. Конфигурация рабочая, у меня в 8.3.8 не конвертится напрямую из 8.1. Найдите платформу 8.2. или 8.1. и я думаю все получится.

    Reply
  54. Alister

    (53) в 8.2 у него получилось

    Reply
  55. Tanis

    Добрый вечер!

    Подскажите, пожалуйста, как и в какой последовательности обращаться к функциям/процедурам, для преобразования дерева значений в таблицу значений?

    Сейчас поставил первое обращение к ПолучитьНовыйКлючСтрокиДерева(Дерево, СписокКлючей = Неопределено) Экспорт , а в ответ ошибка. У моего дерева нет ключа строки….

    Reply
  56. Sintson

    (55) Добрый вечер!

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

    А вообще этот реквизит необходим, добавьте в дерево эту колонку.

    Reply
  57. Tanis

    Добрый день!

    Спасибо! За совет. Правда, не написал сразу, и еще не пробовал добавить поле. Но у меня дерево виртуальное, там этот Ключ строки поставить в цикле — «н + 1» ? Или как-то по другому алгоритму? Что родитель — 1, а подчиненные 2….н, дерево двухуровневое.

    Спасибо!

    Reply
  58. Sintson

    1. Добавьте в своем дереве колонки «КлючСтроки» и «КлючСвязи»

    2. Запустите последовательно процедуры:

    ОбновитьКлючиСтрокВДеревеЗначений(ВашеДерево)

    ОбновитьКлючиСвязиВДеревеЗначений(ВашеДерево)

    3. ВашеДерево готово для дальнейшей работы по теме

    Reply
  59. Pavean

    А что изменено в обновлении 17.08.2017?

    Reply
  60. azamatjon98

    интересно стало

    Reply
  61. Bee2014

    Киньте работающий пример, s`il vous plat !! второй день бьюсь — что за КлючСвязи и КлючСтроки??

    Reply
  62. МихаилМ

    (61) метод преобразования дз в тз.

    //——————————————————————————————————————————
    //!!! в нетленку
    Функция ОтобратьМассивВсехСтрокДЗ(ДЗ,МассивТекСтрокДЗ) Экспорт
    Перем Рез;
    Перем ИмяКолонкиОтбора;
    Перем Отбор;
    ИмяКолонкиОтбора = УникальноеИмяКолонки();
    
    Попытка
    
    ДЗ.Колонки.Добавить(ИмяКолонкиОтбора,Новый ОписаниеТипов(«Булево»));
    Отбор = Новый Структура();
    Отбор.Вставить(ИмяКолонкиОтбора,FALSE);
    МассивТекСтрокДЗ = ДЗ.Строки.НайтиСтроки(Отбор,TRUE);
    ДЗ.Колонки.Удалить(ИмяКолонкиОтбора);
    Рез = TRUE;
    Исключение
    Рез = FALSE;
    Конецпопытки;
    
    
    Возврат Рез;
    
    КонецФункции //ОтобратьМассивВсехСтрокТЗ
    
    
    //——————————————————————————————————————————
    Функция СтруктураТЗвДЗ(ТЗ,ДЗ) Экспорт
    Перем Рез;
    Перем ТекущаяКолока;
    Для Каждого ТекущаяКолока Из  ТЗ.Колонки Цикл
    ДЗ.Колонки.Добавить(ТекущаяКолока.Имя,ТекущаяКолока.ТипЗначения);
    КонецЦикла;
    Возврат ИСТИНА
    КонецФункции //СтруктураТЗвДЗ
    //——————————————————————————————————————————
    
    Функция СтрокиДЗ_вТЗ(ДЗ,ТЗ)
    Перем рез;
    Перем СтрокиДЗ;
    Перем ПустаяСтрокаТЗ;
    Перем БуФТЗ;
    
    
    ОтобратьМассивВсехСтрокДЗ(ДЗ,СтрокиДЗ);
    ТЗ = Новый ТаблицаЗначений;
    СтруктураТЗвДЗ(ДЗ,ТЗ); // и наоброт работает как тз в дз  , так и дз в тз
    
    // теперь имитируем   СтрокиДЗ в масив строк ТЗ
    // путем вставки в массив первой строки из тз
    БуФТЗ = ТЗ.СкопироватьКолонки();
    
    ПустаяСтрокаТЗ = БуФТЗ.Добавить();
    СтрокиДЗ.Вставить(0, ПустаяСтрокаТЗ);
    
    ТЗ = БуФТЗ.Скопировать(СтрокиДЗ);
    
    // удаляем добавленную пустую строку
    ТЗ.Удалить(0);
    
    
    
    Рез = true;
    
    Возврат рез;
    
    
    КонецФункции //СтрокиДЗ_вТЗ
    
    

    Показать

    Reply
  63. Sintson

    (61) Что именно не работает? В чём выражается ошибка?

    КлючСтроки — это ключ строки, КлючСвязи хранит ключ строки родителя. По этим колонкам строится структура делева.

    Reply
  64. Team leader

    (62) не взлетит, не все функции указали:

    ИмяКолонкиОтбора = <<?>>УникальноеИмяКолонки(); (Проверка: Толстый клиент (обычное приложение))

    Reply
  65. Team leader

    (62) Эта схема лучше зашла:

    //—————————————————————————————
    // 1. Дерево значений в таблицу значений
    
    &НаСервере
    Процедура ВТЗНаСервере()
    тДерево = РеквизитФормыВЗначение(«Дерево»);
    тТаблица = РеквизитФормыВЗначение(«Таблица»);
    
    ПреобразоватьВТЗРекурсия(тДерево, тТаблица, Новый УникальныйИдентификатор(«00000000-0000-0000-0000-000000000000»));
    тДерево.Строки.Очистить();
    
    ЗначениеВРеквизитФормы(тТаблица, «Таблица»);
    ЗначениеВРеквизитФормы(тДерево, «Дерево»);
    КонецПроцедуры
    
    &НаСервере
    Процедура ПреобразоватьВТЗРекурсия(тДерево, тТаблица, ГУИД)
    Для Каждого тСтр Из тДерево.Строки Цикл
    нСтр = тТаблица.Добавить();
    нСтр.Колонка1 = тСтр.Колонка1;
    нСтр.Колонка2 = тСтр.Колонка2;
    нСтр.Родитель = ГУИД;
    нСтр.ГУИД = Новый УникальныйИдентификатор();
    
    Если тСтр.Строки.Количество()>0 Тогда
    ПреобразоватьВТЗРекурсия(тСтр, тТаблица, нСтр.ГУИД);
    КонецЕсли;
    КонецЦикла;
    КонецПроцедуры
    
    //—————————————————————————————
    // 2. Таблица значений в дерево значений
    
    &НаСервере
    Процедура ВДЗНаСервере()
    тДерево = РеквизитФормыВЗначение(«Дерево»);
    тТаблица = РеквизитФормыВЗначение(«Таблица»);
    
    ПреобразоватьВДЗРекурсия(тДерево, тТаблица, Новый УникальныйИдентификатор(«00000000-0000-0000-0000-000000000000»));
    тТаблица.Очистить();
    
    ЗначениеВРеквизитФормы(тТаблица, «Таблица»);
    ЗначениеВРеквизитФормы(тДерево, «Дерево»);
    КонецПроцедуры
    
    &НаСервере
    Процедура ПреобразоватьВДЗРекурсия(тДерево, тТаблица, ГУИД)
    тПоиск = Новый Структура(«Родитель», ГУИД);
    тМассив = тТаблица.НайтиСтроки(тПоиск);
    Для Каждого тСтр Из тМассив Цикл
    нСтр = тДерево.Строки.Добавить();
    нСтр.Колонка1 = тСтр.Колонка1;
    нСтр.Колонка2 = тСтр.Колонка2;
    
    ПреобразоватьВДЗРекурсия(нСтр, тТаблица, тСтр.ГУИД);
    КонецЦикла;
    КонецПроцедуры

    Показать

    Для обычных форм функции тоже будут работать

    (пример для сохранения дерева из 2х колонок)

    Reply
  66. SmArtist

    (16)

    мой вариант:

    можете показать полный вариант своей рекурсивной процедуры? спасибо

    Reply
  67. Cyberhawk

    del

    Reply
  68. Cyberhawk

    Приведенный в статье метод нельзя считать унивесальным, поскольку он применим только если соблюдается условие: ключ родителя всегда «больше» ключа любых его потомков. Ну и необходимо упорядочить исходную таблицу по возрастанию значений поля ключа, как об этом уже заметили в комментарии № 16.

    Простой пример иерархии, когда метод не работает:

    — код = 111, родитель пустой

    — код = 11, родитель = 111

    — код = 1, родитель = 11

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *