Загрузка данных из таблицы Excel в два шага




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

30 Comments

  1. D9ID9I_SaIIIa

    (0)»Для того, чтобы каждый раз не писать одно и то же, предлагается идея загружать данные из Excel в два шага.»

    хм…по моему чего то не хватает в заголовке и в содержательной части,или я чего то недопонимаю…

    +скриншоты мелкие

    \каждый извращается по своему 😀

    Reply
  2. karabas1980

    Да уж… Для скриншотов лупы явно не хватает

    Reply
  3. Abadonna

    (0)

    Пока есть данные во всех указанных колонках – в текстовом поле указывается одно или несколько номеров колонок, разделенных точкой с запятой «;», если в строке в одной из колонок содержится пустое значение, загрузка прекращается

    И чего только народ не придумает 😉

    E.Workbooks.Open(Сокрлп(ИмяФайла));
    Строк=E.Cells.SpecialCells(11).Row;    // строка последней ячейки
    Столбцов=E.Cells.SpecialCells(11).Column; // столбец последней ячейки
    
    Reply
  4. Арчибальд

    (3) В соответствии с этикой Конфуция, ты должен был отплюсоваться 😉

    Reply
  5. мх

    Рациональное зерно в предложении есть.

    Несмотря на высказанные замечания по реализации.

    Можно развить предложение дальше: сделать эту обработку вызываемой с параметрами. При автоматизации обработки полученных от различных поставщиков накладных такой подход может быть весьма полезен

    Reply
  6. Abadonna

    (4)

    В соответствии с этикой Конфуция, ты должен был отплюсоваться

    А в соответствии с этикой Абадонны, это мне кто-нить должен спасибо сказать, кто не знал, о существовании SpecialCells, а в частности, о

    SpecialCells(11)

    Reply
  7. Арчибальд

    (6) Ты отвечаешь за тех, кого приручаешь, в частности, за тех, кому сообщаешь о SpecialCells 😎

    Reply
  8. Abadonna

    (7)

    Ты отвечаешь за тех, кого приручаешь

    Это называется по другому:

    Ни одно доброе дело не останется безнаказанным!

    😉

    Reply
  9. Арчибальд

    (8) Верно. Вот и «накажи» себя сам 😉

    Reply
  10. Abadonna

    (9)

    Верно. Вот и «накажи» себя сам

    Ну и скажи тогда: на какую из своих разработок мне минус поставить? 😀

    Reply
  11. Арчибальд

    (10) Поскольку на свою минус не получится, поставь плюс сюда. Наказание будет в укорах совести за отданный якобы незаслуженный плюс. 🙂

    Reply
  12. Abadonna

    А ставить плюс на СоздатьОбъект(«Excel.Application») не буду никогда, аж по трем причинам:

    1. Кто его пользует незаконно — ворюган

    2. Кто купил — дурачок

    3. И есть, наконец, http://infostart.ru/public/59436/

    Работа с xls-файлами на считывание/запись напрямую (не требует наличия Excel или Open Office)
    Reply
  13. Арчибальд

    (12)

    1. Кто его пользует незаконно — ворюган

    2. Кто купил — дурачок

    Я не покупал, но и не крал — пользуюсь корпоративной лицензией. 😀

    Так что заслуживает внимания только 3-я позиция.

    Жадница

    Reply
  14. Ish_2

    (6) Ну, я не знал. Но кто кому что должен — запутался.

    По Арчибальду выходит ты мне должен плюс поставить, а я тебе — простое спасибо.

    Reply
  15. Арчибальд

    (14)

    1. Арчибальд прав.

    2. Если кто-то считает, что Арчибальд ошибается, значит он чего-то не учитывает. Например, контекст формы.

    Reply
  16. Abadonna

    (13)

    Я не покупал, но и не крал — пользуюсь корпоративной лицензией.

    Либо вы её брали давно, когда она дешево стоила, либо твоя корпорация — дурачок. А на моей бывшей работе спокойно снесли всем доменной политикой все Офисы, поставили Open Office (так же автоматом, при входе в систему) — юзвери поворчали немного, привыкли и работают себе спокойненько

    Reply
  17. Арчибальд

    (15) Шо вы мне зубы заговариваете? Вам это, право, не с руки. 😎

    Reply
  18. Abadonna

    (17) Арчи, я так и не понял за что я должен плюс поставить.

    Вот написанная лет пять назад функция:

    Функция ReadExcel(ИмяФайла) Экспорт
    Попытка
    E=СоздатьОбъект(«Excel.Application»);
    Исключение
    Предупреждение(«Excel на компьютере не установлен!»);
    Возврат ПолучитьПустоеЗначение();
    КонецПопытки;
    E.Workbooks.Open(Сокрлп(ИмяФайла));
    Строк=E.Cells.SpecialCells(11).Row;    // строка последней ячейки
    Столбцов=E.Cells.SpecialCells(11).Column; // столбец последней ячейки
    фТЗ=СоздатьОбъект(«ТаблицаЗначений»);
    Для А=1 По Столбцов Цикл
    фТЗ.НоваяКолонка();
    КонецЦикла;
    Для Стр=1 По Строк Цикл
    Состояние(«Обработано «+Строка(Стр)+» строк из «+Строка(Строк));
    фТЗ.НоваяСтрока(Стр);
    Для Столб=1 По Столбцов Цикл
    фТЗ.УстановитьЗначение(Стр,Столб,СокрЛП(E.Cells(Стр,Столб).Value));
    КонецЦикла;
    КонецЦикла;
    E.Workbooks.Close();
    Возврат фТЗ;
    КонецФункции
    

    Показать

    Что-то мне подозревается, что она делает почти как раз то, про что статья;)

    И не надо «каждый раз не писать одно и то же», вызови функцию в любом отчете, поимей готовую ТЗ и делай с ней, что хочешь.

    P.S. Если с номером листа, тогда так

    Функция ReadExcel(ИмяФайла,Лист=1) Экспорт

    и, соотвественно:

    Строк=E.Sheets(Лист).Cells.SpecialCells(11).Row;

    Столбцов=E.Sheets(Лист).Cells.SpecialCells(11).Column;

    Reply
  19. Арчибальд

    (18) Связался черт с младенцем 😀

    За это младенцу (младенцЕ) и плюс. Я так дУмаю 😎

    Reply
  20. Abadonna

    (19) Лежала бы в профайле фотка, да если бы мне еще и интерфейс понравился, я бы плюсанул даже не читая про что тут. 😉 Вот так!

    Да и ваще — может бы и поставил, но теперь из вредности (из-за тебя) точно не поставлю. Так что радуйся, что не минус 😀

    Reply
  21. Арчибальд

    (20)

    из вредности (из-за тебя)

    Арчибальд = Вредность Абадонны

    Ни хрена себе теорема. Доказывай!

    Reply
  22. Abadonna

    (21) Не теорема, а аксиома:

    Хочешь, чтобы Абадонна чего-нибудь не сделал — проси очень настойчиво его это сделать 😉

    Reply
  23. Арчибальд

    (22) Обратное тоже верно? 😉

    Reply
  24. Abadonna

    (23)

    Обратное тоже верно?

    Это односторонняя функция 😉

    Триггер уже перекинулся, поэтому вопрос рейтинга этой разработки уже обсуждению не подлежит 😀

    P.S. А если по честному — жуть до чего дикий принцип решения изложен

    Reply
  25. Арчибальд

    (24) Поверю на слово — я не читал.

    Reply
  26. Abadonna

    (25)

    Поверю на слово — я не читал.

    Советник, блин. Развел тут фаворитизм 😀

    Reply
  27. Арчибальд

    (26) Фаворитизм здесь ни при чем. Это ностальгия. Вспомнилось, как я кувыркался с импортом из екселя за заре знакомства с одноэсиной. Всплакнул 😥

    Reply
  28. Abadonna

    (27)На заре я с ним и кувыркаться не стал, просто сохранял сразу xls в dbase4, а работа с dbf — это было как раз то, что я самое первое в 1С освоил;)

    Вот эта, кстати, вообще моя самая первая на 7.7:

    http://infostart.ru/public/14639/

    Reply
  29. Арчибальд

    (28) С этим-то было просто: Клиппером вдоль и поперек ДОСовской 1С я рассекал уверенно. А в Ексель вообще не лазил. Впервые увидел году в 2000, позже своих экономистов 😮

    Reply
  30. Abadonna

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

    Функция глОткрытьФайл(Маска=»») Экспорт
    Перем ИмяФайла,ИмяКаталога;
    Маска_=»Файлы «+Маска+»|*.»+Маска;
    Если СокрЛП(Маска)=»» Тогда
    Маска_=»Все файлы |*.*»
    КонецЕсли;
    Если ФС.ВыбратьФайл(0,ИмяФайла,ИмяКаталога,»Открыть файл»,Маска_)=1 Тогда
    Возврат ИмяКаталога+ИмяФайла;   //полное имя открытого файла
    Иначе
    Возврат «»;
    КонецЕсли;
    КонецФункции
    
    Функция ReadExcel(ИмяФайла,Лист=1) Экспорт
    Попытка
    E=СоздатьОбъект(«Excel.Application»);
    Исключение
    Предупреждение(«Excel на компьютере не установлен!»);
    Возврат ПолучитьПустоеЗначение();
    КонецПопытки;
    E.Workbooks.Open(Сокрлп(ИмяФайла));
    Строк=E.Sheets(Лист).Cells.SpecialCells(11).Row;    // строка последней ячейки
    Столбцов=E.Sheets(Лист).Cells.SpecialCells(11).Column; // столбец последней ячейки
    фТЗ=СоздатьОбъект(«ТаблицаЗначений»);
    Для А=1 По Столбцов Цикл
    фТЗ.НоваяКолонка();
    КонецЦикла;
    Для Стр=1 По Строк Цикл
    Состояние(«Обработано «+Строка(Стр)+» строк из «+Строка(Строк));
    фТЗ.НоваяСтрока(Стр);
    Для Столб=1 По Столбцов Цикл
    фТЗ.УстановитьЗначение(Стр,Столб,СокрЛП(E.Sheets(Лист).Cells(Стр,Столб).Value));
    КонецЦикла;
    КонецЦикла;
    E.Workbooks.Close();
    Возврат фТЗ;
    КонецФункции
    
    Процедура Сформировать()
    ИмяФайла=глОткрытьФайл(«xls»);
    Если СокрЛП(ИмяФайла)=»» Тогда Возврат; КонецЕсли;
    ТЗ.Загрузить(ReadExcel(ИмяФайла,1)); // ТЗ — таблица значений на форме
    // ну а дальше смотрим визуально, что с ней дальше делать
    КонецПроцедуры
    

    Показать

    Примечание: функции, конечно, перенести в ГМ или ДопГМ formex, т.е. в отчете останется только процедура Сформировать()

    Reply

Leave a Comment

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