<?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='\
Запомним как упорядочение приемов.
Однако предложенное 1С использование копипаста втыкает в файл-приемник всю ту грязь, которую пользователь копирует у себя пока программа готовит вордовый документ…
«А мужики то не знают»…
🙁
Вся эта объектная модель взаимодействия требует установленного ворда.
Была у меня идейка извратиться и написать взаимодействие с Word’овскими макетами через ЧтениеДанных для простых задач.
Работать должно в разы быстрее и не требовать офиса.
Раньше также делал дикую вложенность как у вас:
Показать
Попробуйте такую запись, она легче читается:
Можно и от цикла избавиться с помощью рекурсивных процедур или goto, но это уже извращение)))
Я сделал с полпинка на node.js — передаешь по GET или POST набор параметров «Ключ:Значение» и имя шаблона, в 1С приходит готовый docx, удобно когда на сервере нет офиса или COMОбъект не работал как у нас (наверно 64битность имеет значение)
(2) (3) я писал COM сервер на C# по прикручиваниюhttps://habrahabr.ru/post/269307/ , работает быстрее некуда, работает на сервере, из минусов только, что нужно особым образом делать шаблоны и нет универсальности, поэтому и не выкладываю
(4) Здорово, но все еще медленнее чем чтение из потока двоичных данных)
автор «собаку съел» на шаблонах Word и автоматизации взаимодействия 1с и Word
респект
Если разрешите — несколько замечаний / дополнений:
1. Вы закладку ищете в цикле. Это лучше делать так:
2. По замене маркеров на нужный текст
У Вас предлагается поиск и замена, но не учитывается, что таким образом можно вставить текст только до 250 символов
Если текст больше — будет исключение. Приходится его разбивать на части и вставлять кусками — так было реализовано в 1С: Документообороте раньше.
Сейчас в БСП сделано концептуально правильно. См. общий модуль УправлениеПечатьюMSWordКлиент, процедура Заменить. Через Selection.TypeText(…).
И я бы рекомендовал использовать все же закладки. В Word-документе кроме основного контента и колонтитулов есть еще и другие Story (например, текст в надписях графических объектов). В каждой Story нужно отдельно поиск выполнять.
Есть универсальное решение
https://infostart.ru/public/662990/
Отлаженное, на его внедрениях тоже много Word’овских собак съедено 🙂
Хорошая статья и бесплатная !
Добрый день.
Смотрю вы работали плотно с WORD, может знаете как программно через 1С задать стиль всему документу по умолчанию 2003, вместо 2010?
(9) Нет, не приходилось сталкиваться. Может кто-нибудь из коллег подскажет.
(9) Дмитрий, а как бы вы это вручную сделали?
(11) в ручную просто. Скриншот прилагаю.
(12) Если знаете как сделать вручную — тогда включаете запись макроса, выполняете действие, останавливаете запись. Потом этот макрос открываете, смотрите как на VB эти действия делаются. Обычно этот код можно из 1С выполнить (с небольшими адаптациями).
Вот для вашего случая что получилось:
ActiveDocument.ApplyQuickStyleSet («Word 2003»)
(13) спасибо за идею!
Но решил отказаться от типового функционала по разбору ворда. Написать свой.
Я как понял баг заключался в том, что типовой функционал копирует участок текста и вставляет в свежий открытый документ. И естественно слитают стили. Но я ведь не могу всегда быть увереным что будет точно 2003… по этому буду как автор публикации ваят свой парсер ворда.
Хотя почти во всех конфигах даже старых типа КА1.1 есть модули по работе с шаблонами ворда. Эх.
Может сможет подсказать кто, как в документе Word скопировать и вставить ниже уже существующую таблицу.
Делаю так:
В результате таблица копируется но весь текст и предыдущая таблица исчезает.
(15) Предполагаю что Content.Paste() делает вставку вместо всего контента. Вам наверное нужно вставить вместо последнего параграфа, который вы добавили.
Что-то вроде
(16)Спасибо большое. Сейчас попробую.
(16)
Шаблон.Application.Documents(1).Paragraphs(КоличествоПараграфов-1).Range.Paste()
(16)
Все получилось! А можно еще один вопрос? Как сделать так, чтобы таблица копировалась с нового листа?
(18) Я вам с ходу не подскажу. Наверное что-то вроде
перед добавление параграфа.
(19)Спасибо!
Спасибо автору.
Хотелось бы еще добавить (может кому пригодиться) поиск и замену колонтитулов в макете Word:
MSWord = Новый COMОбъект(«Word.Application»);
MSWord.ActiveDocument.Sections(1).Headers(1).Range.Find.Execute(«<ТекстИскомогоКолонтитула>»,,,,,,-1,,,<НужныйТекст>, 2); — верхний
MSWord.ActiveDocument.Sections(1).Footers(1).Range.Find.Execute(«<ТекстИскомогоКолонтитула>»,,,,,,-1,,,<НужныйТекст>, 2); — нижний
Зачем в типовом механизме пользовательских шаблонов делают через копирование шаблона? например при копировании не копируются оформление страницы. Сейчас придется изобретать велосипед
Спасибо! Отличная статья. Вопрос автору — как можно вставить из файла HTML в Word информацию (с конвертацией)