Загрузка из EXCEL в 1С. Чтение файла XLSX средствами 1С. ПостроительDOM




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-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='\

25 Comments

  1. StepByStep

    Чтение файла XLSX средствами 1С. ПостоительDOM

    Reply
  2. monkbest

    Я извиняюсь, а можно в статью написать текст с описанием. А то кроме цитаты из мстителей слов-то и нет:)

    По листнингу понять, что рассказывается в статье — сложно. Скомкали все. Дали ссылки на пять статей, в которых та же каша, процитировали. Кроме заголовка ни одного информативного слова нет.

    Reply
  3. arasn

    Полезная информация!

    Reply
  4. StepByStep

    (2) monkbest,

    Добавил небольшое описание.

    СПАСИБО.

    Reply
  5. DragEugen

    если бы было с описанием всех функций то вообще бы цены небыло

    Reply
  6. monkbest

    так это же получается клевая штука. Читаем ексель без екселя. очень удобно будет для случаев, когда нет возможности создать ОЛЕ оъект екселя в силу его отсутствия или же недостаточности прав

    Reply
  7. Drizer2000

    А этот метод обрабатывает только файлы с расширением XLSX, а обычный xls умеет?

    Reply
  8. awk

    (7) Drizer2000, Докумены Microsoft Office с некоторых пор хранятся в формате xml. И сжаты zip.

    Reply
  9. awk

    (7) Drizer2000, xls хранятся не в zip/xml.

    Reply
  10. hazd

    интересный подход, но как-то все сложно описано, сохраню в блокнот, время будет, разберу.

    Reply
  11. Ivon

    (6) monkbest, Читать эксель без экселя можно и с помощью ADO. И быстрее, и код меньше, и читать можно файлы любых версий.

    Reply
  12. StepByStep

    (11) Ivon,

    ADO описан здесь: Метод ADO

    Reply
  13. Soikalv

    Интересно. на досуге разберусь.

    Как много нам открытий чудных готовит внедрение новых платформ 1с. Вот перехожу на тройку и радуюсь ища новые обработки для тройки.а так хорошо все было настроено в 8.1. и 8.2. Так и не поняла из статьи, эта обработка — то,что я ищу или нет. В 8.2. была типовая внешняя обработка с диска ИТС для загрузки данных из таблиц икселя в любой табличный документ. Целые базы грузили, очень удобно было..

    Reply
  14. StepByStep

    (13) Soikalv,

    Обработка, в которой применяется функционал этой статьи: http://infostart.ru/public/120961/

    Обработка построена по-другому, если сравнивать ее с обработкой с ИТС.

    Reply
  15. kuzyara

    При применении на практике мне нужна была просто ТаблицаЗначений, идентичная натуральной, доработал несколько моментов:

    Во-первых, убрал разделитель разрядов во всех числах которые приводятся к строке, по-моему здесь типизация — лишнее.

    Во-вторых, убрал первые три колонки: «НомерСтроки», «Сопоставлено», «УровеньГруппировки».

    В-третьих, МассивИменКолонокXLSX определяется по первой строке, пришлось написать свою функцию ДесятичныйВНомерКолонки(х):

    Функция ДесятичныйВНомерКолонки(Знач НомерКолонки)
    Перем Латиница, ДлинаНомера, Поз, ит;
    Латиница = «ABCDEFGHIJKLMNOPQRSTUVWXYZ»; // 26.
    // 1   5    0    5    0    5
    
    целое = НомерКолонки;
    слово=»»;
    
    Пока Целое>0 Цикл
    НовЦелое=Цел(Целое/26);
    
    остаток = Целое%26;
    
    Буква = Сред(Латиница, остаток, 1);
    слово = Буква+слово;
    Целое=НовЦелое;
    КонецЦикла;
    
    Возврат слово;
    
    КонецФункции

    Показать

    В целом метод рабочий, автору большая благодарность.

    Reply
  16. Cyberhawk

    Подскажите, пожалуйста, можно ли в вашей «подсистеме» (назвал так прилагаемый к публикации набор процедур и функций) узнавать цвет фона ячейки xlsx-файла? Если да, то в какой процедуре / функции из прилагаемых это можно сделать?

    Reply
  17. kuzyara

    (16) Cyberhawk, принципиальной сложности в разборе https://en.wikipedia.org/wiki/Microsoft_Office_XML_formats нет.

    Reply
  18. StepByStep

    (15) kuzyara,

    Удачного применения.

    Reply
  19. StepByStep

    (16) Cyberhawk,

    При распаковке должен сформироваться файл styles.xml, в котором описаны используемые форматы.

    Reply
  20. pedchenko32

    Добрый день! Почему, если в файле xlsx 1 лист, возникает ошибка файл не обнаружен …sheet2.xml? Если создать 2й лист, с таким же содержимым, считывание происходит…

    Reply
  21. pedchenko32

    и еще вопрос, как определить в этом случае, что ячейка пустая?

    Reply
  22. pedchenko32

    или как сделать, чтобы строки с оформлением тоже не включались в таблицу значений?

    Reply
  23. StepByStep

    (20) pedchenko32, (21) pedchenko32, (22) pedchenko32,

    1. «sheet2.xml» — не сталкивался.

    2. «ячейка пустая» — ЗначениеЗаполнено(ЗначениеЯчейки).

    3. «строки с оформлением» — Конкретно это не интересовало. Если строки пусты — то написать доп процедуру.

    Reply
  24. Жолтокнижниг

    Необходимо поправить загрузку SharedStrings

    иногда встречаются подобные конструкции:

    <si><r><t>mail@mail.ru</t></r><r><rPr><sz val=»10″/><color rgb=»FF000000″/><rFont val=»Arial»/><family val=»2″/><charset val=»204″/></rPr><t xml:space=»preserve»>  </t></r><r><rPr><sz val=»10″/><color rgb=»FF909090″/><rFont val=»Arial»/><family val=»2″/><charset val=»204″/></rPr><t> </t></r></si>

    За счет этого сбивается нумерация.

    Если SharedStrings.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
    МассивSharedStrings.Добавить(Строка);
    КонецЕсли;

    мое исправление ситуации

    Reply
  25. tyfmyl

    Добавте в параметры функции разрядность округления — Окр(). Excel при чтении данных при выгрузке полей не форматированных представляет некоторые числа в виде бесконечной десятичной дроби с «9» ой на конце.

    Из справки известно, что excel хранит числа в 8 байтах. Для округления достаточно 14 цифр разрядов.

    Reply

Leave a Comment

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