<?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='\
вот ещё по темеВот это поворот
Один вопрос — когда помещаете во временнное хранилище не указываете адрес:
ПоместитьВоВременноеХранилище(<Данные>, <Адрес>)
Параметры:
<Данные> (обязательный)
Тип: Произвольный.
Данные, которые необходимо поместить во временное хранилище.
<Адрес> (необязательный)
Тип: УникальныйИдентификатор; Строка.
Уникальный идентификатор формы, во временное хранилище которой надо поместить данные и вернуть новый адрес. Или адрес во временном хранилище, по которому надо поместить данные. Адрес должен получен ранее с помощью данного метода.
В случае, если передается УникальныйИдентификатор формы или адрес в хранилище, то значение будет автоматически удалено после закрытия этой формы.
Если передан УникальныйИдентификатор, не являющийся уникальным идентификатором формы, то значение будет удалено после завершения сеанса пользователя.
Если параметр не указан, помещенное значение будет удалено после очередного запроса сервера из общего модуля, при контекстном и неконтекстном серверном вызове из формы, при серверном вызове из модуля команды или при получении формы.
(1) Franco, в «Альтернативы:» я уже дал ссылку на эту статью
(2) w.r., А в чём вопрос то? Боитесь, что значение будет удалено раньше чем вы успеете его использовать?
Кстати для 2-го примера <Передача макет Word (Двоичные данные) с сервера на клиент> можно и не писать
,т.к. в СтруктураВсехДокументов попадает СтруктураПараметров, в которую в свою очередь попадает только строковые значения (какое значение на какое заменить). Для строковых значений не нужно сериализовать значение. Именно эта строка написана для примера. Если вы так-же как и я в СтруктураПараметров будете писать только строковые значения, то можно и не помещать во временное хранилище.
(3)
Да, будет удалено.
Вы, кстати, еще используете без адреса временное хранилище здесь:
И вот тут лучше будет передавать в качестве адреса для временного хранилища идентификатор формы. Те вот так:
(3)
Оффтоп. Еще совет — если не используете форму на сервере, тогда лучше использовать &НаСервереБезКонтекста
(4) w.r., ну в общем случае вы конечно правы и вообще правильно написать:
Но у меня написан код:
Показать
У меня даже нет переменной где бы я запомнил адрес во временном хранилище, т.к. как только я делаю «ПоместитьВоВременноеХранилище» потом сразу делаю «ПолучитьИзВременногоХранилища». Между этими двумя действиями нет ни строчки кода, поэтому пропасть значение до получения не может. Кстати код у меня установлен в рабочей базе и всё работает.
Если же кому-то исходя из специфики задачи нужен будет этот адрес не единожды и он его будет потом использовать вплоть до закрытия формы, то конечно корректней использовать УникальныйИдентификатор.
Другими словами: замечание хорошее, но в моей конкретной реализации задачи ничего не потеряется даже без уникального идентификатора.
Спасибо за замечание, статью позже чуть допишу (вдруг кому-то и правда адрес во временном хранилище нужен будет не единожды и сразу).
(6)
Вы не внимательно читали видимо описание. Написано:
Т.е. любое выполнение регламентного задания или иных действий параллельно работающих пользователей, использующих общие модули, в промежутке выполнения вашего кода на форме очистит временное хранилище, куда вы поместили макет еше до получения из хранилища
(6)
Еще могут отработать подписки на события. Сам сталкивался давным давно с этим, когда начинал работать со временным хранилищем
Вообще, передача объектов с клиента на сервер у 1С реализвона хреново. Например, из клиентского общего модуля нельзя получить имена реквизитов формы, тк нельзя передать форму с клиента на сервер, если ты не находишься собственно в самой форме. А процедура ПолучитьРеквизиты для УФ работает только на сервере. И тут никакие временные хранилища не помогут уже
(8) w.r., Ну уж за час у нас точно куча подписок было отработано в рабочей базе))
Давайте на минуту представим, что
мы понимаем как
Первый вопрос: почему у меня тогда ничего не удалилось ни в течении часа ни в течении 10 минут на рабочей базе БП 3.0?
Второе: методы «ПоместитьФайл, ПоместитьФайлы, ПоместитьВоВременноеХранилище» получается вообще некорректно использовать без Уникального идентификатора, т.к. любое действие любого пользователя базы может привести к очистке адреса хранилища. На большом количестве народу (1000+ одновременно работающих пользователей) данные методы будут давать корректный (не очищенный) адрес только в 50% случаев, а то и меньше. Не думаю, что это так, тем более я на практике привёл пару исчерпывающих тестов.
У меня: Бухгалтерия предприятия, редакция 3.0 (3.0.41.64) , 1С:Предприятие 8.3 (8.3.6.2332).
(3) прошу прощения за невнимательность
(10)
Протестировал. Правда не очищается временное хранилище причем даже с вызовом сервера, если находишься в текущей форме.
У меня между методами
и
, выполнился метод
. Может 8.3.6 так работает, на 8.2 точно очищалось. Попробую протестировать на базе с 8.2 и отпишусь
(10)
у вас вариант базы клиент-серверный или файловый?
(13) w.r., конечно клиент-серверный. Как я написал в статье для файловой базы можно вообще не заморачиваться, выполнил на сервере запрос, чтобы получить данные, получил Word (не важно откуда) заполнил и показал пользователю. Ничего передавать на клиент не надо, лепота))
А как у вас в варианте с ActiveDocument работает на сервере эта конструкция?
В макет у меня попадает ОболочкаActiveDocument, а Получить() падает с ошибкой вызова метода контекста.
В СП написано, что для этого типа метод Получить() доступен только на толстом клиенте.
(15) Kirill_K, у меня рабочего кода на руках нет, ибо сейчас в отпуске. Сделал обработку (см вложение). где всего пару строк кода. У меня дома на 8.2 (файловая база) не падает на методе «Получить()»! На работе практически самая свежая 8.3 и там тоже никакой ошибки на этой строчке (файловая или клиент-серверная).
Тупо в обработке нажмите на «Команда1» — будет ошибка?
(16) 8.2 клиент-серверная падает, а в файловой 8.3 ком-объект создается.
Значит, обновляться нужно, спасибо.
(17) Kirill_K, код который написан у меня в статье я писал для клиент-серверной 8.3.6. Всё работало. Поэтому после обновления возможно и у вас заработает. Но для чистоты эксперимента я когда выйду на работу попробую на клиент-серверной обработку из 16 сообщения.
(17) Kirill_K, попробовал в серверном режиме на 8.3.6.2332: ничего не вырубается. После строчки:
в переменной MSWord появляется COMОбъект. Походу Вам правильный совет — это обновиться.
Кстати в справке даже в 8.3.6.2332 написано, что метод Получить() якобы работает только в толстом клиенте:)
Не пойму в чем дело?
ошибка при вызове метода контекста save типы не совпадают
(21) gmtv, есть пример-обработка, выслал её в личку.
(18) доброго дня — у меня 8.3.6 клиент сервер — запустил вашу обработку стопорится на Получить(). В чем может быть проблема?
(23) micha26,
1. У вас офис на сервере установлен?
2. Если да, то на пользователе под которым работает агент 1С нормально запускается?
3. Обработка из 16-го сообщения работает?
(24) офис установлен, пользователю даны права на запуск офиса, нет стопорится также.
(25) micha26, обработка маленькая, на какой из строк стопорится?:
И ещё: а если в обработке переделать процедуру с серверной на клиентскую: тоже не работает?
На SaveAs, без разницы клиент или серверная.
(27) micha26,
Это решение пробовали?:
Ошибка при вызове метода контекста (SaveAs)
Документ.SaveAs(ИмяВрем);
по причине:
Произошла исключительная ситуация (Microsoft Word): Ошибка команды
Мне поначалу эту ошибку не удалось победить, поэтому я стал использовать ДвоичныеДанные. Позже нашёл решение проблемы: необходимо по пути C:WindowsSysWOW64configsystemprofile и C:WindowsSystem32configsystemprofile создать папки Desktop. Туда никаких файлов никто не пишет, похоже, программе важен факт наличия этой папки. Решение нашёл по ссылке:http://devtrainingforum.v8.1c.ru/forum/thread.jsp?id=581998&threadtype=0
(28) да ходил по этой ссылке, не помогло. Макет с двоичными данными делал та же фигня получается.
(29) micha26, даже не знаю что тогда… Такое ощущение, что проблема не на стороне 1С. Может антивирус или брандмауэр что-то блокирует? Попробуйте хотя-бы локально все по-вырубать и на клиенте SaveAS() сделать.
(30) отрубал все для примера сделал следующее:
Показать
Один хрен не работает…куда копать уже не представляю.
(31) micha26, похоже у вас ошибка в строчке:
Вместо ПутьКФайлу вам нужно использовать СтруктураДанных
(32) да похоже верно — проверю.
(33) micha26,
Показать
Что-то я нить потерял, как теперь данные заполнить в документе.
(34) Вообщем переделал все на фиг — сохраняю шаблоны в выделенную папку на сервере, делаю запрос на сервере, сохраняю значения в реквизиты для печати и на клиенте заменой загоняю значения в шаблон. Шустро работает.
(34) micha26,
Вместо Word = Новый COMОбъект(«Word.Application»); и Open(ПутьКФайлу); можно использовать Документ = ПолучитьCOMОбъект(ИмяВрем); (как в принципе и написано у меня в статье)
Что касается метода Open: он вроде используется так: Word.Documents.Open(ПутьКФайлу).
(36) я таким макаром сделал:
Показать
Как бы заработало и шаблоны шустро править можно
(37) micha26, ну в принципе как вариант. Я в альтернативах в конце статьи об этом варианте тоже упомянул:
(38) за что вам премного благодарен ))))
А кстати если кому интересен полный код стучитесь в личку.
Прекрасная статья! Всё понятно и доходчиво написано.
По правде говоря мне пришло уведомление на гневный комментарий в моей теме со ссылкой на вашу статью где меня «ну просто опустили» (дословная цитата). Странно, прочитал всё от корки до корки, нигде никто меня не опускал)))) Гневный комментарий тоже удалён))) Видимо его автор сильно неуверен в себе, раз позволяет себе такое.
Насчёт кода на сервере, которым я записывал файл, вот он (в начале лета приводил в порядок всю свою базу наработок):
Показать
Спасибо, что поставили ссылку на статью. Рад, что хоть чем-то смог помочь. Сейчас отредактирую её и приведу данный листинг кода.
(41) CeHbKA,
Так вот как оказывается можно ещё сохранить! Не заметил, что у ОболочкаActiveDocument есть метод Записать. Обязательно обновите статью, т.к. многие сваливаются на методе SaveAs, а Записать() у ОболочкаActiveDocument фактически является альтернативой
Есть ещё вариант заполнения на сервереhttps://infostart.ru/public/675307/
Понять не могу только у меня спотыкается на этом месте:
ОбъектВ получается это оболочка активного документа…
(44) Попробуйте обработку из (16) сообщения и посмотрите цепочку сообщений связанных с (16). Похоже это ваш случай (у вас Платформа 8.2 же?)
(16) {ВнешняяОбработка.СоздатьТестWord.Форма.Форма.Форма(26)}: Ошибка при вызове метода контекста (Получить)
MSWord = Макет.Получить();
Столкнулся с проблемой, при заполнении Active doc на сервере. Если два пользователя одновременно запустят печать , произойдет наложение активных документов, и либо все зависнет, либо заполнится некорректно. Если ли способ разделить заполнение, чтобы оно работало параллельно?