Excel через ADO




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

24 Comments

  1. sashulyT

    Интересненько.

    Раз ознакомитеьлная, надо б коментарием в текст побольше написать.

    Reply
  2. logarifm

    Кстати когда работа через АДО Ексель ненужен

    Reply
  3. sashulyT

    Sasha_H, в (1) я имел ввиду комментариев в код

    Reply
  4. logarifm

    Кста, писал с форумов Миста.ру и с книги.

    Reply
  5. vovan519

    Ну рано или поздно попадется клиент без MS Officа и без Open Officа, и конечно ADO будет актуален. Разница в скорости конечно впечатляет, поэтому при большом количестве строк ADO лучше. Надеюсь доработаешь. (закрыть файл за собой, открытый через Excel.Application, количество строк через ADO, преобразование типов через ADO — числа, даты). Ну и чтоб считать обработку законченной — загрузка через OpenOffice. (могу скинуть примерчик). +1 авансом 🙂

    Reply
  6. logarifm

    Насчет преобразования, есть там недочеты я на них не зацикливался, если верно подать дату в Ексель то АДО отдаст ее верно в ТЗ, а сдесь дело программера он веть знает, что колонка «2» у него с датами вот пускай и работает. Но это мое ИМХО, я просто чисто ради прммера выклал тем более она вполне рабочая и функциональная, далее я думаю буду раздувать ее функционал, просто для начинающего программера это будет хорошим приммером и думаю максимально понятным без наворотов и т.п.

    Что же насчет закрытия АДО, я же сделал:

    АДОЗапись.Close();

    АДОСоединение.Close();

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

    И еще при использовании 1С 8.х без АДО необойтись, там сумашедшая разница в производительности, 8.х почему-то хуже обрабатывает Ексель через СОМОбъект чем 7.7

    Reply
  7. константин

    За разработку темы +3

    Reply
  8. CheBurator

    Кто мне все-таки ответ когда-нибудь?

    Если в эксель-файле есть вычисляемый столбец С=А+Б) — при работе через адо (когда на машине нет офиса) будет возвернуто правильное значение вычисляемого столбца? и кто производит вычисление в таком случае?

    Reply
  9. logarifm

    Этого точно не скажу, но нельзя все полагать на АДО, нужно и самому чуток думать если в таких случаях значение не будет вернуто правильно, значит нужно узнать формулу и вычислить (это как вариант).

    Reply
  10. Близнец

    Интересная возможность. Я как-то об этом и не задумывался. А можно через ADO записать? Например вместо select использовать insert.

    Закрыть Эксель:

    ОкноЕхел=СоздатьОбъект(«Excel.Application»);

    ОкноЕхел.WorkBooks.Close(); — почему-то у меня закрывает все открытые книги, остается только пустое окно.

    ОкноЕхел.Quit(); — полностью закрывает Эксель со всеми книгами.

    Reply
  11. logarifm

    Можно записать!!!

    Reply
  12. CheBurator

    (9) О как интересно!

    > Если в таких случаях значение не будет вернуто правильно,

    Если в таких случаях значение не будет вернуто правильно?

    Reply
  13. logarifm

    Слушай ты чего хочеш??? Я выкинул тестовый приммер. Тебе интересуют формулы копай… Я в эту обработку не выкладывал полной функциональности, а положил чисто для приммера работы с АДО.

    Reply
  14. CheBurator

    Хочу чтобы было указана область применимости данной разработки… пока даже непонятно — можно ли ее даже для чтения данных юзать…?

    -0.5

    Reply
  15. logarifm

    (14) а В САД можно…

    Для особо одаренных область проста, тест применения АДО-загрузки с Екселя….

    Reply
  16. Abadonna

    Вопрос как автора MPlus:

    Прогрес.SleepTime(0); зачем?

    или от отладки осталось?

    Reply
  17. logarifm

    (16) Скорей всего пропустил…

    Reply
  18. Abadonna

    Расширение к файлу добавь: скачивается просто ТЕСТ, без .ert

    Reply
  19. anton905

    спасибо, помогло!!!! — голова забита разным…, а сделать перегрузку надо было сделать уже вчера..

    Reply
  20. Dmitry100

    Полезная штука. Ну не в мсдн же лезть чтоб посмотреть.

    Reply
  21. cleaner_it

    При чтении через ADO надо обязательно заранее знать структуру колонок (хотя-бы их число). В противном случае надо указывать максимальное количество колонок (предположительно), и юзать код:

    Попытка

    ЗначениеЗаписи = АДОЗапись.Fields(iCount).Value;

    ВыходнаяТаблицаДанных.УстановитьЗначение(НомерПозТЗ,ИндетификатораКолонки,ЗначениеЗаписи);

    //Сообщить(«Попытка чтения колонки № «+А+»: («+ЗначениеЗаписи+»)»);

    Исключение

    //Сообщить(«Попытка чтения колонки № «+А+»: (неудачная)»);

    КонецПопытки;

    Reply
  22. cleaner_it

    И названия листов тоже должны быть известны заранее. Попробовал прочитать не книгу, а просто файл Excel (кому интересно — именно так 1С сохраняет свои mxl в xls) — не получилось, нечего читать говорит. Должно быть, для файлов Excel имеется стандартное название единственного листа. Если его узнать, то можно будет пользователю предоставить возможность загрузки книги Excel или файла

    Reply
  23. RegrZ

    Классная вещь, пригодится 🙂

    Reply
  24. pavlo

    ничего подобного, количество листов знать не обязательно, через Command можно получить

    Reply

Leave a Comment

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