Универсальная таблица для ввода данных в 1С 7.7




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

33 Comments

  1. svsrus

    Вот собственно. Плюсуйте или минусуйте ) Блин как не удобно сделано добавление статьи. Подскажите, как вставить рисунок в то место, где он должен быть.

    Reply
  2. CheBurator

    Блин, как эту таблицу-то делать? нифига не втыкаю — с чего это MXL будет весить 64 мега?

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

    Reply
  3. svsrus

    Во-первых, я не говорил про таблицу MXL. Я говорю про таблицу в режиме ввода данных. В режиме ввода данных каждой ячейке таблицы можно присвоить любой тип. С абсолютно пустой таблицей(ничего не меняя) отчет весит 166 кб. Выделив 500 на 500 ячеек и назначив им тип «неопределеныый» отчет уже весит 15 Мб. А назначив тип Справочник.XXX — уже 20 Мб. 65 мегабайт это когда 1000 на 1000).

    А что тебе не понятно? именно… Таблица сама делается, функция вверху, остается только эту функцию воткнуть в ПриОткрытии() или еще куда. Главное не забыть что таблица в режиме ввода, а ставится это в свойствах формы.

    На счет раскраски ты прав. Функция есть, раскраска в функции есть, остается только подставлять туда значения для распространенных типомест. Тут я не счел необходимым это делать, дальше додумывайте/придумывайте что хотите с этой таблицей. Хоть пусть как новогодняя елка мигает:) У меня к тем цветам что на рисунке добавится еще один — «ЗАНЯТО». Т.е. занятое место будет выделено другим цветом. Зеленое — свободные места. Т.е. визуально сразу видно будет:)

    Reply
  4. svsrus

    Позже выложу готовую обработку, если интересует…

    Reply
  5. svsrus

    ну, если не интересует не буду выкладывать значит…

    Reply
  6. CheBurator

    положи, пусть будет…

    мне такой подход нравится.. имхается мне что РМ таким образом написаны должны быть.. нафиг куча закладок и полей… 😉

    Reply
  7. astonvilla

    Выкладывай, чего уж :))

    Reply
  8. svsrus

    Che, извиняй возможно за глупый вопрос, но что такое РМ?

    Reply
  9. mdzen

    Круто. Писал для автостоянки конфу использовал таблицу в режиме ввода даных, действительно получается тяжелая. Будет время надо попробовать такой вариант….

    Reply
  10. svsrus

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

    Reply
  11. ivisor_fil

    А че не использовать просто таблицу значений? Ложишь на документ вместо табличной части и обрабатываешь клик по таблице через текущую строку и колонку? Правда раскрасить так красиво не удастся, зато гимора меньше!

    Reply
  12. ВторНик

    Люди добрые! Где в свойствах формы обработки устанавливается использовать таблицу для ввода данных? Ну, не могу найти чесное слово! Объясните тупому! 🙂

    Reply
  13. poppy

    (12)

    МенюДействияСвойства формы

    Reply
  14. ВторНик

    poppy — Спасибо! Ни разу не приходилось сталкиваться.

    Reply
  15. svsrus

    А ты попробуй 50 на 50 хотя бы ТЗ сделать… Удобно? Красиво? )))

    Reply
  16. svsrus

    Выложил обработку. Жду вопросов.

    http://infostart.ru/projects/1299/

    Reply
  17. ВторНик

    ПолучитьКоординатыЯчейки — это функция? Как она работает? Прошу не шпинять сильно, я еще не волшебник а только учусь.

    Reply
  18. mdzen

    Нормально.

    Теперь думаю как и где сохранять структуру 100×35 (или 35×100, как угодно) попробую на текущую дату в справочнике использовать строку неограниченной длины (если влезет).

    Reply
  19. svsrus

    ВторНик, в данном модуле это процедура. Причем моя. Разрешаю пользоваться) На входе в процедуру имеем адрес ячейки, как принято в 1С, т.е. формата R#C#. На выходе получаем нормальные координаты x,у(строка,столбец), чтобы можно было работать с ТЗ. Пример. На входе адрес ячейки R3C5, на выходе x = 3, y = 5.

    mdzen, именно по этому я и отказался от справочника и других вариантов. Т.к. заранее неизвестно, какая структура может быть. Поэтому было принято решение использовать в качестве «хранилища» структуры документ с табличной частью. Об этом написано в статье.

    Reply
  20. mdzen

    Да с документом оказалось динамичнее и показательно. Спасибо за идею. Будем пользовать

    Reply
  21. svsrus

    на здоровье…)

    Reply
  22. svsrus

    Все конечно хорошо. Столько похвальных комментов! Здорово!Но давайте вернемся на землю.

    Почему, никто не поинтересовался, как передать таблицу значений в документ, вызывающий эту обработку? Сейчас бьюсь над этим. Вариантов несколько, пытаюсь найти самый простой и оптимальный. К сожалению, через параметр формы не удастся. Т.к. форму в модальном режиме использовать нельзя. Предлагайте свои варианты.

    Reply
  23. astonvilla

    Понимаешь, пока нет реальной необходимости в использовании, решать возникающие проблемы при интеграции никто не будет.

    Reply
  24. svsrus

    У меня реальная необходимость)))

    Reply
  25. Shaman100M

    Я так понял, ТЗ в качестве «подложки» использовано только из-за «громоздкости» назначить тип «неопределенный» для ячеек таблицы. Но можно же хранить значение, тип которого пока неопределен как строку через ЗначениеВСтрокуВнутр(объект). А?

    Reply
  26. svsrus

    (25) Правильно понял. Поскольку таблица задумывалась как универсальная, то на теоритических примерах при размере 1000 на 1000 и более обработка просто «неподъемная» и не летающая). Но практически редко бывает более 50 на 50, так что вполне свободно можно использовать и какой-то тип. НО, использование подложки в виде ТЗ имеет свои плюсы. Скоро увидишь.

    Хранить можно, а представлять в таблице как?

    Reply
  27. Shaman100M

    (26) Представление. Должно работать:

    Код
    Ячейка.Текст = СокрЛП(Элемент);
    Ячейка.Значение = ЗначениеВСтрокуВнутр(Элемент);
    

    Показать полностью

    Хранение в ТЗ: согласен, удобно.

    Посмотрел, установка большого кол-ва строк и столбцов 10т х 10т память почти не кушает. :0 Приходится бороться со своим рационализмом: по старинке сделал бы типа, "4-ой формы нормализации": ТЗ с 4 колонками "НомСтроки","НомСтолбца","Значение","Индекс". В первой строке ТЗ хранить размерность, а Индекс — порядковый номер ячейки при проходе слева — направо, сверху-вниз.

    Reply
  28. svsrus

    (27) Нет. Не работает. В режиме ввода Ячейка.Текст = Ячейка.Значение;

    Гы. Запустил 10т на 10т. 5 минут подождал, не дождался ))) Прервал. Комп, правда, слабенький.

    Рационализм? В итоге у тебя получится в 3 раза больше ТЗ. А надо оно?

    Reply
  29. Shaman100M

    (27) Да, действительно Текст = Значение.

    Перепроверил еще раз. Память кушает. Создал ТЗ 1т колонок и 1т столбцов — 80мб. Видимо, забыл обозначить ТЗ как переменную модуля…

    Рационализм относился к задаче «редкой» посадки на большом поле. Можно использовать и список значений с представлением-составным адресом… но при макс. наполнении память еще больше, а поиск значения по представлению вообще ни в какие рамки… Так что, остается единственный вариант.

    Reply
  30. svsrus

    (29) На чсет «редкой посадки ты прав однако ) Для моей задачи так даже удобнее наверное будет. Подумаю над этим.

    Запустил 1000 на 1000. Жду 5 минут. Пока не вывелось ( Уже съело 170 Мб оперативки и фаул подкачки увеличился на 50 Мб… ((( ТЗ идет как переменная модуля. Наверно связано с расскраской таблицы.

    Reply
  31. Shaman100M

    +(29) Единственный вариант имелся ввиду твой.

    Тестил не в проге:

    ТЗ.КоличествоКолонок(1000);

    ТЗ.КоличествоСтрок(1000);

    Можно также использовать массив, инициализация «весит» те же 80мб

    Перем ВместоТЗ[

    Reply
  32. Shaman100M
  33. juk12345

    Не очень практично. А если СЗ будет под 1000 значений? Пролистаешь? А разнотипные данные? По сути в данном случае не используется таблица для ввода данных по назначению да и сама табличка суто однотипные данные без какого-либо подсчета.

    Таблицы ввода в 7.7 извратные по причине невозможности присвоения имен области таблицы программным методом, к сожалению. Мне сейчас это так необходимо, как воздух. Приходится извращаться с ВК.

    Reply

Leave a Comment

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