Произвольный отбор при открытии формы любого динамического списка




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

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

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

<?php // Полная загрузка сервисных книжек, создан 2026-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='\

29 Comments

  1. slawa

    Для чего Схему помещать во временное хранилище?

    Reply ↓
  2. starik-2005

    (1) в принципе тут схема вообще не нужна — можно создать объект настроек компоновки данных. А помещение в хранилище — дань традициям.

    Reply ↓
  3. nomadon

    без помещения интерактивно не работают доступные поля, мож и тут что то не работает

    Reply ↓
  4. starik-2005

    (3) тут все работает, но компоновка тут нужна лишь для получения фиксированных настроек, т.е. фактически весь этот код можно заменить на «ФиксНастройки = Новый НастройкиКомпоновкиДанных».

    Reply ↓
  5. Yashazz

    Ваще чего-то совсем баян. Из серии «как вывести пользователю сообщение». С чего вдруг столько плюсов?..

    Автор, насчёт производительности что-нибудь известно? Или это вариант только для простых списков по основной таблице?

    Reply ↓
  6. starik-2005

    (5) все зависит от того, что открывает пользователь. Если первый вариант отбора позволяет на «Равно» и «ВСписке» отбирать, то второй фактически определяет любой отбор, доступный пользователю в настройке списка, только при этом пользователь не видит отбор из фиксированных настроек. Производительность определяется полями отбора, которые уже будут влиять на план запроса в СУБД. Если по индексированному полю отбор происходит — производительность будет высокая, а если по какому-то ПОДОБНО в реквизите табличной части, то все зависит от размера таблицы. Я как-то руками группировку попытался сделать по весьма небольшому справочнику — пятнадцать минут ждал, пока программа что-то вернет.

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

    ЗЫ: Ты до сих пор не знаешь, за что на Инфостарте плюсуют? Могу как-нибудь рассказать…

    Reply ↓
  7. zqzq

    (4) Так и надо всю эту воду из статьи убрать и оставить нужное

    
    ФиксНастройки = Новый НастройкиКомпоновкиДанных;
    
    ФиксНастройки.ПараметрыДанных.Элементы.Добавить().Параметр = Новый ПараметрКомпоновкиДанных(«Период»);
    ФиксНастройки.ПараметрыДанных.УстановитьЗначениеПараметра(«Период», ПППП);
    
    УправлениеНебольшойФирмойКлиент.УстановитьЭлементОтбораСписка(ФиксНастройки, «Склад», СССС);
    
    

    Показать

    Reply ↓
  8. Новиков

    (4)

    но компоновка тут нужна лишь для получения фиксированных настроек, т.е. фактически весь этот код можно заменить на «ФиксНастройки = Новый НастройкиКомпоновкиДанных».

    Может быть для потомков покажете вторую редакцию готового кода, с замененными фрагментами? Может как-то бы и в статье это отразить?

    И не понятно, если при всех одинаковых вводных, можно написать меньше когда, то почему не воспользоваться данной возможностью? 🙂

    Reply ↓
  9. mitia.mackarevich

    Забавно, а что будет автор если пользовательские настройки будут идти в наложении(Например сохраненные) или пользователь захочет потом сам настроить дин. список? вывалиться ошибка, наложение икс и пользовательских настроек недопустимо.Тогда имеет смыл запретить редактирование настроек при открытии динамического списка.

    За труды все равно плюсану.

    Reply ↓
  10. starik-2005

    (8) если потомки не смогут сделать это самостоятельно, то за державу станет обидно )))

    Reply ↓
  11. starik-2005

    (7) ну некоторым интересно полностью поглядеть ))

    Reply ↓
  12. starik-2005

    (9) так можно всегда гипотезу попытаться подтвердить или опровергнуть экспериментом!

    Reply ↓
  13. Новиков

    (10) Так вы для кого статью то писали, для себя или для других? Если для себя — вопросов нет. Если для других, вы зачем-то предложили длинный путь при наличии короткого. Дальше эту статью очевидно будут находить поисковиком и просто копи-пастить, меняя название документа и табличной части на свое. И расползется ваша портянища по многим и многим конфам. Я уверен, даже до комментов основная масса не дойдет, зная что решение — работает.

    Дополните статью коротким вариантом, типа «но код можно подсократить, и я покажу как».

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

    Спасибо.

    Reply ↓
  14. starik-2005

    (13) как в одном анекдоте про обезьян, прапорщиков, палку и бананы: «что тут думать — прыгать надо!» Отсюда мораль: не стоит упрощать то, что недоступно для понимания масс, чтобы оное оставалось в элитарном сегменте.

    Reply ↓
  15. palsergeich

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

    Почему не использовать пользовательские настройки с доступностью — недоступный?

    Reply ↓
  16. palsergeich

    Что то типо такого.

    ПараметрыФормы = Новый Структура(«ПользовательскиеНастройки», ПользовательскиеНастройки);

    ПараметрыФормы.Вставить(«СформироватьПриОткрытии» , Истина);

    Форма = ОткрытьФорму(«Отчет.XXXXX.Форма.ФормаОтчета», ПараметрыФормы, ПараметрыВыполненияКоманды.Источник, ПараметрыВыполненияКоманды.Источник.УникальныйИдентификатор, ПараметрыВыполненияКоманды.Окно);

    Reply ↓
  17. starik-2005

    (16) это для отчетов. В расширении формы динамического нет параметра «ПользовательскиеНастройки». Или есть? Для расширения формы компоновщика настроек есть.

    Reply ↓
  18. alexei366

    В СП можно ввести «Расширение управляемой формы для динамического списка» и там будут и ФиксированныеНастройки и ПользовательскиеНастройки и КлючПользовательскихНастроек. Так что можно поиграться.

    Reply ↓
  19. starik-2005

    (18) у меня в СП так, пользовательские настройки есть — круто!

    Reply ↓
  20. alexei366

    (19)Ну славо богу, хоть СП сопали)))

    Reply ↓
  21. starik-2005

    (20) с пользовательскими настройками то плохо, что пользователь их может отрубить. При этом фиксированные он срубить не сможет. С другой стороны, пользователь всегда прав — и если так, то можно и пользовательские настройки передавать.

    Reply ↓
  22. alexei366

    (21) Надо тестить, ты же их передавать будешь, они может будут замещать пользовательские, плюк ключ пользовательских настроек можно передать какойнить специфический.

    Reply ↓
  23. Pawlick
    1С не работает с соответствием

    С какого числа?

    Проверил: Платформа 1С:Предприятие 8.3 (8.3.8.1784)

    Соответствие = Новый Соответствие;

    Работает!!!

    …Фух… Перепугался даже

    Reply ↓
  24. starik-2005

    (23) это если выдирать из контекста, то работает, а если с контекстом — нет )))

    Reply ↓
  25. Makushimo

    Спасибо!

    Reply ↓
  26. SlavaKron

    (15)(18)(19)

    Так что там с параметром формы ПользовательскиеНастройки? Получилось у кого-нибудь через него установить отбор?

    Reply ↓
  27. starik-2005

    (27) попробуй — узнаешь!

    Reply ↓
  28. SlavaKron

    (28) У меня не получилось, потому и спрашиваю.

    Reply ↓
  29. SlavaKron

    Получилось, хоть и не без шаманства. Оказывается, идентификатор пользовательских отборов для любого динамического списка при создании формы всегда один и тот же: «dfcece9d-5077-440b-b6b3-45a5cb4538eb».

    Может, кому-нибудь пригодится:

    &НаКлиенте
    Процедура Реквизит1НачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    
    ПользовательскиеНастройки = Новый ПользовательскиеНастройкиКомпоновкиДанных;
    
    ИдентификаторПользовательскойНастройки = «dfcece9d-5077-440b-b6b3-45a5cb4538eb»;
    
    Отбор = ПользовательскиеНастройки.Элементы.Добавить(Тип(«ОтборКомпоновкиДанных»));
    Отбор.ИдентификаторПользовательскойНастройки = ИдентификаторПользовательскойНастройки;
    Отбор.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Авто;
    
    ЭлементОтбора = Отбор.Элементы.Добавить(Тип(«ЭлементОтбораКомпоновкиДанных»));
    ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(«Наименование»);
    ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Содержит;
    ЭлементОтбора.ПравоеЗначение = «Вода»;
    ЭлементОтбора.Использование = Истина;
    ЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.БыстрыйДоступ;
    ЭлементОтбора.ИдентификаторПользовательскойНастройки = Новый УникальныйИдентификатор;
    
    ПараметрыФормы = Новый Структура(«ПользовательскиеНастройки», ПользовательскиеНастройки);
    
    ОткрытьФорму(«ВнешняяОбработка.ВнешняяОбработка1.Форма.Форма1», ПараметрыФормы, Элемент);
    КонецПроцедуры

    Показать

    Reply ↓

Leave a Comment

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