<?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='\
Программный код не хотите разукрасить?
http://infostart.ru/public/19856/
(1) Спасибо за наводку, разукрасил 🙂
Меня бы больше порадовал алгоритм представления дерева в виде таблицы значений в «чистом виде», без привязки к восьмерке. Ну, хоть так…
А ещё такие фишки можно проделывать, используя построитель или СКД. Иной раз гибче выходит, хотя с оформлением источника данных, конечно, морока.
(3) Если Вы поясните, что имеется в виду под «чистым видом», можно подумать, хотя рекурсия — она и в Африке рекурсия 🙂 .
(4) Абсолютно согласен, можно и ПостроительОтчетов использовать.
(5) Дерево и таблица существуют независимо от восьмерочной платформы. Соответственно и алгоритм представления дерева таблицей не имеет отношения к восьмерочной платформе. Т.е. задача, решенная в публикации, сильно заужена, является очень частным случаем.
Это не в укор, а мечтательно.
(6)
Присоединяюсь, даешь универсальный алгоритм;-)
(6)(7) Вызов принимается, как прикажете оформить?
(0) Задача тривиальная.. добавить КлючСтроки и КлючСвязи (я использую даже точно такие же наименования — совпадение?)
Но данная реализация — достаточно медленная..
можно обойтись без использования метода «Найти», «СортироватьПоЗначению» — очень замедляет весь процесс
но, всеравно поставлю + 🙂
(8) Лучше всего (наглядней и прозрачней) — в виде комикса.
(10) Это как? В виде алгоритма — знаю, в виде комикса — это как?;-)
(9) Реверанс
(9) Реверанс
(10) Я пас, алгоритмы в виде комикса для меня слишком 😎
(10) (13) Вот, спугнули;-) Хорошо хоть не в виде мульта;-)
(9) может поделитесь реализацией? Хотелось бы взглянуть так сказать в метадле…
Пример выгрузка Таблицы в Дерево..
1. в твой код необходимо вставить:
Таблица.Сортировать(«КлючСтроки»);
т.к. если в таблице строки не будут упорядочены по КлючуСтроки, то у тебя дерево построится неправильно
2. СтрокаГруппировки = Дерево.Строки.Найти(СтрокаТаблицы[КлючСвязи], КлючСтроки,Истина);
достаточно медленая, тем более ты ищешь по всем уровням дерева..
мой вариант:
числоЭлементов = Таблица.Количество();
Если числоЭлементов = 0 Тогда
Возврат;
КонецЕсли;
МассивСтрок = Новый Массив(Таблица[числоЭлементов-1][«КлючСтроки»]);
Для каждого Строка Из Таблица Цикл
Если Строка.КлючСвязи = 0 Тогда
МассивСтрок.Вставить(КлючСтроки,Дерево.Строки.Добавить());
Иначе
МассивСтрок.Вставить(КлючСтроки,МассивСтрок[Строка.КлючСвязи.Строки.Добавить());
КонецЕсли;
ЗаполнитьЗначенияСвойств(МассивСтрок[«КлючСтроки»], Строка);
(16) С первым согласен, однако если таблицу мы получаем из дерева — она так и так будет отсортирована. В моем случае в качестве таблицы выступала табличная часть документа для хранения данных.
Со вторым полностью согласен, достойный вариант построения.
Sintson, выложите, плиз, файл конфигурации с примером документа для чайников.
(9) Sergey K, выложите, плиз, Ваш пример реализации преобразования дерева значений в таблицу значений и обратно.
(18) Выложил простой пример использования процедур для табличной части документа.
(16) Проблем с построением ни разу за все время не было, во всяком случае если применять так как в конфигурации с примером 😉 .
Спасибо большое! 🙂
(21) Пожалуйста, заходите еще 😉
а как заставить заработать сабж в 1С: Предприятие 8.2 (управляемое приложение)?
Может у кого есть пример вывода дерева в печатную форму(в виде дерева), нужно сделать для обычной и управляемой формы
(23) В 1С: Предприятие 8.2, как вариант рекомендую создать реквизит с типом хранилище значения и восстанавливать перед открытием и сохранять при закрытии формы.
Чтобы заставить работать мои процедуры — их нужно просто немного переписать, учитывая специфику управляемого приложения.
(24) Вывод в печатную форму из дерева значений осуществляется с использованием рекурсии.
Можно также запихнуть его в СКД, используя как внешние данные.
Спасибо, очень пригодилось.
Большое спасибо!
Картинка тоже порадовала! 🙂
(28) Ценю чувство юмора, спасибо!
Спасибо!Поставил плюсик!
Вот бы ещё получилось бы скачать конфу для изучения.. ;(
(11)
Для универсального алгоритма достаточно ключи назвать id и parentid 🙂
Отличное подспорье для новичков. Сидел и печально придумывал хитрые рекурсии на листочке, пока не наткнулся на ваш пример. Кстати, по поводу оптимизации на сколько пример с массивами будет работать быстрее. вопрос не пустой, мне в дерево надо будет перегонять таблицу с количеством строк от 10 до 6000 ( ух и огромная организационная структура у этой организации 🙂 )
(16) Sergey K, пока не разорался как ваш кусок кода работает. и думаю стоит ли (в целях самообразованя -да, а вот в целях разработки..). на сколько он будет эффективнее, чем поиск с «найти» и «сортировать» ? (дерево будет строиться минимум из 10-15 элементов, максимум 6000.
(34) Спасибо за комментарий, однако, задачка у Вас!
А может, пока на берегу, пересмотрите подходы к реализации?
Дерево это конечно интересно, но 6000 элементов!!!
Не лучше ли попробовать использовать динамические списки?
А то, опираясь на личный опыт, с такими объемами легко словить «ошибку памяти по адресу»
или «неизвестную ошибку компоненты C++», а то и банальное «недостаточно памяти»…
(34) Чем больше элементов в дереве, тем в разы быстрее будет работать вариант в (16)
С вариантом в (16) выводил деревья в сотни тыс. строк.
(35) да. после прочтения вашего комментария начал смотреть в сторону дим.спискоков, но пришел начальник, настучал по головушке, без того опухшей, за неправильное соединение таблиц и теперь работаем с таблице в максимум 100 строк. Производительность посмотрел. Да чем больше объем, тем более явно выражается производительность (16).
Кстати, нет ли возможности напрямую передать через ком-соединение дерево? Т.к. первоначально стоит задача сделать дерево с возможность множественного выбора как впримере . Но есть одна беда — Ком-соединение.
Сейчас я делаю как : получаю Ком-таблицу вида (Ключ|КлючРодитель|Наименование), преобразую своей процедурой в Тз и прогоняю через вашу функцию. Получив дерево, отправляю его уже «разделанную» под мои нужды обработку из примера выше и получаю результат. Вся эта абра-кадабра очень медленная и порой дерево строится не верно.
По этому и вопрос — есть ли варианты напрямую передавать дерево (может не в явном, но с меньшим количество шагов) ?
(37)ЗначениеВСтрокуВнутр()
(38) Sergey K, XML!!! ДА! как раньше сам до этого не додумался! Спасибо!
Хочу предложить свою реализацию перевода таблицы в дерево значений:
Функция тз_в_дз(тз_Ссылка, дз_Ссылка, КлючСвязи=0)
м_Строки=тз_Ссылка.НайтиСтроки(Новый Структура(«КлючСвязи», КлючСвязи));
Для Каждого ъ_Строка Из м_Строки Цикл
ъ_Строка_ДЗ=дз_Ссылка.Строки.Добавить();
ЗаполнитьЗначенияСвойств(ъ_Строка_ДЗ, ъ_Строка);
тз_в_дз(тз_Ссылка, ъ_Строка_ДЗ, ъ_Строка_ДЗ.КлючСтроки);
КонецЦикла;
КонецФункции
Предварительно в таблице необходимо добавить индекс для ускорения поиска строк:
тз_Ссылка.Индексы.Добавить(«КлючСвязи»);
Вызов:
тз_в_дз(тз_Источник, дз_Приемник);
Конфа пустая
конфа нормальная
(42) в контексте публикации, предлагаю ознакомиться с рабочей конфигурацией, где этот модуль является центральным для визуализацииhttp://infostart.ru/public/205664/
похожее решение —http://infostart.ru/public/281131/
(0) Ещё бы найти пример как в ТЧ загнать справочник номенклатуры с иерархией из запроса.
(29) а подскажите, что передавать в качестве КлючСвязи?
Функция ВыгрузитьТаблицуЗначенийВДеревоЗначений(Таблица, КлючСтроки = «КлючСтроки», КлючСвязи = «КлючСвязи»)
(46) Это название реквизита, близкий по смыслу к аналогу «родитель» в иерархическом справочнике.
не открывается -«Невосстановимая ошибка
Ошибка при выполнении запроса GET к ресурсу /e1cib/userSettings:
по причине:
Ошибка SDBL:
В схеме базы данных нет таблицы с именем SystemSettings (pos=20)»
(48) Возможно требуется конвертация, конфигурация по-моему 8.1.
конфигуратор пишет «Невосстановимая ошибка» и вылетает…. Как её открыть??
чем её конвертировать? конфигуратор вылетает…
Попробуйте не 8.3.9, а 8.3.8 или сначала 8.2, а потом уже 8.3
(51) Коллега Alister прав. Конфигурация рабочая, у меня в 8.3.8 не конвертится напрямую из 8.1. Найдите платформу 8.2. или 8.1. и я думаю все получится.
(53) в 8.2 у него получилось
Добрый вечер!
Подскажите, пожалуйста, как и в какой последовательности обращаться к функциям/процедурам, для преобразования дерева значений в таблицу значений?
Сейчас поставил первое обращение к ПолучитьНовыйКлючСтрокиДерева(Дерево, СписокКлючей = Неопределено) Экспорт , а в ответ ошибка. У моего дерева нет ключа строки….
(55) Добрый вечер!
Я бы посоветовал Вам скачать демо конфигурацию, там пример использования.
А вообще этот реквизит необходим, добавьте в дерево эту колонку.
Добрый день!
Спасибо! За совет. Правда, не написал сразу, и еще не пробовал добавить поле. Но у меня дерево виртуальное, там этот Ключ строки поставить в цикле — «н + 1» ? Или как-то по другому алгоритму? Что родитель — 1, а подчиненные 2….н, дерево двухуровневое.
Спасибо!
1. Добавьте в своем дереве колонки «КлючСтроки» и «КлючСвязи»
2. Запустите последовательно процедуры:
ОбновитьКлючиСтрокВДеревеЗначений(ВашеДерево)
ОбновитьКлючиСвязиВДеревеЗначений(ВашеДерево)
3. ВашеДерево готово для дальнейшей работы по теме
А что изменено в обновлении 17.08.2017?
интересно стало
Киньте работающий пример, s`il vous plat !! второй день бьюсь — что за КлючСвязи и КлючСтроки??
(61) метод преобразования дз в тз.
Показать
(61) Что именно не работает? В чём выражается ошибка?
КлючСтроки — это ключ строки, КлючСвязи хранит ключ строки родителя. По этим колонкам строится структура делева.
(62) не взлетит, не все функции указали:
ИмяКолонкиОтбора = <<?>>УникальноеИмяКолонки(); (Проверка: Толстый клиент (обычное приложение))
(62) Эта схема лучше зашла:
Показать
Для обычных форм функции тоже будут работать
(пример для сохранения дерева из 2х колонок)
(16)
можете показать полный вариант своей рекурсивной процедуры? спасибо
del
Приведенный в статье метод нельзя считать унивесальным, поскольку он применим только если соблюдается условие: ключ родителя всегда «больше» ключа любых его потомков. Ну и необходимо упорядочить исходную таблицу по возрастанию значений поля ключа, как об этом уже заметили в комментарии № 16.
Простой пример иерархии, когда метод не работает:
— код = 111, родитель пустой
— код = 11, родитель = 111
— код = 1, родитель = 11