<?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='\
Решение хорошее, неоднократно к подобному прибегал. Однако не понимаю как оно решает озвученную проблему «Соединение источников данных происходит по правилам, несколько отличным от соединения таблиц в запросе и так как пользоваться этим приходится редко, то не хочется тратить время и разбираться в этом, если можно все свести к старым привычным запросам». От наборов, к которым как известно может применяется только левое соединение, оно никуда не уводит. В то же время проблема типизации колонок внешнего источника не такая уж и проблема 🙂 Затратив меньшие усилия можно набросать обработку по быстрому созданию набора данных внешних на основе переданной таблицы с последующим сохранением данной схемы для возможности использования в ручном режиме.
В моем опыте использование данного подхода мотивировалось необходимостью получить исходные настройки отборов/группировок пользователя в привычном ему виде СКД. После чего отборы использовались уже в программных запросах формирования внешнего источника (к примеру циклическая раскрутка данных дебиторки помесячно на заранее неизвестную глубину). После чего данные сформированного внешнего источника + настройки пользователя использовались для вывода результатов.
Кажется, что автор путает внешние источники данных и «набор данных — объект» в СКД.
Про «работающую схему не встречал» тоже не понял.
Когда я столкнулся с этой проблемой, нашел в форумах обсуждения еще от 2011г.
Схема обычная: использование в СКД набора данных объект, его программное заполнение и программное выполнение СКД. Структуру полей конечно вручную приходится создавать, но в общем времени разработки отчета это мелочь.
(1) Если нужно — можно пример по программному создании набора на основе ТЗ выдрать отсюда В частности, на закладке «Модификация набора записей->Редактирование набора» фильтрация осуществляется средствами отбора схема, сформированной подобным образом.
KapasMordorov — Спасибо за коментарий.
//Кажется, что автор путает внешние источники данных и «набор данных — объект» в СКД.
Да, действительно перепутал. Каюсь 🙂
//Про «работающую схему не встречал» тоже не понял.
Не встречал — значит буквально — не встречал. Это не значит — не существует. Глубокого патентного исследования не проводилось — это правда
(4)
Ну хоть поправил бы статью ради приличия. Зачем людей путать?
— что-то похожее здесь делал, давно уже. Но изобрел не сам а нашел и допилил, только где — уже не вспомню. Так что, вроде, описанное — не такая уж проблема.
Уважаемый автор, а не могли бы вы пояснить на счет создания временной таблицы в СКД. Предоставленый вами код создания ВТ имеет синтаксическую ошибку. «ПОМЕСТИТЬ» стоит после «ИЗ».
Да же, если поставить в правильной последовательности, то конструктор СКД ругается: «Ошибка в запросе набора данных по причине:Таблица не найдена «тзИнтервалов».
Или я что-то не понимаю.
(7) Вы правы — есть синтаксическая ошибка :(. Но в правильном варианте у меня все работает (версия 8.3 — может в этом дело?..). Приведенный код должен выглядеть так:
«ВЫБРАТЬ
тзИнтервалов.НачИнтервала КАК ДатаКалендаря
ПОМЕСТИТЬ втИнтервалов
ИЗ
тзИнтервалов КАК тзИнтервалов»
Сейчас для проверки создал новую обработку , добавил в нее макет типа СКД и поместил куда приведенный выше текст как показано на картинке. Конструктор запускается без проблем. Предлагаю буквально повторить эти шаги для однозначного определения ситуации.
Уважаемый автор, спасибо за статью. Я использую указанное вами решение для внесение изменений в таблицу значений, полученную в результате выполнения запроса. Все работает замечательно, за исключением возможности использовать доступ к вложенным полям через точку (на пример: Номенклатура.Артикул, ВнутреннийЗаказ.ДатаОтгрузки). При добавлении такого поля в список выбранных полей оно не отображается, при попытке отфильтровать или сгруппировать по такому полю возникает ошибка:
«Ошибка исполнения отчета
по причине:
Ошибка при выполнении обработчика — ‘ПриКомпоновкеРезультата’
по причине:
{ВнешнийОтчет.МойОтчет.МодульОбъекта(103)}: Ошибка при вызове метода контекста (Выполнить)
по причине:
Ошибка компоновки макета
по причине:
Поле не найдено «ВнутреннийЗаказ.ДатаОтгрузки»
»
Отбор и группировку делаю по полям, которые добавлены в список выбранных полей. Поле «ВнутреннийЗаказ» присутствует в запросе.
Версия платформы — 8.3.7.2027, конфигурация — УПП для Украины 1.3.42.2.
Возможно ли сделать так, чтобы можно было использовать вложенные поля?
(9) Рад, что вам пригодился описанный способ, но по вашему вопросу — боюсь ,не смогу помочь. Это решение в моей работе — эпизод, причем достаточно экзотический. Часто подобными упражнениями мне заниматься не приходится и корифеем в этой области я не являюсь. Просто решение показалось мне достаточно необычным, чтобы поместить в статью, и чтобы, возможно ,пригодилось другим (ну хотя бы в качестве начальной идеи). Сейчас углубляться в это у меня нет возможности :(.
(9) Видимо у вас поле «ВнутреннийЗаказ» может иметь тип, не содержащий реквизит «Дата». Без анализа кода точно сказать нельзя.
(11) Прошу прощения, «не содержащий реквизит «ДатаОтгрузки»»
Чума!!!
Реально работает…Спасибо!
работает!! спасибо.
(9) Разыменование ссылочных полей набора данных объект работает в том случае, если указан тип значения поля набора данных. Поскольку в данном случае набор данных объект создается программно, а его поля «копируются» из исходного набора данных запрос, то типы для ссылочных полей нужно явно указать в исходном наборе данных запрос.
Добрый день.
Если пользователь настроил отборы в отчете, то при программном получении данных запросом (ТабДанных = Запрос.Выполнить().Выгрузить();), эти отборы не работают? Запросом «выгребаются» все данные, и только после этого отрабатывает отбор?
(15) Ну да — очевидно так. Конечно, это серьезный недостаток — но как обойти это я не знаю.
(8) Скажите, эту возможность случайно не выпилили? У меня 8.3.9.1850, я никак не могу воспроизвести работающий вариант.
Создаю отчет, в схему СКД добавляю запрос-набор данных, пишу текст как у Вас указано, и при попытке сохранить выдаётся ошибка
Ошибка получения информации набора данных
по причине:
Ошибка в запросе набора данных
по причине:
{(5, 1)}: Таблица не найдена «тзИнтервалов»
<<?>>тзИнтервалов КАК тзИнтервалов
причём неважно, пишу я & или нет. Хотя конструктор запроса, да, работает…
Не знаю. У меня релиз 1с -2170. Вообще-то работает. Но при попытке проверить — несколько раз вставлял текст, включал конструктор, сохранял — описанная ошибка пару раз проскакивала, но скорее как промежуточный этап , причем не воспроизводимый регулярно — повторно нажимаешь кнопку и все сохраняется. Какие-то нюансы видимо есть. Точно сказать в чем причина не могу.
(18) «не воспроизводимый регулярно» — это я могу понять, у меня вроде бы так же. Ошибка возникает только когда текст запроса изменён (добавлен или удалён символ). После попытки сохранить выскакивает ошибка. Но при повторном сохранении того же текста (т.е. когда символы не добавлялись и не удалялись) ошибки, действительно, нет.
Но не заполняются поля (а значит нельзя настроить вариант отчёта) и при запуске отчёта в Предприятии сразу же выскакивает та самая ошибка «Ошибка в запросе набора данных».
Ладно, не получается, может вернусь к этому вопросу позже. Пока обошёл эту необходимость.
У меня на 8.3.9.1850, как и у (17) не получается воспроизвести рабочий вариант. В результате ничего не выводится.
У меня на 8.3.9.1850 и не получается воспроизвести рабочий вариант. В результате ничего не выводится. Но и ошибка не выводится.
При открытии схемы выходит ошибка.
(21) Возможно — дело как раз в этом :). Когда-то трюк сработал, и полученный код работает по прежнему. Но некоторое время назад — попробовал воспользоваться этим методом при разработке — тоже были проблемы типа описанных вами. Возможно после обновлений этот способ уже не работает. Этого можно было ожидать потому что метод , так сказать , «хакерский» , нестандартный и ненадежный. Я сильно разбираться не стал — не очень было нужно и не было времени. Так что если кто-то ждет от меня объяснений как от автора — то прошу извинить — ничего конструктивного пока сказать не могу.
В публикации укажите, что не работает данный метод на новых платформах, а то пока комменты до конца не прочитаешь можно много времени убить впустую.
Спасибо
(23) Присоединяюсь к Ивану.
Автор, пожалуйста, укажите что данный метод не работает!
Коллеги, скажите пожалуйста, есть ли чего подобное на 8.3.10+ ?
Данный метод работает, только с небольшими изменениями.
Проверял на платформе 8.3.13.1513, конфигурация на основе УПП, обычное приложение.
Не нужно сразу в запрос добавлять временную таблицу — только «заглушки» для используемых из неё полей:
Добавляем временную таблицу при замене текста запроса (мой пример):
Показать
Далее так же, как у автора.
Только у меня «слетели» настройки форматов полей.
В окончательном варианте своего отчета использовал другой метод — из статьи «Смена типа набора данных СКД с сохранением полей» (другой сайт, поэтому ссылку не привожу). Там настройки сохраняются.