UE: Copy/Paste через буфер обмена Windows справочников, документов и др. ссылочных объектов между идентичными конфигурациями (Безлимитная лицензия)




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

39 Comments

  1. davdykin

    А как в данном решение на счет ссылочной целостности. Синхронизация, я так понимаю, по ГУИД?

    Reply
  2. MarSeN

    Перенос происходит средствами серелизации.

    Да, получается что переносятня гуиды ссылочных объектов и простые типы.

    Reply
  3. Dr.Aziw

    Классная обработка !!!

    Reply
  4. Evgen.Ponomarenko

    Зачетно! Так держать )))

    Reply
  5. AllexSoft

    давно пора подобный механизм да средствами платформы, жаль 1С нас пока не слышет (

    Reply
  6. MarSeN

    (5) AllexSoft,

    У 1С рабочих рук не хватает. Хорошо они не ставят палки в колеса нам, смертным, кто пытается упростить некоторые операции )

    Reply
  7. ssn5810

    они только конфигурации до «ожирения» могут доводить

    Reply
  8. BodunOff

    Кхм, у меня кроме пунктов «Справка» и «Закрыть» ничего не отображается. Розница 2.1, платформа 8.3.4.437. Как быть?

    Reply
  9. MarSeN

    (8) BodunOff,

    У вас режим работы «отдельные окна»?

    если да, тогда Вам надо открыть форму списка в режиме отдельного окна. Т.е. нажимаете на shift и кликаете на ссылку списка в панели навигации.

    Можно так-же копировать одиночные объекты. Открываете документ и в меню именно документа (как на gif-ках только не главного окна, а окна документа) выбираете Copy. Так-же для вставки нужно проделать

    Но лучше конечно, если у вас режим отдельных окон — использовать shift при открытии списков.

    Дело в том что UE работает только если текущее окно есть в наборе окон, возвращаемых методом ПолучитьОкна(). В режиме отдельных окон все что открывается не в режиме окна — окна не имеет и UE не может работать с такой формой.

    То же самое для рабочего стола в режима закладок

    Reply
  10. MarSeN

    (8) BodunOff,

    Если не получится, обязательно напишите в личку. Я Вам помогу разобраться.

    Reply
  11. Temniy

    Интересно.

    Reply
  12. BodunOff

    (10) Спасибо, всё заработало! «+» обязательно за меганужную полезняшку!

    Reply
  13. MarSeN

    (12) BodunOff,

    Отлично! спасибо

    Reply
  14. Evgen.Ponomarenko

    (6)

    У 1С рабочих рук не хватает.

    Мозгов у них рабочих не хватает ))) Хорошо, что на ИС хватает и того и другого 😉

    Reply
  15. AllexSoft

    (14) Evgen.Ponomarenko, надеюсь они сюда заглядывают и черпают идеи… кстати, зазеркалье 1С оживилось, постоянно новости интересные появляются… это не может ни радовать ! лично у меня появилась надежда что какие то подвижки в сторону улучшений связей с 1С-общественностью все же есть!

    Reply
  16. MarSeN

    (15) AllexSoft,

    Да, 1С стала обращать внимание на то, в какую сторону смотрит общество 1С-программистов.

    Новшества в 8.3 явно взяты не с потолка. Обратите внимание на то, что сделанные «фишки» покрывают некоторые сторонние разработки.

    Reply
  17. Evgen.Ponomarenko

    (15) AllexSoft,

    Зазеркалье оживилось действительно… в целом это радует. Печалит то, что к примеру «Рефакторинг» от 1С ничего общего с действительным рефакторингом не имеет. В данном случае произошла подмена понятий: «Поиск и замена модальных диалогов» 😉

    Типа «Смотрите! — В конфигураторе теперь есть новая фишка!» Вот если бы в зазеркалье была возможность постить, вот это был бы шаг навстречу сообществу…

    А так у Нуралиева свои мечты, у разработчиков платформы свои, у нас свои.

    А пользователь хотел только одного: «Стабильности» ))))

    ПС

    К стати, «нормальный рефакторинг» начинается с нормализации структуры БД.

    Потом начинается уже функциональный рефакторинг.

    Reply
  18. MarSeN

    (17) Evgen.Ponomarenko,

    Согласен.

    Еще вариант «подьбы навтсречу» — если бы в конфигуратор добавили возможность подгружать свои скрипты и модули. Тогда бы 1С могла сосредоточить свои усилия на стратегических направлениях разработки

    Reply
  19. AllexSoft

    (17) Evgen.Ponomarenko, согласен полностью… хотя с другой стороны сколько времени конфигуратор вообще не развивался, что я рад даже этому «псевдо зачатку рефакторинга»

    А вот камментить статьи в зазеркалье действительно было бы полезно! Может Доржи предложить сделать тут раздел в типа Замеки из зазеркалья, чтобы все могли каментить не на 1с.ру, так хоть тут…

    Reply
  20. Evgen.Ponomarenko

    (18)

    Если бы в конфигуратор добавили возможность подгружать свои скрипты и модули.

    Я себе уже сделал такую фишку — пятый год наслаждаюсь )))

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

    Мне понравилась идея виждетов в WordPress-е. Инсталируешь плагин (модуль) и виджет (визуальную часть)

    настраиваешь параметры и вперед!!! Они не делят приложение на серверную часть и клиентскую.

    Они делят приложение на: Базу данных, функциональную часть, визуальную часть.

    И точка! красота )))

    Reply
  21. Evgen.Ponomarenko

    (19) AllexSoft,

    Стопудово…

    Reply
  22. adapter

    идея с копипастом хорошая. только некоторые баги в реализации. Например запустить обработку в двух базах одновременно не удалось. Пытается при втором запуске переписать длл-ки, а они открыты при первом запуске. Пришлось код немного поправить:

    &НаКлиенте
    Процедура ПриОткрытии(Отказ)
    
    ПутьККомпоненте = КаталогВременныхФайлов() + «UniversalExtensions.dll»;
    ВремФайл = Новый Файл(ПутьККомпоненте);
    Если Не ВремФайл.Существует() Тогда
    ДвоичныеДанные = ПолучитьИзВременногоХранилища(ПолучитьДЛЛ());
    ДвоичныеДанные.Записать(ПутьККомпоненте);
    КонецЕсли;
    
    ПутьКЛицензии = КаталогВременныхФайлов() + «license.key»;
    ВремФайл = Новый Файл(ПутьКЛицензии);
    Если Не ВремФайл.Существует() Тогда
    ДвоичныеДанные = ПолучитьИзВременногоХранилища(ПолучитьЛицензию());
    ДвоичныеДанные.Записать(ПутьКЛицензии);
    КонецЕсли;
    
    Успех = ПодключитьВнешнююКомпоненту(ПутьККомпоненте,»UniversalExtensions»,AddInType.Native);
    Если Успех Тогда
    
    ПолноеИмяОбработки = ПолучитьИмяОбработки();
    ФормаМеню  = ПолучитьФорму(ПолноеИмяОбработки + «.Форма.ue»,Новый Структура(«ПутьККомпоненте,ПутьКЛицензии»,ПутьККомпоненте,ПутьКЛицензии),,,ВариантОткрытияОкна.ОтдельноеОкно);
    ФормаМеню.Init(ПолучитьПользовательскиеНастройки());
    
    КонецЕсли;
    
    Отказ   = Истина;
    КонецПроцедуры
    
    &НаСервере
    Функция ПолучитьИмяОбработки()
    вОбъект    = РеквизитФормыВЗначение(«Объект»);
    ПолноеИмяОбработки  = вОбъект.Метаданные().ПолноеИмя();
    Возврат ПолноеИмяОбработки;
    КонецФункции // ПолучитьИмяОбработки()
    
    
    Функция ПолучитьДЛЛ()
    вОбъект    = РеквизитФормыВЗначение(«Объект»);
    ДвоичныеДанные  = вОбъект.ПолучитьМакет(«UniversalExtensions»);
    Возврат ПоместитьВоВременноеХранилище(ДвоичныеДанные);
    КонецФункции
    

    Показать

    Ну и ссылочной целостности у подхода нет. Т.е. перенос объектов возможен только если в реквизитах ссылочных типов ничего не менялось. А если допустим добавили нового поставщика в спр, то накладная уже переносится с <Объект не найден>. Надо рекурсии прикручивать и т.д.

    Reply
  23. MarSeN

    (21) adapter,

    при таком подходе при закрытии UE или закрытии базы должна валиться ошибка при попытке удалить файл dll (в форме ue). Там тогда временно поставьте попытку/исключение. Думаю даче обфусцированность кода не помешает вам это сделать )

    Я обязательно предусмотрю одновременное открытие обработки в нескольких базах.

    почему не сделал сразу — это временная защита от того чтобы нельзя было запустить обработку в базе повторно.

    Спасибо!

    Reply
  24. MarSeN

    (21) adapter,

    По ссылочной целостности — тут не так все однозначно.. Наверное проще открыть документ, увидеть что есть битая ссылка и скопипастить недостающий объект. Ваш вариант предполагает перенос большого объема информации, отчасти ненужной.

    Как вариант можно прикрутить механизмы конвертации данных

    но, ИМХО, изначально предложенный подход более прост в использовании и прозрачен в понимании того, что надо сделать при появлении битых ссылок.

    Reply
  25. DoctorRoza

    + однозначно! 🙂

    Reply
  26. Светлый ум

    *А на обычных формах вариант есть ?

    Reply
  27. MarSeN

    (26) Светлый ум,

    На обычных формах такого варианта нет, так как 1С в обычном режиме не предоставляет список открытых окон 1С ( ПолучитьОкна() не работает )

    Обычные формы постепенно вымирают.

    Reply
  28. Himik861

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

    Reply
  29. Himik861

    Ошибка не найдено поле ВналичииОстаток. У меня запрос в подборе переделан и не работает теперь. Не подскажите как это исправить.

    Reply
  30. MarSeN

    (28) Himik861,

    Да, быстрый поиск работает во всех динамических списках

    Reply
  31. MarSeN

    (29) Himik861,

    ВналичииОстаток

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

    Reply
  32. Himik861

    У вас ошибка!!!! если в подборе стоит галочка «Только в наличии на складе» то выскакивает ошибка «не найдено поле ВНаличииОСтаток», как это исправить. Пробовал на типовой 11.1.2.31. Есл она не стоит то все проходит нормально.

    Reply
  33. MarSeN

    (32) Himik861,

    Форма обработки QuickSearch — не 100% рабочий вариант. Об этом написано в статье.

    UE предоставляет Вам возможность организовать поиск. Вам надо самим написать-допилить безбажный код.

    Reply
  34. AKV77

    Автор, указывайте что ваша разработка требует лицензию ! Тратить стартмани на просмотр окошка не есть хорошо !

    Reply
  35. MarSeN

    (34) AKV77,

    Согласен, не хорошо.

    напишите в личку или на почту s.marchenko77 собака mail ру и я вам вышлю актуальную лицензию.

    Reply
  36. retif

    ссылка в статье http://infostart.ru/public/266022/ неработает

    Reply
  37. retif

    а строки в ТЧ тоже копирует и вставляет?

    Reply
  38. MarSeN

    (37) retif,

    В примере копирования через буфер обмена этого нет.

    UE, это механизм, который дает вам возможность сделать копирование строчек документа.

    Reply
  39. Shalnov

    Требует лицензию на dll

    Reply

Leave a Comment

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