<?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='\
конструктор форматной строки для даты: ДФ=’d ММММ yyyy «г.» чч:мм’
«йогурт без даты…» 🙂
(1) 3.14159, это когда вам известно, что в источнике все даты одного формата, а если нет? а если источник не один, а даты заполняют произвольно? и тд.
Форматы, к сожалению, не всегда «делают погоду».
😉
Забыли «обратный» вариант написания дат: YYYY-MM-DD
https://dev.1c-bitrix.ru/api_help/main/general/lang/format.php
ЗЫhttp://dev.1c-bitrix.ru/api_help/main/functions/date/formatdatefromdb.php
echo FormatDateFromDB(’01/23/2013′, ‘DD MMMM YYYY’); // вернет 23 Enero 2013, если язык сайта испанский
echo FormatDateFromDB(‘7 June 2012 12:00pm’, ‘SHORT’); // вернет 7 Июня 2012, если язык сайта русский и короткий формат языка — DD MMMM YYYY
echo FormatDateFromDB(‘7 June 2012 12:00pm’); // вернет 7 Июня 2012 12:00pm, если язык русский и полный формат — DD MMMM YYYY G:MIT
echo FormatDateFromDB(‘7 June 2012 12:00pm’, ‘DD.MM’); // вернет 07.06 для любого языка
(3) AnryMc, да, я знаю об этих национальных нюансах. Кстати, MS Excel и MS Access в коде VB используется нац.формат, а в запросах евро «mm/dd/yyyy» — вот где можно запутаться )))
Что касается yyyy/*/* , то можно добавить проверку первого отбора(дней) и если количество сиволов = 4, то … и тут опять тупик: «а следующий месяц или дни?»
С месяцами mm/dd/yyyy сложнее. Разве что контролировать на >12.
Это сложно и сделать на автомате практически нереально. Нельзя определить 01/01/01 где тут месяцы, года и дни ) без дополнительных вопросов = формат
Любопытно
Автор, а про регулярные выражения и объект «VBScript.RegExp» Вы слышали?
Вот такой шаблон, например: d{1,2}D{1}d{1,2}D{1}d{2,4} позволит выделить в строке дату или время из тестовых строк :
27/082015 3-15-22 = 27/082015
2/3/55 = 2/3/55
05/3/15 = 05/3/15
02/04/2015 = 02/04/2015
27.08.2015 3:15:22 = 27.08.2015
27.08-2015 5:24 = 27.08-2015
Дальше с помощью тех же регулярных выражений можно заменить все не числовые символы в строке и анализировать, дата это или время.
Также можно написать шаблон для дат, в которых месяц указан прописью.
Например, шаблон d{1,2}s+D+d{2,4} выделит из строки «1 ФеВраЛя 05 г. 20:01:0» строку «1 ФеВраЛя 05».
В общем код сократится в разы!
(6) premier, Знаю и использовал. Так же знаю, что использование функции разбивающей строку на подстроки сократит код в . И?
К слову, то, что вы не видите код и его количество в обьекте RegExp, это не значит, что его нет. ))
Функция самодостаточна в рамках 1с — это огромный плюс.
Протестируйте( в 1с), что будет быстрее работать, скажем с 100 000 строк. Но, можете не тратить время зря. )) Создание обьекта — это уже огромный «тормоз».А 100000 раз превращает такой вариант в кошмар. Так что, не вижу, ни единого плюса от RegExp в данном случае. Разве что, делать пакетную обработку столбца/структуры, что неудобно в рамках таблиц и циклов.
о, то что надо… недавно столкнулся с загрузкой счетов в которых один из вариантов даты представленный автором. в регулярных выражениях разбираться лень, а обработочка полезная
(7) а кто запрещает создавать объект один раз за сеанс и сохранять его во временном хранилище? Где-то на Инфостарте я читал статью на эту тему. А то, что мы не видим код в объекте, позволяет нам не загромождать собственный код. Хотя, я впрочем — совсем не противник альтернативных вариантов. Просто механизм регулярных выражений достаточно мощный и что немаловажно язык — лаконичный. Ну и минусы, конечно есть — COM объект всё-таки, можно использовать только на клиенте.
А вообще, конечно, при отсутствии описания используемого формата, достаточно велика погрешность преобразования. Например:
Сообщить(СтрВДату(«2/3/55»)) вернёт 02.03.1955 0:00:00, хотя это может быть также и 01.01.0001 02:03:55 т.е. время, а может быть и 02.03.2055 0:00:00, в общем, вариантов много.
(9) premier, (9) premier, вы протестируйте на нескольких сотнях тыщ и будете удивлены. Только не пакетную передачу, а по одной переменной.
))) Блин….вы занудствуете. Если вам известно, что «2/3/55» это время, так передайте в функцию «1/1/01 «+»2/3/55» и не нужны никакие форматы!!! Вам же известно, что это время…. если, конечно, вы не Чумак или Кашпировский ))) Могли бы добавить критики, что функция не отрабатывает «// 2/3/55», а такой «2/3/55 //» делает )) Ну, я же надеялся на вас )
Дам совет, а вы уже можете к нему прислушиваться или нет, это ваше дело. Не используйте никогда сторонние приложения если этого можно избежать. Причин для этого тьма, начиная от средств защиты системы, до самой ОС. Понимаете, между 1с и внешним обьектом может стоять анивирус/hips, зависит от настроек, и ваше приложение может работать нормально, а у пользователя жутко тормозить. Вы лысину заработает на правом яичке, но не догадаетесь, что у него стоит ESET NOD )))
Второй совет, бонус, делайте функции самодостаточными если возможно — это облегчает экспор/импорт/обновления. На самом деле, это, когда у вас есть опыт за пличами. наверное, главный приоритет в функциях/процедурах.
Эту функцию можно вставить в любой проект, даже «голый» и она отработает своё независимо, какие ActiveX/Com разрешены/запрещены/инфицированы/присутствуют и какая это версия — в этом ее огромный плюс.
Более того, разделители же можно добавить, убрать,… гибкость и вариативность присутствует на откупе программиста. Каждый может подстроить под свои нужды или добавить большей универсальности. Но смысл и суть функции это : » меньше вопросов — больше дела». Есть дата(кстати, это не время) и она отработает ее по основным, часто встречающимся форматам, а точнее разделителям/делиметерам. Всё! Если ваш формат какой-то особый — это не для вас. Но в гуще своей, если вам встречаются данные с разными форматами, заполняемые разными программами, сканируемые неизвестно откуда и всё это нужно класть в одно место, зычно и красиво, вот, когда эта функция очень нужна.
В общем, регулярные выражения — это очень крутой механизм, очень-очень, но не в данном, я бы сказал примитивном, случае.
(10) убедили. «+» за идею, «-» за оформление кода. Мне, например, очень сложно было вникнуть в программный код, приведенный Вами. Ну, а вообще, конечно больше на «+» тянет. Большую работу проделали. Как говорится — «респект и уважуха».
10/02/2016 00:33:07
загнулась на таком дате (((
версия платформы 8.3.8.1784
Класс! Спасибо! была мелкая ошибка, добавил затык, а так работает отлично!
не читаются месяцы «мая», «июня» и «июля», требуется доработка кода
ошибка:
Преобразование значения к типу Дата не может быть выполнено
п_мТЕМП[6] = дата(п_мТЕМП[6]);
Если п_мТЕМП[2] = 5 Тогда
п_мТЕМП[3] = «мая»;
ИначеЕсли п_мТЕМП[2] = 6 Тогда
п_мТЕМП[3] = «июня»;
ИначеЕсли п_мТЕМП[2] = 7 Тогда
п_мТЕМП[3] = «июля»;
КонецЕсли;
(14)
(16)По последним комментариям — все равно не подходит.
Добавлял свой код:
Показать
Может где то еще добавлял.