Визуализация и интерактивное изменение дерева значений.




Принцип обмена данными из 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='\

25 Comments

  1. Belkin_Sergey

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

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

    Reply
  2. Belkin_Sergey

    (1) нормальный такой, «как оно связывается с объектами 1С» — никак не связывается, просто парсится html

    Reply
  3. нормальный такой

    Прикольно

    А как оно работает? здесь уже видел несколько разработок «интерактивных» отчетов, тоже с использованием js, но я таки не очень понял как оно связывается с объектами 1С.

    Как в данном случае вы говорите, что можно потыкать html отображение этого дерева и оно перестроится в списке.

    Reply
  4. Belkin_Sergey

    (5) chmv, все зависит от вашей фантазии 🙂

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

    Reply
  5. chmv

    Интересно. Но где это можно применить на практике?

    Reply
  6. help1Ckr

    Спасибо огромное! Будем проверять. К сожалению слабо знаком с html но давно хотелось что то такое. ВОт как раз мучаюсь с графическими схемами. Но на html больше возможностей

    Reply
  7. нормальный такой

    (2) о, спасибочки за ответ 🙂 будем в курсе.

    Мне почему-то тоже сразу пришла в голову идея с деревом штатного расписания в ЗУПе 🙂

    Reply
  8. Belkin_Sergey

    (9) mip128, Вставьте в общий модуль ОбщегоНазначения функцию

    // Преобразует шестнадцатиричное число в десятичное
    //
    // Параметры:
    // Источник — строка с шестнадцатиричным числом
    //
    // Возвращаемое значение:
    // Число — десятичное число
    //
    Функция ШестнадцатиричноеВДесятичное(Источник) Экспорт
    
    Результат = 0;
    
    Для Поз = 1 По СтрДлина(Источник) Цикл
    ТекКод = КодСимвола(Источник, Поз);
    
    Если ТекКод >= КодСимвола(«0») И ТекКод <= КодСимвола(«9») Тогда
    ТекКод = ТекКод — КодСимвола(«0»);
    ИначеЕсли ТекКод >= КодСимвола(«a») И ТекКод <= КодСимвола(«f») Тогда
    ТекКод = ТекКод +10 — КодСимвола(«a»);
    ИначеЕсли ТекКод >= КодСимвола(«A») И ТекКод <= КодСимвола(«F») Тогда
    ТекКод = ТекКод +10 — КодСимвола(«A»);
    КонецЕсли;
    
    Результат = Результат * 16 + ТекКод;
    
    КонецЦикла;
    
    Возврат Результат;
    
    КонецФункции // ШестнадцатиричноеВДесятичное()

    Показать

    Если в нем нет функции ДесятичноеВШестнадцатиричное(), то вставьте ее тоже.

    // Преобразует десятичное число в шестнадцатиричное
    //
    // Параметры:
    // Источник — число (десятичное) от 0 до 255
    //
    // Возвращаемое значение:
    // Строка — десятичное число
    //
    Функция ДесятичноеВШестнадцатиричное(Источник) Экспорт
    
    ШестнадцатиричныеСимволы = «0123456789ABCDEF»;
    
    Если Источник < 0 Тогда
    Возврат «00»;
    КонецЕсли;
    Если Источник > 255 Тогда
    Возврат «FF»;
    КонецЕсли;
    
    ПервыйСимвол = Цел(Источник / 16) + 1;
    ВторойСимвол = Источник % 16;
    
    Возврат Сред(ШестнадцатиричныеСимволы, ПервыйСимвол, 1) + Сред(ШестнадцатиричныеСимволы, ВторойСимвол, 1);
    
    КонецФункции // ДесятичноеВШестнадцатиричное()

    Показать

    Вообще эти процедуры в типовых должны быть.

    Reply
  9. Belkin_Sergey

    (9) mip128, перенес эти процедуры из общего модуля в модуль объекта обработки (для тех, кто собирается качать). Вышлите мне в личку свой e-mail, я вам отправлю обновленную версию.

    Reply
  10. alyaev.a.v

    Забавная штука.почему 1с не встроит в платформу уже средства визуализации.

    Reply
  11. Гость

    (10) представьте что у пользователя вообще пустая конфигурация…

    или тогда описывайте релиз, платформу и версию ОС…

    А еще настройки ОС что бы JS отрабатывал… а то если пользователь запустит эту ерунду на терминале с ограниченными групповыми политиками, то он как бы пойдет куда по дальше…

    Reply
  12. RainyAugust22

    Классно!!! +

    Reply
  13. BigB

    (10) так по моему проще

    Функция ШестнадцатиричноеВДесятичное(Hex) Экспорт
    Стр=ВРег(СокрЛП(Hex));
    Dec=0;
    ДлинаСтр=СтрДлина(Стр);
    Для Х=1 По ДлинаСтр Цикл
    Dec=Dec+Найти(«123456789ABCDEF»,Сред(Стр,Х,1))*Pow(16,СтрДлина(Стр)-Х)
    КонецЦикла;
    Возврат Dec
    КонецФункции

    Показать

    Reply
  14. Belkin_Sergey

    (14) BigB, гораздо.

    Какую в типовой нашел, такую и использовал 🙂

    Reply
  15. logarifm

    Где применить пока даже не знаю, но вот за идею и за труд ставлю плюс. Это можно где-то как фичу применить для красоты.

    Reply
  16. Belkin_Sergey

    (17) gubanoff,

    Там важно создать дерево значений, где будет только 1 главная строка, которая будет родителем для всех остальных строк.

    Если вы пытаетесь визуализировать справочник, то предлагаю первой строкой ввести название справочника.

    т.е. надо сделать так:

    -Номенклатура

    —Материалы

    ——Товары

    —Готовая продукция

    Reply
  17. gubanoff

    Подскажите пример, как красиво вывести справочник с иерархией элементов? У меня задваивает элементы — они и на вышестоящих уровнях и на нижестоящих.

    Reply
  18. gubanoff

    (17) gubanoff, Сделал такой вариант для иерархии элементов:

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

    Показать

    Reply
  19. gubanoff

    На базе с большим числом подразделений выдает ошибку «На этой странице произошла ошибка сценария»

    Reply
  20. JohnyDeath

    А оно может отрабатывать правый клик и даблклик на конкретном блоке?

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

    1) работает и в тонком клиенте

    2) отрабатывает «ОбработкаРасшифровки» и «ОбработкаДополнительнойРасшифровки»

    Reply
  21. graphbuh

    Однозначный плюс! Было бы интересно увидеть развитию этой идеи для результата запроса.

    Reply
  22. npilatov

    А дерево можно применить к документам на пример заказ на производство в унф

    Reply
  23. stash_84

    нет ли варианта обрабатывающего дерево, как и писали выше, формируемое из запроса?

    Reply
  24. ls300

    Автор, я воодушевился твоей идеей и сделал аналогичный отчет. Дерево выводится по блокам, но столкнулся с проблемой что поле HTML документа выводит дерево дважды при выполнении метода «УстановитьТекст(ТекстHTMLдокумента)». Подскажи, пожалуйста, как решил эту проблему?

    Reply
  25. chingiz001

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

    Reply

Leave a Comment

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