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




Принцип обмена данными из 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. 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 не будет опубликован. Обязательные поля помечены *