<?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='\
Непонятно, зачем вообще все это нужно. В СКД можно вызывать функции общих модулей — то есть обработка полей может быть насколько угодно сложной. Единственный минус — нужно вносить изменения в конфигурацию.
(1) MadMix, собственно плюсую вопрос ) непонятно зачем это надо, в смысле понятно, что бывают такие ситуации, когда надо. Но в 95% ситуаций можно сделать всё в СКД, а тут в примерах костыль на костыле
согласен, да можно все попросить в общем модуле. и читабельность получится лучше.
но пусть +
А зачем в первом подходе использовать две схемы? Можно же сразу формировать нужную таблицу значений полностью программно, в т.ч. на основании какого-либо запроса и передавать её как источник данных для второй схемы. Т.е. первая схема не нужна.
(4) AnderWonder, на мой взгляд проще передать параметры и условия от второй схеме первой, нежели от схемы запросу, да и код будет получше выглядеть, имхо.
(0) Я не вижу в представленном примере ни одной фишки, которую нельзя было бы сделать в одной схеме, используя функционал только СКД.
Составить строку с длиной строки в скобках пожалуйста:
Функция языка выражения СКД ДлинаСтроки
Наименование +» [«+ДлинаСтроки(Наименование))+»]»
Вывести уникальный идентификатор(UUID) ссылки — пожалуйста:
XMLСтрока(Ссылка)
(1) MadMix, (2) slazzy,
А вы пробовали использовать глобальные функции в СКД-отчете с хорошим количеством строк и парой временных таблиц? А я пробовал. Окончания формирования не дождался. А дело в том, что, если в функции общего модуля идёт обращение к базе данных, то это обращение происходит после того, как получены все данные для отчёта. По сути для каждой строки запрос будет выполняться ещё раз.
Кроме того, действительно, случаются ситуации, когда нельзя изменять конфигурацию, и уж тем более выносить некие функции в глобальный модуль, отрывая их от «родных» общих модулей. И еще не очень понятно как быть в ситуации, когда в такую глобальную функцию нужно передать структуру параметров и т.д.
Т.е. ситуаций бывает много, наверное мне стоило вынести эти ситуации в начало поста.
(6) echo77,
Представленный пример я писал быстро и что сразу пришло в голову, то и написал.
Однако и ваш пример
не работает. Более того, функция ДлинаСтроки появилась только в 8.2.14, а у меня есть базы на 13.219
А вот за XMLСтрока() спасибо, как-то не задумывался что эта функция глобального контекста
(8) ошибка в тексте выражения.
Не вижу смысла сидеть на 8.2 и использовать древние релизы платформы.
Кстати, в 8.3 еще больше интересностей в СКД появилось, но 8.3 пока не пользуется большой популярностью.
(9) echo77,
Я имел в виду что пример в принципе не работает, даже так:
Ну не нравится ему конкатенация вместе с функциями.
(9), простите я точно попал в 2015 год? Просто я уже как года 2 практически не видел 8.2, абсолютно у всех стоит 8.3 и уже очень давно. Более того вряд ли вообще существуют хоть сколько-то адекватные причины не переходить на 8.3
(7), я прекрасно знаю как вызываются эти строки. Я написал всего лишь о том, что вообще крайне редки ситуации, в которых может понадобиться вручную добавлять какую-то колонку и придется делать это программно вне СКД. Почти наверняка это на самом деле можно сделать в СКД и сделать удобно, просто вероятно человек не знает все особенности СКД или не хочет/не может писать сложные запросы.
Если же реально нужна какая-то хитрая и сложная колонка, то что мешает изначально БЕЗ использования второго СКД просто собрать ТЗ и загрузить её в СКД уже с этой колонкой?
В Вашем же примере всё равно используется цикличное обращение к базе данных для каждой строки.
Так что тоже не совсем понятно в чем тут выигрыш.
(10) Да, я рукожоп. Чтобы это заработало, необходимо привести число к типу строка.
Правильное выражение выглядит так:
(11) Собрать ТЗ иногда надо на основании отборов, которые установил пользователь. Как я понял, автор об этом хочет сказать
(9) Ну ты ржачно загнул, caro collega. БП 3.0 и УТ 11.1 уже почти год требуют исключительно 8.3.
Спасибо за публикацию. Пытался самостоятельно реализовать оба подхода на практике — получились костыли, несовместимые с жизнью.
(11) у меня на работе используется 8.2 да еще и в режиме совместимости. Конфа настолько перековеркана сторонними программистами, что страшно рассказывать. В связи с чем ни кто не стремится переходить на что-либо новое. И меняющееся законодательство не пугает.
(1) MadMix, минус в том, что не всегда эти самые общие модули конфигурации могут быть открыты. Если конфа базовая — все, дело труба. А если даже нетиповая, то приходится спрашивать разрешение у руководителя проекта на добавление-модификацию общих модулей…
В любом случае универсальность теряется.
Из минусов подхода
чаще всего обычно строку из дат и чисел не получается. Решение то с подобной идеей хорошая, но пользоваться нужно в крайнем случае, когда очень надо чтоб отчет СКД был универсальным и зависел только от релиза конфигурации. Трудоемкость на час-два минимум возрастет только на изучение и подгонку.
(11) slazzy, Про повсеместность 8.3 вы зря. Типовые базы типа бух 3 и торг 11.1, да крутятся на отдельных серверах с 8.3. Но есть целый зоопарк отраслевых решений, типа альфа-авто, ликероводочный завод на обычных интерфейсах со своими доработками которые то ли будут работать на 8.3, то ли нет — проверять себе дороже. Но это вообще темы не касается.
Что касается перебора строк при выводе результата, то в методе «подстановка» никакой цикличности нет, просто идет вывод результата построчно. В «двух схемах» выгрузка в ТЗ и загрузка из нее съедают основное время. А вот когда мы используем глобальную функцию, то боюсь в этом случае запрос выполняется действительно циклично: столько раз, сколько нужно рассчитать значение функции. Я, правда, не уверен на 100%, что это так и есть, но на практике с глобальной функцией получалось неприемлемо долго.
В любом случае, ситуаций, когда что-то нельзя получить в запросе очень мало. И даже если они возникают, чаще всего удается объяснить заказчику, что так ему не нужно.
(12) echo77, Да, действительно, две схемы используются потому, что на них легко «накинуть» один и тот же пользовательский отбор.
Регулярно использую вариант 2 схемы, но параметры и отборы доступные пользователю нужно делать по первой схеме чтобы ограничить выборку данных и не затягивать формирование отчета. По поводу — нафига ваще — а ряд формул расчета значений в строках оперируют итоговыми значениями других ресурсов
(18) Lancelot-2M,
Все правильно, только в моем примере и вообще концептуально, пользовательский отбор накладывается на обе схемы сразу, но за основу берется вторая схема, поскольку в ней есть новые рассчитанные значения, по которым мы тоже, как правило, хотим отбор.
(17)
Т.е. вызов глобальной функции плохо, а обращение к БД в цикле методом НайтиПоНаименованию — ОК?
Имеется ввиду, что вы в цикле обращаетесь каждый раз к базе. Таким макаром СКД и запросы использовать вообще нет смысла.
?
(20) alest, При вызове глобальной функции будет как минимум такое же количество обращений к базе данных. Более того, это толком нигде не описано, но у меня есть большое подозрение, что весь запрос может выполняться столь раз, сколько будет обращений к глобальной функции. Есть еще ряд ограничений, которые накладывает вызов глобальной функции. Они описаны выше. Могу и повторить: 1. Не всегда возможно добавлять в конфигурацию глобальный модуль со своей функцией. 2. В эту функцию мы не сможем передать сложные параметры вроде структур. 3. Собственноручное наблюдение: если глобальная функция не очень простая, то с ней отчет формируется ооочень медленно.
(1) MadMix, действительно костыль на костыле. Но можно развить идею, например, создать свой ПроцессорВывода, который выводит не только в ДеревоЗначений, ТаблицуЗначений и ТабличныйДокумент, а и в другие прикладные типы.
(19)
Добрый день. Возможно ли получить данные с веб сервиса (таблицу значений), при помощи данной схемы?
(23) Никаких проблем. Только в ТЗ понятно должны быть текст и числа. Ссылки только в виде GUID или 1С-ссылок в текстовом формате.
Добрый день!Попробовал применить первый подход для своего отчета. В первую схему в Вычисляемое поле получаю ТаблицуЗначений готовой функцией общего модуля, далее беру из нее значение определенной ячейки, предварительно сохранив результат схемы компоновки в ТаблицуЗначений1, добавляю в ТаблицуЗначений1 новую колонку и вывожу в нее строку из ячейки, а колонку ТаблицаЗначений (Вычисляемое поле) удаляю, она мне больше не нужна, но отчет пустой. Подскажите, в чем может быть ошибка?
Автор ввел в заблуждение.
Понятно что во втором случае любой дурак может сделать
но как заменить цифру в отчете на основе текущих группировок он не объяснил. А этим вторым способом — никак.