Универсальная смотрелка DBF-файлов [обновлено!]




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

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

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

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

33 Comments

  1. artbear

    (0) Вместо

    Для Каждого ПолеDBF Из ФайлDBF.Поля Цикл

    НомерКолонки=НомерКолонки+1;

    НоваяСтрока[ПолеDBF.Имя]=ФайлDBF[ПолеDBF.Имя];

    КонецЦикла;

    Попробуй поюзать

    ЗаполнитьЗначенияСвойств(НоваяСтрока, ФайлДБФ);

    Reply
  2. aximo

    (1) согласен, но так как у меня — более «классически что-ли» и понятнее…

    Reply
  3. aximo

    (0) просьба, можешь подсказать как выделять цветом код… я не нашел с ходу тегов

    Reply
  4. Alraune
  5. artbear

    (3) Когда у тебя будет ДБФ из хотя одной/двух тысяч строк, разницу сразу ощутишь 🙂

    ЗЫ ВСЕГДА юзай ЗаполнитьЗначенияСвойств, а не ручной перебор имен.

    ИМХО Это признак опытного разработчика 1cv8

    Reply
  6. aximo

    (5) спасибо. исправил, стало быстрее.

    Reply
  7. anton.fly7

    а если будет колонка на 950 символов, как твоя обработина его покажет?

    и еще, не проще ли смотреть DBF_ки в екселе?

    Reply
  8. alexk-is
    Reply
  9. artbear

    (8) Да, ФайлDBF.Следующая(); очень быстро работает.

    Reply
  10. DionisioSPb

    А вот я столкнулся, что при выполнении такого кода:

    //———————

    ОбъектXBase = Новый XBase;

    ОбъектXBase.Кодировка = КодировкаXBase.OEM;

    ОбъектXBase.поля.Добавить(«KEY», «S», 50, 0);

    ОбъектXBase.поля.Добавить(«STR», «S», 50, 0);

    ОбъектXBase.СоздатьФайл(«C: est.dbf»);

    ОбъектXBase.АвтоСохранение = Истина;

    Значения = новый Структура(«KEY, STR», «Значение KEY», «Значение строка»);

    ОбъектXBase.Добавить();

    ЗаполнитьЗначенияСвойств(ОбъектXBase, Значения);

    ОбъектXBase.Записать();

    ОбъектXBase.ЗакрытьФайл();

    //———————

    Поле «KEY» не будет заполнено. Пришлось переделывать на Для Каждого ИмяПоляDBF Из ПоляDBF Цикл

    Грустно…

    Reply
  11. echo77

    Простым пользователям эта штука на хер не нужна, anton.fly7 правильно говорит — DBF проще смотреть с помощью excel/calc.

    Куда сложнее обратное преобразование, у меня в публикациях была такая штука

    Reply
  12. defini
    echo77 пишет:

    Простым пользователям эта штука на хер не нужна, anton.fly7 правильно говорит — DBF проще смотреть с помощью excel/calc.

    правильно говорит — DBF проще смотреть с помощью excel/calc.

    ИМХО смотреть дбф-ки удобнее дбф-навигатором и вьювером. Но никак не екселем.

    Reply
  13. jONES1979

    «Простым пользователем» ещё и похерить можно DBF-ку, открывая её Экселем и исправляя. А потом в нескажу-каком-банке её не примут, потому что убогие программисты этого банка толи «привязали» свою программу к какой-то устаревщей версии формата DBF, толи ещё чего.

    Reply
  14. djd.sf
    «Простым пользователем» ещё и похерить можно DBF-ку, открывая её Экселем и исправляя. А потом в нескажу-каком-банке её не примут, потому что убогие программисты этого банка толи «привязали» свою программу к какой-то устаревщей версии формата DBF, толи ещё чего.

    Это ты про что? Разъясни пожалуйста, я не понимаю.

    Reply
  15. jONES1979

    Это пример из жизни, вместо того чтобы сформировать DBF c корректными данными, бухгалтеры открыли Екселем и подправили цифры. Но в банке их программа «подавилась» DBF-кой, не смогла открыть.

    Reply
  16. sommid

    Типизация очень даже може пригодиться. Например, для использования полученной таблицы в качестве виртуальной в запросе.

    в свое функции писал так:

    //—————————————-

    Для каждого ТекКолонка из мФайл.Поля Цикл
    
    ТипДБФ = ТекКолонка.Тип;
    //возможные типы из Синтаксис-помощника: Содержит тип поля: «S»- строка, «N» — число, «D» — дата,
    //    «L» — булево, «F» — число, «M» — мемо поле (не поддерживается)
    
    Если ТипДБФ = «S» Тогда
    ТекТип = «Строка»;
    ТекКвалификатор = Новый КвалификаторыСтроки(ТекКолонка.Длина);
    ТекОписаниеТипов = Новый ОписаниеТипов(ТекТип, , ТекКвалификатор);
    тз.Колонки.Добавить(ТекКолонка.Имя, ТекОписаниеТипов);
    
    ИначеЕсли ТипДБФ = «N» ИЛИ ТипДБФ = «F» Тогда
    ТекТип = «Число»;
    ТекКвалификатор = Новый КвалификаторыЧисла(ТекКолонка.Длина, ТекКолонка.Точность);
    ТекОписаниеТипов = Новый ОписаниеТипов(ТекТип, ТекКвалификатор);
    тз.Колонки.Добавить(ТекКолонка.Имя, ТекОписаниеТипов);
    
    ИначеЕсли ТипДБФ = «D» Тогда
    ТекТип = «Дата»;
    ТекОписаниеТипов = Новый ОписаниеТипов(ТекТип);
    тз.Колонки.Добавить(ТекКолонка.Имя, ТекОписаниеТипов);
    
    ИначеЕсли ТипДБФ = «L» Тогда
    ТекТип = «Булево»;
    ТекОписаниеТипов = Новый ОписаниеТипов(ТекТип);
    тз.Колонки.Добавить(ТекКолонка.Имя, ТекОписаниеТипов);
    
    Иначе
    ТекТип = «»;
    тз.Колонки.Добавить(ТекКолонка.Имя);
    
    КонецЕсли;
    
    КонецЦикла;

    Показать

    //————————————

    
    
    Reply
  17. help1Ckr

    Читалка в дбф удобная функция — иногда не удобно между окнами переключатся. Еще бы для xmlфайлов нормальную смотрелку сделали 😀

    Reply
  18. help1Ckr

    Кстати, для большей пользы, не мешало бы добавить итоги по числовым полям.

    Reply
  19. Hamitova

    На 1С я перешла с Fox Pro, и мне показалась очень интересной и простой эта обработка. Спасибо…

    Reply
  20. aximo

    (19) да пожалуйста. это у меня капля в море и еще идей непаханное поле …

    Reply
  21. boriskud

    Спасибо! Функция пригодилась при написании процедуры загрузки в базу DBF файла.

    Reply
  22. anig99

    (0) переделал под управляемые формы http://infostart.ru/public/98411/

    (17) для xml вот есть — http://infostart.ru/public/84254/

    Reply
  23. xaker1C

    Прикольно

    Reply
  24. Waldor

    Спасибо. Оптимизировал свою дбф загрузку…

    Reply
  25. stormtg

    Спасибо, очень интересно

    Reply
  26. i132

    Получится немного быстрее если анализировать ответ ДБФ.Следующая();:

    ЕстьЗаписи = ДбФ.Первая();

    Пока ЕстьЗаписи Цикл



    ЕстьЗаписи = ДБФ.Следующая();

    КонецЦикла;

    пример отчета на СКД по произвольному DBF файлу: http://infostart.ru/public/116645/

    Reply
  27. Созинов

    Спасибо. Думаю функция пригодится. Как раз планируем добить FoxPro. Остались последние секции, так что думаю можно будет перетащить остатки на 8.2 автоматом, а не заниматься этим вручную. Хотя от ручной работы полностью не избавиться (в foxpro по моему штрихкоды отсутствуют).

    Reply
  28. h_vitya
    Спасибо. Думаю функция пригодится. Как раз планируем добить FoxPro. Остались последние секции, так что думаю можно будет перетащить остатки на 8.2 автоматом, а не заниматься этим вручную. Хотя от ручной работы полностью не избавиться (в foxpro по моему штрихкоды отсутствуют).

    Меня устраивает через Exel смотреть dbf

    Reply
  29. electronik

    Спасибо но хотелось узнать как предстоят дела с кодировками, ато при работе с ДБФ возникает кучу моментов кодировками ето здесь предусмотрено или нужно руками допиливать

    Reply
  30. aximo

    (30) в моих задачах еще не случалось его допиливать под что-то… малая вероятность…

    Reply
  31. Alfer

    меня устраивает во всем — а некоторые моменты возьму на вооружение для дальнейшего использования

    Reply
  32. vvirus

    добавь определение типов данных DBF, при формировании таблицы — это поможет при загрузке ТЗ в запрос

    пример есть тут http://infostart.ru/public/100001/

    Reply
  33. cheiser1982

    Адаптированно для управляемых форм платформы 8.3:

    DBFViewer8_3 для управляемых форм

    Reply

Leave a Comment

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