Копирование табличной части из одного документа в другой




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

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

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

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

32 Comments

  1. vdv_4462

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

    Возможно, это по моей бестолковости, у меня не очень много опыта.

    Reply
  2. PanKir

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

    Reply
  3. vdv_4462

    Да, все верно, понял. Спасибо!

    Reply
  4. Sk0rp

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

    Reply
  5. PanKir

    (4)а какая платформа у тебя? я делал на 8.2.13.202 (и до сих пор на этой платформе, ещё не обновлял)

    может из-за этого, хотя признаюсь тут я не знаток.

    может попробовать в конфигураторе пересохранить обработку под своим именнем… хз…

    Reply
  6. Sk0rp

    У меня 1С:Предприятие 8.1.13.41, в описании обработки сказано, что она должна работать в том числе и на 8.0

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

    Reply
  7. PanKir

    (6)прошу прощения, моя оплошность, видимо всё что сделано на 8.2 нельзя использовать на 8.1 и 8.0 (((

    хотя обратное и работает…

    могу тогда предложить как вариант — сделать аналог на 8.1 простым копированием модулей и реквизитов и созданием аналогичной формы.

    всё же не с нуля начинать )))

    Reply
  8. cool.vlad4
  9. marts-ya

    попробовал из «заказа покупателя» скопировать ТЧ в другой заказ покупателя. В ТЧ 1 строка в табл. Товары. РЕЗУЛЬТАТ:

    {Форма.Форма.Форма(9)}: Индекс находится за границами массива

    СтрокаПриемник = ДокументПриемник.ПолучитьФорму().Товары[ДокументПриемник.ПолучитьФорму().Товары.Количество()-1];

    Reply
  10. PanKir

    (9) Хз что там у Вас случилось, это надо разбираться на месте, пошагово.

    Посмотрел у себя, всё работает. А с другими вариантами пар документов тоже самое?

    Если в других вариантах всё норм, то вероятней всего в этом случае Вы делаете что-то не так…

    Reply
  11. e.kogan

    (0), (8) И http://infostart.ru/public/16453/ в аналоги.

    Reply
  12. 21oleg6

    1С:Предприятие 8.2 (8.2.12.80)

    пробовал из «поступления товаров и услуг» скопировать всё и только номенклатуру в другое «поступление товаров и услуг»

    При этом в документе источнике 2 строки-проведён, в документе приёмнике нет строк(пустой)-непроведён.

    В результате выдает ошибку : Индекс находится за границами массива. Подробно: {Форма.Форма.Форма(9)}: Индекс находится за границами массива

    СтрокаПриемник = ДокументПриемник.ПолучитьФорму().Товары[ДокументПриемник.ПолучитьФорму().Товары.Количество()-1];

    Если в документ приемник добавить строку, то ошибки нет, но никакого копирования не происходит..:(

    Reply
  13. shard

    допилить на:

    Процедура КнопкаВыполнитьНажатие(Кнопка)
    Ответ = Вопрос(«Перед копированием будет очищена Табличная Часть документа-приемника. Продолжить?», РежимДиалогаВопрос.ДаНет, , , «Вы уверены???»);
    ДокПриемник=ДокументПриемник.ПолучитьОбъект();
    Если Ответ = КодВозвратаДиалога.Да Тогда
    ДокПриемник.Товары.Очистить();
    Для Каждого ТекСтрока Из ДокументИсточник.Товары Цикл
    СтрокаПриемник = ДокПриемник.Товары.Добавить();
    //СтрокаПриемник = ДокументПриемник.ПолучитьФорму().Товары[ДокументПриемник.ПолучитьФорму().Товары.Количество()-1];
    Для Каждого Строка Из ТабличнаяЧастьИсточник Цикл
    Если Строка.Флажок Тогда
    Попытка
    СтрокаПриемник[Строка.Наименование] = ТекСтрока[Строка.Наименование];
    Исключение
    
    КонецПопытки;
    КонецЕсли;
    КонецЦикла;
    КонецЦикла;
    КонецЕсли;
    ДокПриемник.записать();
    КонецПроцедуры

    Показать

    тогда работает

    Reply
  14. PanKir

    долго меня тут не было…

    исправил процедуру как предложили в последнем коменте.

    Reply
  15. FlyLink

    (13)+1

    Reply
  16. almas

    Табличные части не только в документах…

    Reply
  17. PanKir

    (16) almas, понимаю, но обычно справочники и документы не путают, когда заполняют ТЧ.

    но идея хорошая, если будет свободное время, подумаю как переделать обработку под справочники, а пока на работе запарка и шеф не дает продохнуть… (

    Reply
  18. alex_asoft

    Спасибо за обработку , помогла

    Reply
  19. Cartman

    Добавил в ТабличнуюЧастьИсточник поле синоним.

    В модуле после:

    ТабличнаяЧастьИсточник[ТабличнаяЧастьИсточник.Количество()-1].Наименование = Имя;

    дописал:

    ТабличнаяЧастьИсточник[ТабличнаяЧастьИсточник.Количество()-1].Синони = Имя;

    строку:

    СтрокаПриемник[Строка.Наименование] = ТекСтрока[Строка.Наименование];

    поменял на:

    СтрокаПриемник[Строка.Синоним] = ТекСтрока[Строка.Наименование];

    Пишем в синоним реквизит как он называется в приемнике. И пункт 1 из минусов можно убирать.

    Reply
  20. VapPaha

    хочу попробовать работу этой обработки, надеюсь поможет.

    Reply
  21. VapPaha

    хотя у меня задача перекинуть таблицу одного документа в другой из регистра бух

    Reply
  22. PanKir

    (21) VapPaha, ну добавить тип документа, который нужен именно Вам, нет проблем, главное чтоб в обоих документах были аналогичные табличные части…

    З.Ы. а при чем тут регистр бух? документ он и в Африке документ, не зависимо от регистра…

    Reply
  23. galexo

    (13)и (22)- спасибо! обработка оказалась полезной. Заработала после исправленний (13).

    Reply
  24. rustork

    Добавил свои документы… вылетает с ошибкой….

    {Форма.Форма.Форма(40)}: Значение не является значением объектного типа (Колонки)

    Для Каждого Колонка Из ТПИсточник.Колонки Цикл

    Пока разбираюсь…

    Reply
  25. PanKir

    (24) rustork,

    а что за документы и под какой конфигурацией работаешь?

    Reply
  26. galexo

    БП2:

    Если источник «Авнсовый отчет», а приемник «Треб-накладная», то сообщения:

    — Неверно выбран тип одного из документов!!!

    — {Форма.Форма.Форма(79)}: Значение не является значением объектного типа (Колонки)

    Для Каждого Колонка Из ТППриемник.Колонки Цикл

    ???

    Reply
  27. PanKir

    (26) сон,

    Если я правильно понял что БП2 — это бухгалтерия, то ошибка ясна:

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

    предполагалось что в обоих документах должна быть ТЧ — ТОВАРЫ, а в требовании-накладной такой ТЧ нет

    можно немного доработать обработку, и даже примерно понимаю в какую сторону идти, но пока у меня нет времени…

    может летом, когда пойду в отпуск у меня появится немного свободного времени и я что-нить придумаю 🙂

    Reply
  28. galexo

    спасибо, поняла

    Reply
  29. Odinsov

    Спасибо, обработка помогла.

    Reply
  30. deutsch2008

    Что то не работает (((((

    {ВнешняяОбработка.КопированиеТабличнойЧасти.Форма.Форма.Форма(40)}: Значение не является значением объектного типа (Колонки)

    Для Каждого Колонка Из ТПИсточник.Колонки Цикл

    Reply
  31. PanKir

    (30) в коменте 27 я уже писал, что документы должны иметь одинаковые ТЧ — ТОВАРЫ. Возможно Вы выбираете документы, в которых нет такой ТЧ.

    К сожалению текущий вариант работает только для ТЧ — ТОВАРЫ. Если надо другие ТЧ копировать, то можно легко подправить обработку руками.

    И вновь к сожалению у меня пока нет времени сделать обработку красивее и более функциональней и/или перевести её на управляемые формы.

    З.Ы. планирую этим заняться ближе к концу года, когда освободятся выходные.

    Reply
  32. deutsch2008

    (31) понял. спасибо )

    Reply

Leave a Comment

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