Инструмент обмена данными между БД с идентичными конфигурациями (OLE)




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

46 Comments

  1. АндрейКр

    Прошу прощения за отсутствие screenshot’ов. Обязательно поставлю в ближайшее время.

    Reply ↓
  2. cs25

    wolfsoft-у конечно тоже ПЛЮС !!! НиНо рулит !!!

    Reply ↓
  3. ValentinV

    Извините, но у Вас не указана версия 1с.

    Reply ↓
  4. АндрейКр

    (3) Спасибо. Версию указал.

    Reply ↓
  5. АндрейКр

    (2) Долго не мог понять, что значит «НиНо». Теперь понял 🙂 Просто поздно было. Исправлено.

    Reply ↓
  6. АндрейКр

    Выпущен новый релиз — 1.31.1.2

    Изменения — в описании, выше.

    Reply ↓
  7. АндрейКр

    Вновь новый релиз — 1.31.1.3

    Reply ↓
  8. АндрейКр

    Новый релиз 1.31.1.4

    Скачало уже 121 человек, а комментариев и плюсиков почти нет.

    Reply ↓
  9. wolfsoft

    > 6. Потенциально существует опасность бесконечной рекурсии при переборе реквизитов справочников только в случае, если значение ключа элемента справочника замыкается на этот же элемент (в последующих версиях попробую устранить эту проблему).

    Вроде не должно в «оригинале». Повторного переопределения одного и того же объекта не происходит, т.е. бесконечного цикла не должно получиться. Или я чего не продумал?

    ЗЫ: Комментарии к своей обработке читал, даже часть продублировал в «Обратной связи» http://www.1partner.nnov.ru/forum/index.php?fid=3&id=120082323675 для пользы дела.

    Reply ↓
  10. АндрейКр

    (9)

    // ищем по ключу

    Если Ключ = «Код» Тогда

    …

    ИначеЕсли Ключ = «Наименование» Тогда

    …

    Иначе

    ОбъектПриемник.ИспользоватьРодителя(РодительОбъекта);

    Если ОбъектПриемник.НайтиПоРеквизиту(Ключ, ОпределитьОбъект(Объект.ПолучитьАтрибут(Ключ)), 0) = 1 Тогда

    Если ЗамещатьЭлементыСправочников = 0 Тогда

    ОбновитьРеквизиты = 0;

    КонецЕсли;

    Иначе

    СоздатьНовыйОбъект = 1;

    КонецЕсли;

    КонецЕсли;

    т.п. ОпределитьОбъект(…) используется до того как информация о найденом приемнике попадает в ТаблУжеВыгрОб.

    Таким образом, если Объект.ПолучитьАтрибут(Ключ) это сам объект, то получается бесконечная рекурсия.

    Reply ↓
  11. АндрейКр

    Найдена ошибка при переносе реквизитов типа «Счет». Исправил. Проверяю. После проверки выложу релиз.

    Reply ↓
  12. wolfsoft

    (10) Согласен. Хотя вероятность такого ключа мала. Он же по идее уникальный должен быть.

    (11) Суть ошибки?

    Reply ↓
  13. АндрейКр

    (12) Ну это в моей обработке только. В твоей проверял. Там нету. Почему она возникает я так и не понял до конца.

    1. Почему-то некоторые документы переносились без заполненного реквизита типа счет. Причем если выгружать только этот тип документов, то все без проблем переносилось.

    Посмотрел в отладчике. Метод ОпределитьОбъект(…) действительно все правильно определял и возвращал. Метод УстановитьАтрибут(…) тоже выполнялся успешно. Но в результате все равно реквизит оставался пустым.

    Тогда я вернул функцию ОпределитьОбъектСчет(…) к тому виду как у тебя. И все заработало.

    Я ведь как делаю? Перед тем как установить атрибут — сравниваю значение этого атрибута у источника и у приемника. Если они совпадают, тогда вызываю метод ОпределитьОбъект(ЗначениеИсточника, …) (для рекурсии), а чтобы повторно не искался объект приемника (сравнение ведь прошло успешно) передаю туда и УжеНайденныйОбъектПриемника. Как только для счетов я убрал это, сразу все стало на свои места. Только все равно не понимаю, как из этого могла произойти ошибка.

    2. Перенес документы. Сверил — все совпало. Начал проводить — один бухгалтерский документ не проводится. Пишет на счете 207 недостаточно ТМЦ. Смотрю в итогах — остатки есть. А документ не видит. Начал отлаживать. В результате получил следующее: ТМЦ.Счет не равен счету из итогов, хотя коды счетов одинаковые.

    Причем ЗначениеВСтрокуВнутр(ТМЦ.Счет)={..}…{ 0000 73} ,а

    ЗначениеВСтрокуВнутр(СчетИзОстатков)={..}…{ 1879 73}. Ну примерно так. Как так могло получиться? Незнаю. ТМЦ был перенесен из источника.

    Наверное решение первой ошибки — есть решение и второй. Но я не уверен.

    Reply ↓
  14. АндрейКр

    Релиз 1.31.1.5

    Изменения — исправления ошибок:

    !!! При установленном флажке «Помечать на удаление непроведенные новые» старые документы не помечались на удаление/не отменялись с удаления вообще. Исправлено.

    !!! В некоторых случаях не переносились реквизиты типа «Счет».

    Reply ↓
  15. mihenius

    Название файла делай без пробелов ;0)

    Глюк движка сайта.

    Reply ↓
  16. АндрейКр

    (15) У меня все нормально качается. А в чем глюк?

    Reply ↓
  17. mihenius

    При скачке обрезает имя файла до пробела. )

    Может только в Firefox-е

    Reply ↓
  18. АндрейКр

    Вышел новый релиз 1.31.1.6

    Значимые изменения:

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

    +++ В отчетах агрегатные объекты из базы приемника выводятся не как ”OLE”, а в виде [владелец] наименование — для справочников и ВидДокумента НомерДокумента ДатаДокумента для документов.

    !!! При выборе ключа справочника на закладке «Настройка» можно было выбрать реквизит без флага «сортировка», что вызовет ошибку при сравнении или выгрузке.

    *** Убрал все лишние сообщения из табло. Теперь в табло сообщений будет появляться только сообщения об ошибках.

    Очень хочется узнать ваше мнение о разработке.

    Возможно есть предложения по работе обработки или возникают какие-либо ошибки — пишите комментарии.

    На сегодняшний момент 691-но скачивание. А комментариев только 17.

    Reply ↓
  19. АндрейКр

    Заметил интересную особенность. Если выполнить следующие команды:

    НачДата=’01.01.80′; //т.е. любая дата

    КонДата=’..’; //Или можно еще так: КонДата=ПолучитьПустоеЗначение(«Дата»);

    Док=СоздатьОбъект(«Документ»);

    Док.ВыбратьДокументы(НачДата,КонДата);

    То в выборку попадут все документы от даты указаной в НачДата до последнего документа в базе включительно.

    А если выполнить:

    Пер=СоздатьОбъект(«Периодический»);

    Пер.ИспользоватьОбъект(«КакойТоПериодРекв»,КакойТоЭлементСправочника);

    Пер.ВыбратьЗначения(НачДата,КонДата);

    То в такую выборку не попадет никогда ни одно значение.

    Чтобы в такую выборку попадали значения аналогично, как в выборку с документами, надо Пер.ВыбратьЗначения(НачДата);

    Reply ↓
  20. Maxis

    А как с Планом счетов? Если в одной базе есть счета, добавленные в режиме Предприятия, то они перенесутся в другую ИБ?

    Reply ↓
  21. АндрейКр

    (20) Нет. Счета не переносятся. Сейчас постараюсь сделать.

    Reply ↓
  22. mihenius

    ПриказОПриемеНаРаботу 23-к от 15.05.2006 1С:Предприятие: Номер не уникальный!

    *Записать 1 => 1С:Предприятие: Номер не уникальный!

    *Дата и время документа 15.05.06 => 1С:Предприятие: Номер не уникальный!

    +++ Приказ об увольнении 71к (31.07.2008)

    *** по собственному желанию, пункт 3 статьи 77 Трудового кодекса Российской Федерации

    *Фасет => 106

    ОбъектПриемник.УстановитьАтрибут(РеквизитИдентификатор,

    {\PROGPROGOLE131_15ИНСТРУМЕНТ ОБМЕНА ДАННЫМИ 1.31.1.5 (OLE).ERT(825)}: 1С:Предприятие: Не выбран элемент!

    Reply ↓
  23. mihenius

    Притом номер уникальный, по ходу старый док не видит, и пытается создать новый

    Reply ↓
  24. mihenius

    Еще _)

    Начата выгрузка:

    Если тблПриемникП.НайтиЗначение(ТекНачДатаПериодРекв,НомСтр,»Дата»)=0 Тогда

    {\PROGPROGOLE131_16ИНСТРУМЕНТ ОБМЕНА ДАННЫМИ 1.31.1.6 (OLE).ERT(916)}: Номер за пределами значения!

    Reply ↓
  25. mihenius

    Обычный 131 работает нормально )

    Reply ↓
  26. mihenius

    При переносе сотрудников Зик 285-Зик 285

    Неправильно переносит реквизит Пол.

    Reply ↓
  27. Катя84

    скачала,попробую

    Reply ↓
  28. gknipas

    При переносе документов «ввод расчета списку сотрудников» из ЗиК-288 в ЗиК-288 суммы округлились до рубля.

    Reply ↓
  29. Hellgard

    Начата выгрузка:

    ОбъектПриемник.Родитель = РодительОбъекта;

    {C:DOCUMENTS AND SETTINGSВЛАДЕЛЕЦРАБОЧИЙ СТОЛНОВАЯ ПАПКА (5)ИНСТРУМЕНТ ОБМЕНА ДАННЫМИ 1.31.1.6 (OLE).ERT(785)}: 1С:Предприятие: Неверное значение!

    Что это означает??

    Reply ↓
  30. АндрейКр

    (29) У меня тоже такое часто бывает. Похоже это не ошибка в обработке — а ошибка в технологии ole. Я в таком случае выключаю 1С и делаю обмен еще раз.

    Reply ↓
  31. borman

    Минус ставить не буду, не разбирался подробно. Но с наскоку воспользоваться не вышло :(.

    Reply ↓
  32. АндрейКр

    (31) А в чем причина? Не запустилась или ошибка какая?

    Reply ↓
  33. VGHOST

    Добавь плз функцию выгрузки бухгалтерских остатков из вложения, не хочу плодить ветки разработки, их и так много уже…

    Моя редакция основана на этой разработке, но от нее остались разве только кнопки, после того как попытался применить на практике и вынужден был подретушировать.

    Reply ↓
  34. knigula

    Спасибо. Очень помогло при поломке базы. Перенес объекты за 2 дня в имеющийся архив.

    Reply ↓
  35. centr1

    Здравствуйте!

    Мне нужна обработка для выгрузки отражения зарплаты в регл. учете из ЗУП в УСН..данная обработка может мне помочь? И как я могу скачать ее?

    Reply ↓
  36. VGHOST

    Эта обработка для v7, на платформе v8 не работает.

    Тут обработка конвертации данных нужна. Если в ЗУП встроенной нет, надо писать.

    Можно воспользоваться конфигурацией «Конвертация данных» с диска ИТС.

    Reply ↓
  37. junglistizzy

    Спасибо! Ваша обработка — чудо!

    Reply ↓
  38. АндрейКр

    (34)(37) Рад что понравилась! Спасибо!

    Reply ↓
  39. chetirepda

    (38) Молодец, достойная обработка, жирный плюс Вам и большое спасибо!

    Reply ↓
  40. alex_gus

    Обработка сразу падает в ошибку при нажатии кнопки выгрузить. Очень жаль возлагал на нее большие надежды.

    Reply ↓
  41. VGHOST

    (41) alex_gus, чтобы ошибок было меньше, нужно присылать хотя бы название конфигурации и тексты сообщений об ошибках. Да и скриншоты закладок обработки с настройками не помешали бы.

    Reply ↓
  42. maksimka1970

    Андрей, спасибо огромное, так вы помогли))

    Reply ↓
  43. АндрейКр

    (39)(43) Спасибо за отзывы! Рад, что помог.

    Reply ↓
  44. Minovich_losha

    Пожелания:

    1. Вывести флаг вывода трассировочных сообщений на форму. Без них быстрее работает.

    2. Контролировать длину выводимых сообщений. Если более 500, то платформа выдает модальное окно «получаемая строка превысит допустимые размеры».

    Reply ↓
  45. TrinitronOTV

    Период, по которому будет выполняться обмен, в вашей обработке можно задавать?

    Reply ↓
  46. АндрейКр

    (46) TrinitronOTV, Да. На вкладке «Выгрузка» группа элементов «Период». Еще посмотрите на вкладке «Настройка» — «Период новых документов».

    НО если в реквизите выгружаемого документа/справочника есть документ, не входящий в выбранный период (на вкладке «Выгрузка»), то он выгрузится.

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

    Reply ↓

Leave a Comment

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