Иерархия окон в 1С 8.2




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

50 Comments

  1. vip

    Молодец.

    Лиха беда начало.

    Любопытно, зачем 1С использует свои классы окон.

    Для понтов?

    Reply
  2. Abadonna

    (1) Начиная с 8.1 у них пошли свои… Наверное, для понтов 😉

    Reply
  3. artbear

    Интересно.

    Но ИМХО очень важное дело с окнами 8, которое пока никто не решил — это получение текста окна 🙁

    Reply
  4. artbear

    Например, очень интересная задача — получение текста модуля в Конфигураторе

    Reply
  5. AmoreMe

    Для того что вы говорите нужно организовать межпроцессный обмен, на мой взгляд инжект DLL самый лучший вариант. Но о вкусах как говорится… А уж потом помятуя, что все контролы — окна, работать с ними как с обычными окнами… (API никто не отменял и какие бы классы кто не писал, все крутится вокруг стандартного API). А текст в конфигураторе это похоже RichEdit, ну или какая его эманация! Суть дела не меняет… (Кстати в этом случае получится не просто читать текст, но и менять его из своего приложения или контролировать ввод…)

    Reply
  6. Abadonna

    (5)

    (API никто не отменял и какие бы классы кто не писал, все крутится вокруг стандартного API). А текст в конфигураторе это похоже RichEdit

    Че ж думаешь, никто не проверил его, например, на стандартную API

    SendMessage(wnd, em_GetLineCount,0,0)? Думаешь я и мессаги там не проконтролировал? Там только только через переопредление оконной процедуры добраться можно, или через перехват родных библиотек 🙁

    Reply
  7. Abadonna

    +(6) А метод отоляринголога для получения текста модуля в конфигураторе реализован в http://infostart.ru/public/19946/

    Reply
  8. Ish_2

    Хоть и не понял ни слова , а любопытствую . Скажи мне , Абадонна , по-простому. Зачем это нужно , обращение к окнам 1с из внешнего приложения ? Просто любопытно расковырять оконный интерфейс 1с ?

    Или это можно где-то применить ?

    Только предупреждаю ,я еле-еле вспомнил школьное определение Handle : логический номер назначаемый объекту (файлу , устройству и т.п).

    Reply
  9. Abadonna

    (8)

    Зачем это нужно , обращение к окнам 1с из внешнего приложения ?

    Из внешнего приложения не особенно и надо, а вот тут (картинка 6)

    http://infostart.ru/public/59436/index.php?fimages=yes#images без этого никак не обойтись, на этом все и построено. А отлаживать- куда как удобнее из внешнего

    Reply
  10. Ish_2

    (9) Кроме глубокомысленного : «кому что нравится» — сказать мне нечего.

    Reply
  11. Abadonna

    (10)

    Кроме глубокомысленного : «кому что нравится» —

    Глубомысленное давно уж написано на воротах: «Каждому своё» 😉

    Reply
  12. Ish_2

    11) Хм.. А ,пожалуй , я с тобой согласен.

    На воротах храма ВК-ашников такая надпись смотрелась бы многозначительно. И всяк входящий сюда — задумался бы.

    Reply
  13. Abadonna

    (12)

    Нет тут, как в аське,символа с двумя пивными кружками 🙁

    А НАДО!!!! Доржи!!!!!!!!!!!!!?????????????

    Reply
  14. artbear

    (8) Не обязательно из внешнего приложения обращаться.

    Если бы была возможность работы с окнами 1С, текстами и т.д., вполне можно было, например, упростить себе работу в Конфигураторе, сделав некое грубое подобие Опенконф для 77 с его скриптами и плагинами 🙂

    Лично меня этот проблема очень занимает, но пока не удается решить 🙁

    Reply
  15. Abadonna

    (14) Вот и я про то же. Если уж один из авторов 1с++ пока на разобрался, то

    (API никто не отменял и какие бы классы кто не писал, все крутится вокруг стандартного API).

    никак не катит

    Reply
  16. Ish_2

    (14) Ага. Понятно. Опенконф полгода назад поставил. Он быстрее и функциональнее чем встроенный редактор 1сv8.

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

    Где только черти не носят Абадонну… Надысь алиментами интересовался, теперь вот окошками 😮

    Reply
  18. support

    (13) Да, не хватает. 😉

    http://infostart.ru/profile/53/blog/868/

    Вот, альтернативный:

    Reply
  19. Abadonna

    (17)

    . Надысь алиментами интересовался, теперь вот окошками

    Смотрю вот сейчас на окошко… Открыть — понимаю, закрыть — понимаю, но как, блин, свернуть? :))))

    Reply
  20. ilya005

    Это конечно всё здорово, НО!!!

    Вы не подумали, ЗАЧЕМ 1с выпустила 8.2 ?!

    Что бы кто-то потом дорабатывал ее в delphi,c, .net Итд ?

    я всегда думал, что это не совсем так и вот доводы:

    1. 8.2 изначально делалась как МУЛЬТИ платформенное решение, в браузере ее (теоретически) можно хоть на линуксе и на телефоне запустить! (как там ваш прогресс бар будет работать ? — НИКАК!)

    2. в 8.2 сделали СВОЙ стандарт внешних компонент.

    Reply
  21. Душелов

    (20) Для начала стоит Вам самим ознакомиться со стандартном внешних компонент, который предлает 1С.

    Reply
  22. cleaner_it

    (16) можно поинтересоваться, а где взяли опенконф под 1С 8? Никак найти не могу, вот уже года три. Может ищу не там/не так?…

    Reply
  23. artbear

    (22) Автор (16) ИМХО подразумевал, что поставил Опенконф для 77.

    Для 8 Опенконф-а не существует, есть только некие зачатки скриптов

    http://www.1cpp.ru/forum/YaBB.pl?num=1227553473/0

    Посмотри ветку в начале и в конце

    Reply
  24. Abadonna

    (20)

    Вы не подумали, ЗАЧЕМ 1с выпустила 8.2 ?!

    Думаю, чтобы бабла еще срубить, а зачем еще? 😉

    Reply
  25. Abadonna

    (4)

    Например, очень интересная задача — получение текста модуля в Конфигураторе

    Вот такая безрадостная фигня пока ;(

    1. Окошко ввода совсем не желает вести себя как нормальный контрол оpгана упpавления pедактиpованием. В частности не реагирует на стандартную API SendMessage(handle,em_GetLineCount,0,0), которая должна вернуть количество строк в органе управления.

    2. Нажатие любой клавиши выдает неопознанную виндой мессагу 0x0118, при этом для любой клавиши wParam=0000FFFF, а lParam=BF84AC9A (всегда, блин!)

    см. рис.

    Reply
  26. Душелов

    (25) Формат бы этих сообщений получить…

    Reply
  27. KroVladS

    (0)

    класс V8TopLevelFrameSDI в 8.2 актуален только для Управляемых форм или для обычных тоже?

    Обычные формы:

    ищу

    FindWindow(L»V8TopLevelFrameSDIsec»,NULL);

    ничего не находит.

    FindWindow(NULL,L»1С:Предприятие — Конфигурация»);

    находит.

    не могу найти окно обработки. не подскажите как?

    можно ли встроить фрейм в окно обработки средствами WIN API?

    Reply
  28. Abadonna

    (27) KroVladS,

    1. Рекомендую использовать мелкософтовский SpyXX — удобная штука.

    SPYXX

    2. Для обычного приложения иерархия совсем другая, похожая на иерархию окон 7.7

    Хендл MDI-окна

    hMDI:=FindWindowEx(MainHandle,0,’V8MDIClient’,»); где MainHandle — хендл главного окна

    Хендл активной обработки

    hActiveForm:=GetTopWindow(hMDI);

    Reply
  29. KroVladS

    (28)

    Спасибо всё нашёл.

    Reply
  30. KroVladS

    (28)

    Ещё один глупый вопрос.

    Есть dll библиотека которая отправляет видеопоток в окно по его Хендлу.

    По COM подключить её нельзя т.к. отсутствуют точки входа.

    Обернул её в внешнюю компоненту NativeAPI, отправляю в окно обработки 1с, всё хорошо пока фокус захвачен dll (вместо паузы использую MessageBoxA(hMDI,»»,»»,MB_OK)), как только 1с возвращают фокус она видит что над её формой нагло надругались и падает.

    в какую сторону капать ?

    Reply
  31. Abadonna

    (30) KroVladS, в своей Native используй компонент TMediaPlayer — и всех проблем. Там можно и в MDI отправить, и в активную форму, и вообще в отдельное окно.

    Reply
  32. Abadonna

    /+31/

    Reply
  33. Abadonna

    (30) KroVladS, Блинский клин! Классно свайт обновили: «Изменить» отправляет хз куда, только не в редактирование, файлы прикрепить не дает…

    К /31/ посмотри картинку в http://infostart.ru/public/18629/

    Как раз TMediaPlayer на активной форме 1С

    Reply
  34. KroVladS

    (33)

    Спасибо за ответ. но задача несколько иная и компонент TMediaPlayer не подойдет.

    т.к. необходимо использовать именно эту библиотеку.

    Если копнуть чуть глубже, падает сама dll из-за ошибки доступа к памяти.

    Есть сишный проект построенный на этой dll вроде работает, делаю те-же вызовы из NativeAPI всё падает.

    В общем это офтопный офтоп.

    Reply
  35. KroVladS

    (33)

    офтоп

    Обернул dll библиотеку в ActiveX и 1с перестала падать.

    з.ы. да я извращенец, но работает же 🙂

    Reply
  36. Abadonna

    (35) KroVladS, там еще нюанс мог быть…

    Ты поток на хендл активной формы выводил? А, скорее всего надо было на то, что я называю hReportDialog

    Reply
  37. KroVladS

    (36)

    И на хендл активной формы.

    И на стандартный элемент картинка.

    И вставлял на форму стандартный ActivX элемент MS Forms 2.0 Frame

    Всё одно падал.

    Reply
  38. Abadonna

    (37) KroVladS, сюда не пробовал?:

    ……………………

    wnd:=FindWindowEx(wnd,w,’V8LayouterTabsWindow’,nil); //его второй V8LayouterTabsWindow

    wnd:=GetTopWindow(wnd);// его первый V8FormElement

    wnd:=GetTopWindow(wnd);// его первый V8LayouterTabsWindow

    wnd:=GetTopWindow(wnd);// его первый V8FormElement — он самый!!!!

    ____________

    Последний как раз hReportDialog

    _________________

    Тебе на обычные формы надо? Тогда напишу как там его найти

    Reply
  39. KroVladS

    (38)

    Именно туда и выводил.

    Для неуправляемых форм.

    HWND hWnd1с = FindWindow(L»V8TopLevelFrame»,NULL);

    HWND hMDI = FindWindowEx(hWnd1с,NULL,L»V8MDIClient»,NULL);

    hMDI =GetTopWindow(hMDI);

    hMDI =GetTopWindow(hMDI);

    hMDI =GetTopWindow(hMDI);

    hMDI =GetTopWindow(hMDI);// <— Элемент картинка на форме

    //лишний уровень

    // hMDI =GetTopWindow(hMDI);

    код правда сишный

    Reply
  40. Abadonna

    (39) KroVladS, стоп-стоп-стоп! Еще раз вопрос повторяю: форма обычная или управляемая?

    Reply
  41. KroVladS

    (40)

    Обычные формы.

    Reply
  42. KroVladS

    Обычные формы.

    Reply
  43. Abadonna

    (41) KroVladS,

    hReport:=GetTopWindow(hMDI);

    hReportDialog:=GetTopWindow(GetTopWindow(hReport));

    три раза TOP от MDI — вот тут железно любые компоненты рисуются

    Reply
  44. KroVladS

    (43)

    В одном из первых сообщений я дезинформировал Вас

    как только 1с возвращают фокус она видит что над её формой нагло надругались и падает.

    На самом деле

    Если копнуть чуть глубже, падает сама dll из-за ошибки доступа к памяти.
    Reply
  45. rootuk

    Подскажите, пожалуйста, могу я с помощью данного подхода изменить шрифт кнопки в командной панели? (это 1С сделать не дает), или задать размер колонки меньше ширина слова, которое в нем(как будто пользователь сам уменьшил размер колонки)?

    Reply
  46. user1014203

    Подскажите можно ли в ВК по nativeAPI получить хендл окна с помощью GetAppMainFrame? Пишу ВК на VS C++, но пока не удается вызвать GetAppMainFrame. Получаю ошибку

    Run-Time Check Failure #0 — The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

    Reply
  47. markers

    (46) Не совсем корректный ответ, но вдруг пригодится: hwndLayout = FindWindowEx(NULL, NULL, L»V8TopLevelFrame», NULL);

    Reply
  48. user1014203

    (47)Боюсь вдруг юзер запустит 2 процесса 1С, или если будет диалоговое окно, то формы будет две, в С# использовал GetAppMainFrame без каких либо проблем, но сейчас нужно nativeAPI, поэтому перешел на С++, но ни как не могу вызвать GetAppMainFrame все время валится с ошибкой.

    Reply
  49. markers

    (48) Согласен, по тому и написал что не совсем корректный ответ. Однако, если я не ошибаюсь, NativeApi компонента не имеет возможности взаимодействовать с окном 1С, только созданные по технологии COM.

    PS: Наверняка я не прав.

    Reply
  50. user1014203

    (49)Возможно вы правы, я тоже уже склоняюсь к такому варианту, но не уверен. Надеюсь кто то сможет подсказать.

    Reply

Leave a Comment

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