Получение массива имен реквизитов обычной формы и имя ее основного реквизита




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

47 Comments

  1. German

    Браво …

    Reply
  2. German

    У Брикса вся фишка в том что он не мог на основе двоичных данных(текстовых) получить форму.

    Код
    СтрокаФормы = ЗначениеВСтрокуВнутр(Форма);
    Форма=ЗначениеИзСтрокиВнутр(СтрокаФормы ); //ошибка 

    Показать полностью

    Потому и затеял эти дела. Форму теперь можно получить из двоичных данных (Как это сделать можно будет посмотреть в новой версии Ei ). Ну а когда есть форма.

    Код
    Для каждого Элемент из Форма.Элементы.Формы Цикл
    Сообщить(Элемент.Имя);
    КонецЦикла; 

    Показать полностью

    Reply
  3. tormozit

    Боюсь, я не смогу получить двоичные данные формы в общем случае. Поэтому данный способ — единственный.

    Reply
  4. tormozit

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

    Reply
  5. coder1cv8

    Высший класс!!! +100 от меня!

    Reply
  6. coder1cv8

    +(5) Про основной реквизит тоже очень интересно посмотреть.

    Reply
  7. tormozit

    (6) Готово. Реквизиты формы покорены… )

    Reply
  8. Sol

    А в этой части не напутано?

    > //{ Заменяем символы, критичные для XML

    >// & на &

    ………

    Вроде в http://infostart.ru/profile/16971/blogs/344/ в (11) было правильно:

    > //{ Заменяем символы, критичные для XML

    >// & на &

    ………

    Reply
  9. tormozit

    (8) Это движок форума постарался 😉

    Reply
  10. tormozit

    Теперь стало некрасиво, зато правильно) Не знаю как в новом форуме оформить код… =(

    Reply
  11. Sol

    А я не пойму даже, как комментарии упорядочить, чтобы как раньше — новые были сверху.

    Reply
  12. tormozit

    (12) Согласен. Последние сверху — очень рульно было.

    Reply
  13. tormozit

    (8) Люди, помогите с проблемой отображения злых символов (&)!

    Reply
  14. larisab

    Не могли бы вы еще раз привести функцию ЛксСтрокаВнутрВХМЛТело в виде кода, а не текста, без лишних , видимо убирая их, что то оставила или удалила лишнюю. Дает ошибку в XMLСтрокаФормы.

    Reply
  15. larisab

    Сделала, в итоге применения этого метода (0) параметр: КакойТоОбъект.ПолучитьФорму(«ФормаЭлемента»)), возращает строку «СправочникОбъект», а не массив реквизитов формы и ее основной реквизит.

    Reply
  16. tormozit

    (15) Вставил как есть. Теперь отображается вроде нормально.

    Reply
  17. larisab

    (16) А насчет «возращает строку «СправочникОбъект», а не массив реквизитов формы и ее основной реквизит.»

    Как получить элементы формы?

    Reply
  18. tormozit

    (17) Вопрос не ясен. Прошу сформулировать четко, что ты хочешь получить. Функции проверены на практике. Они возвращают именно то, что заявлено.

    Reply
  19. larisab

    ФормаОбъекта = ГрафикОбъект.ПолучитьФорму(«ФормаЭлемента»);

    ПолученнаяФорма = ЛксПолучитьИмяОсновногоРеквизитаФормы(ФормаОбъекта);

    Хочу в текст кнопки Месяц вставить:

    ТекущаяКнопка = Формат(ДатаМесяца, «ДФ=»»ММММ гггг»»»);

    ПолученнаяФорма.КоманднаяПанельКалендаря.Кнопки.Месяц.Текст = ТекущаяКнопка;

    Reply
  20. larisab

    +19 ГрафикОбъект это уже полученный СправочникОбъект ГрафикиРаботы в ЗУПе.

    Reply
  21. vladnet

    +1 Искал давно как то как получить имя основного реквизита формы, жаль тогда не нашел )

    Reply
  22. vladnet

    В 8.2 не работает ни получение списка реквизитов, ни получение основного реквизита. 🙁

    Reply
  23. tormozit

    (22) Теперь работает и в 8.2. Единственное — не стал делать получение версии платформы из системной информации в нужном формате. Т.е. нужно в функцию версию платформы передавать в виде строки «81» или «82»

    Reply
  24. vladnet

    (23) Спасибо )

    Reply
  25. Akela_Crimea

    Я так понял, что с управляемыми формами эта фича не работает?

    Или это я глючу?

    Reply
  26. tormozit

    (25) Да. Управляемые формы не поддерживаются.

    Reply
  27. mt171

    tormozit, спасибо за разработку!

    Только у меня (8.2.12.80 + ЗУП 2.5.27.6) выдаёт ошибку:

    Ошибка при вызове метода контекста (Прочитать): Ошибка разбора XML: — [1,1]

    Фатальная ошибка:

    Document is empty

    ДокументDOM = ПостроительDOM.Прочитать(ЧтениеXML);

    по причине:

    Ошибка разбора XML: — [1,1]

    Фатальная ошибка:

    Document is empty

    В чём может быть причина? Вызываю из модуля формы при открытии, в качестве параметра ЭтаФорма,»82″. Сама строка XMLСтрокаФормы заполнена

    Reply
  28. Sergey K

    Кто-нибудь приведите пример, для чего м.б. использован данный функционал? когда требуется программное определения реквизитов формы?

    Reply
  29. HIgor

    Вещь полезная. Для неуправляемых форм видимо единственное решение. Но давайте здесь тоже не кастрированную функцию ЛксСтрокаВнутрВХМЛТело запишем :

    Функция ЛксСтрокаВнутрВХМЛТело(вхСтрока, выхХМЛТело = Неопределено) Экспорт
    
    //{ Получение одной длинной строки
    выхХМЛТело = СтрЗаменить(вхСтрока,СИМВОЛЫ.ПС,»»);
    выхХМЛТело = СтрЗаменить(выхХМЛТело,СИМВОЛЫ.ВК,»»);
    //}
    
    //{ Заменяем символы, критичные для XML
    // & на «&»
    // < на «<»
    // > на «>»
    выхХМЛТело = СтрЗаменить(выхХМЛТело,»&»,»&»);
    выхХМЛТело = СтрЗаменить(выхХМЛТело,»<«,»<«);
    выхХМЛТело = СтрЗаменить(выхХМЛТело,»>»,»>»);
    
    //{ Замена одинарных символов
    выхХМЛТело = СтрЗаменить(выхХМЛТело,»,»,»</data><data>»);
    выхХМЛТело = СтрЗаменить(выхХМЛТело,»{«,»<elem><data>»);
    выхХМЛТело = СтрЗаменить(выхХМЛТело,»}»,»</data></elem>»);
    //}
    
    //{ Удаляем лишние блоки и
    выхХМЛТело = СтрЗаменить(выхХМЛТело,»<data><elem>»,»<elem>»);
    выхХМЛТело = СтрЗаменить(выхХМЛТело,»</elem></data>»,»</elem>»);
    //}
    
    //{ Добавляем перенос строки к и к для удобства поиска различий
    выхХМЛТело = СтрЗаменить(выхХМЛТело,»</elem>»,»</elem>»+СИМВОЛЫ.ПС);
    выхХМЛТело = СтрЗаменить(выхХМЛТело,»</data>»,»</data>»+СИМВОЛЫ.ПС);
    //}
    
    Возврат выхХМЛТело;
    
    КонецФункции
    

    Показать

    Reply
  30. tormozit

    (29) Спасибо. Поправил.

    Reply
  31. fomix

    Присодиняюсь к [28]

    Кто-нибудь приведите пример, для чего м.б. использован данный функционал? когда требуется программное определения реквизитов формы???????????????????????????????????????????

    Reply
  32. AlexO

    Тоже не понял — а зачем этот массив получать? ну там деструктивный анализ формы — еще куда ни шло (хотя как его применяют в статьях — сомнительная цель).

    Но какое практическое применение данного массива реквизитов?

    Reply
  33. tormozit

    Например это полезно в команде «Отладить источник» в подсистеме ИР, которая открывает консоль кода и передает в нее грубо говоря форму. Контекстная подсказка подсказывает реквизиты формы.

    Reply
  34. frc

    (33)

    а что на входе? некая XML-выгрузка?

    Reply
  35. frc

    (34) frc,

    а, вроде разобрался — на входе Форма, превращается СтрокаВнутр, потом эта строка разбирается по кускам и перегружается в формат XML-DOM для анализа…

    А что такое «делайте кэширование DOM»?

    Reply
  36. tormozit

    (34) На входе чего? На входе команды всегда ключ записи или ссылка.

    Reply
  37. frc

    (36)

    На входе чего?

    на входе в функцию «ЛксПолучитьМассивИменРеквизитовФормы»

    На входе команды всегда ключ записи или ссылка.

    т.е. ссылка на ФормаОбъект?

    Reply
  38. tormozit

    (37) Под командой я подразумевал одноименный объект управляемого приложения. Но теперь я вижу что вопрос был про другое.

    Reply
  39. frc

    (38)

    На тот вопрос вы и не ответили 🙂

    Вот ошибка так и возникает:

    в

    ДокументDOM = ПостроительDOM.Прочитать(ЧтениеXML);

    {ОбщийМодуль.эрФункцииОбщегоНазначения.Модуль(354)}: Ошибка при вызове метода контекста (Прочитать)

    по причине:

    {ОбщийМодуль.эрФункцииОбщегоНазначения.Модуль(354)}: Ошибка при вызове метода контекста (Прочитать)

    по причине:

    Ошибка разбора XML: — [1,1]

    Фатальная ошибка:

    Document is empty

    Reply
  40. frc

    Могу форму в XML (переменная ЧтениеXML) дать.

    Reply
  41. frc

    В общем, значит так и нельзя получить никаких реквизитов таким методом…

    Reply
  42. frc

    (27) mt171,

    ну да, видимо, с 2010 года так ничего и не изменилось по 8.2 — так не работает получение реквизитов.

    Reply
  43. tormozit

    Правильный вывод следует сразу же после прочтения названия публикации — «Получение массива имен реквизитов ОБЫЧНОЙ формы и имя ее основного реквизита». Все, кто пробуют метод за рамками описанной области применимости, получают не ожидаемый результат.

    Reply
  44. sergant500

    Если метод выдает ошибку, то заменяем строки в посте №29 (HIgor)

    выхХМЛТело = СтрЗаменить(выхХМЛТело,»&»,»&»);
    выхХМЛТело = СтрЗаменить(выхХМЛТело,»<«,»<«);
    выхХМЛТело = СтрЗаменить(выхХМЛТело,»>»,»>»);

    на

    выхХМЛТело = СтрЗаменить(выхХМЛТело,»&»,»&»);
    выхХМЛТело = СтрЗаменить(выхХМЛТело,»<«,»<«);
    выхХМЛТело = СтрЗаменить(выхХМЛТело,»>»,»>»);
    

    Спасибо за наводку Сергею Чуяну (Собеседник) http://infostart.ru/public/20069/

    вызов функции

    Процедура ДополнительныеДействияСФормой(ФормаОбъекта) Экспорт
    ИмяОсновногоРеквизита = ЛксПолучитьИмяОсновногоРеквизитаФормы(ФормаОбъекта);
    ОсновнойРеквизит = ФормаОбъекта[ИмяОсновногоРеквизита];
    Если ТипЗнч(ОсновнойРеквизит) = Тип(«СправочникОбъект.Контрагенты») Тогда
    Сообщить(ОсновнойРеквизит);
    КонецЕсли;
    КонецПроцедуры

    Все хорошо работает, но наблюдается потеря времени при открытии форм.

    Например функция УстановитьДоступностьПоляВводаНомера, которая вызывается ПриОткрытии() многих форм документов или элементов справочников затрачивает времени 0,003-004 сек. без проверки основного реквизита. А с проверкой 0,35 – 0,6 и больше в зависимости от сложности формы. Визуально заметна разница во времени. Придется мириться с задержкой примерно в половину секунды при открытии любой из форм.

    Reply
  45. sergant500

    Почему-то движок съедает текст. Нужно читать «заменить на»

    выхХМЛТело = СтрЗаменить(выхХМЛТело,»&»,»& amp;»); // пробел убрать между & и amp

    выхХМЛТело = СтрЗаменить(выхХМЛТело,»<«,»& lt;»); // пробел убрать между & и lt

    выхХМЛТело = СтрЗаменить(выхХМЛТело,»>»,»& gt;»); // пробел убрать между & gt

    Reply
  46. Sabfir

    Полезная штука, жаль только, что ресурснозатратная 🙁

    Reply
  47. Andrei.Rch

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

    Reply

Leave a Comment

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