При разработке в среде 1С 7.7 многие программисты используют инструмент TurboMD. Это расширение для OpenConf, которое позволяет вносить изменения в модули и формы «на лету», без необходимости монопольного выгона пользователей и сохранения всей конфигурации. Однако стандартная функциональность TurboMD часто ограничена выгрузкой только текстов модулей и визуальных форм (диалогов). Макеты (таблицы в формате MXL) при этом остаются внутри метаданных, что затрудняет их быструю правку.
В данной статье мы подробно разберем, как расширить возможности TurboMD для работы с макетами, проанализируем программные способы подмены печатных форм и рассмотрим готовые скрипты для автоматизации этого процесса.
Рассмотрим ситуацию: при нажатии стандартной комбинации клавиш Ctrl+M в TurboMD выгружаются только форма и модуль. Это происходит потому, что стандартный скрипт анализирует только первые две страницы документа в конфигураторе. Выясним причину: в архитектуре OpenConf окно редактирования объекта (например, документа или отчета) представляется как многостраничный документ, где:
Для того чтобы TurboMD «увидел» макеты, нам необходимо модифицировать скрипт выгрузки, заставив его проходить циклом по всем страницам документа, начиная со второй.
Проанализируем программный код на языке VBScript, который можно добавить в основной файл скриптов TurboMD (например, TurboMD_Artur.vbs). Этот макрос позволит выгружать все макеты активного окна в отдельные файлы.
Sub UnloadCurrentWndMXL()
Dim w, d, page, i, name, pos
Set w = Windows.ActiveWnd
If w Is Nothing Then
MsgBox "Нет активного окна", vbOKOnly, "TurboMD"
Exit Sub
End If
Set d = w.Document
If d.ID < 2 Then
MsgBox "Окно не является ни формой, ни модулем", vbOKOnly, "TurboMD"
Exit Sub
End If
' Вызываем анализ файла настроек turbomd.prm
AnalyzeTurboMDPrm 1
' Проверяем тип документа. Если это воркбук (форма с макетами)
If d = docWorkBook Then
' Начинаем цикл со второй страницы (индекс 2), где лежат макеты
For i = 2 To d.CountPages - 1
Set page = d.Page(i)
' Проверяем, является ли страница таблицей
If page = docTable Then
name = page.name
pos = InStrRev(name, ".")
' Формируем имя файла на основе имени страницы
name = Left(name, pos-1) & "." & d.NamePage(i)
' Выгружаем макет в файл через вспомогательную процедуру
UnloadDoc page, name
End If
Next
End If
' Сохраняем обновленные привязки в turbomd.prm
WriteToTurboMDPrm 1
End Sub
Важное замечание: процедура UnloadDoc должна уметь обрабатывать передаваемое имя. Если ваша версия скрипта принимает только один параметр, убедитесь, что вы адаптировали вызов под свою реализацию. Рассмотрим более полную версию структуры автоматизации выгрузки ниже.
Для полноценной работы нам потребуется набор вспомогательных функций, которые будут создавать каталоги на диске и прописывать пути в файл TurboMD.prm. Разберем комплексный пример:
' Базовый каталог для выгрузки внешних файлов
Dim BaseDir
BaseDir = IBDir & "unpack\"
' Функция создания структуры папок на диске
Sub MakeDir(Dir)
Set fso = CreateObject("Scripting.FileSystemObject")
' Обработка сетевых путей UNC и локальных дисков
' ... (логика перебора папок)
If fso.FolderExists(p) = False Then fso.CreateFolder p
End Sub
' Процедура выгрузки конкретного документа (текста или таблицы)
Sub UnloadDoc(doc, Name)
fName = Replace(Name, ".", "\")
' Определяем расширение файла: mxl для таблиц, txt для модулей
If doc = docTable Then
fName = fName & ".mxl"
Else
fName = fName & ".txt"
End If
FullName = BaseDir & fName
lastdec = InStrRev(FullName, "\")
Dir = Left(FullName, lastdec - 1)
MakeDir Dir ' Создаем папку, если ее нет
doc.SaveToFile FullName ' Сохраняем объект метаданных во внешний файл
' Добавляем информацию о подмене в список для TurboMD.prm
AddDocToList Name, "unpack\" & fName
End Sub
Используя данный подход, мы получаем возможность редактировать MXL файл обычным редактором или в другом сеансе 1С, а текущий сеанс будет подхватывать изменения моментально.
Если вы не хотите глубоко внедряться в скрипты OpenConf, можно реализовать механизм «внешних макетов» непосредственно в коде конфигурации. Этот метод основан на использовании функции ИсходнаяТаблица(), которая в 1С 7.7 позволяет загружать макет из внешнего файла.
Рассмотрим пример функции, которая ищет MXL файл в специальном каталоге ExtMXL внутри информационной базы. Если файл найден — используется он, если нет — используется стандартный макет из метаданных.
Функция ПолучитьТаблицуMXL(Знач ИмяМакета="", Знач ПоУмолчанию="") Экспорт
ИмяМакета = СокрЛП(?(ПустаяСтрока(ИмяМакета)=1, ПоУмолчанию, ИмяМакета));
// Добавляем расширение, если оно не указано
Если Найти(ВРег(ИмяМакета), ".MXL") = 0 Тогда
ИмяМакета = ИмяМакета + ".MXL";
КонецЕсли;
// Ищем во внешнем каталоге базы
КаталогВнешнихМакет = КаталогИБ() + "ExtMXL\";
ФайлТаблицы = КаталогВнешнихМакет + ИмяМакета;
Если ФС.СуществуетФайл(ФайлТаблицы) = 1 Тогда
Возврат ФайлТаблицы; // Возвращаем путь к внешнему файлу
Иначе
Возврат ПоУмолчанию; // Возвращаем имя макета в конфигурации
КонецЕсли;
КонецФункции
Посмотрим на практическое применение этой функции при формировании печатной формы документа:
Процедура Печать()
Таб = СоздатьОбъект("Таблица");
// Пытаемся взять внешнюю форму "ПриходнаяНакладная.mxl"
ФайлМакета = ПолучитьТаблицуMXL("ПриходнаяНакладная");
// Метод ИсходнаяТаблица одинаково принимает как имя макета, так и путь к файлу
Таб.ИсходнаяТаблица(ФайлМакета);
Таб.ВывестиСекцию("Шапка");
// ... дальнейший код печати
Таб.Показать();
КонецПроцедуры
Этот способ крайне эффективен, так как позволяет обновлять печатные формы у пользователей на лету, просто копируя новый MXL файл в папку ExtMXL, без внесения изменений в MD файл.
В некоторых случаях макеты могут быть разнесены по подпапкам. Для этого удобно использовать рекурсивную функцию поиска. Проанализируем пример такой функции, которая использует объект ФС (Файловая Система):
Функция РекурсивныйПоискФайла(Знач ТекущийКаталог, ИмяФайла) Экспорт
ТекущийКаталог = СокрЛП(ТекущийКаталог);
Если Прав(ТекущийКаталог, 1) <> "\" Тогда
ТекущийКаталог = ТекущийКаталог + "\";
КонецЕсли;
// Проверяем наличие файла в текущей папке
Если ФС.СуществуетФайл(ТекущийКаталог + ИмяФайла) = 1 Тогда
Возврат ТекущийКаталог + ИмяФайла;
КонецЕсли;
// Если не нашли, перебираем подкаталоги
ОбъектФС = СоздатьОбъект("ФС");
Файл = ОбъектФС.НайтиПервыйФайл(ТекущийКаталог + "*.*");
Пока ПустаяСтрока(Файл) = 0 Цикл
// Игнорируем системные переходы "." и ".."
Если Лев(Файл, 1) <> "." Тогда
Атрибуты = "";
ОбъектФС.АтрибутыФайла(ТекущийКаталог + Файл, , Атрибуты);
ЭтоКаталог = Число(Сред(Атрибуты, 4, 1));
Если ЭтоКаталог = 1 Тогда
// Рекурсивный вызов для вложенной папки
НайденныйПуть = РекурсивныйПоискФайла(ТекущийКаталог + Файл, ИмяФайла);
Если ПустаяСтрока(НайденныйПуть) = 0 Тогда
Возврат НайденныйПуть;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Файл = ОбъектФС.НайтиСледующийФайл();
КонецЦикла;
Возврат "";
КонецФункции
Помимо TurboMD, существуют и другие мощные инструменты для работы с макетами вне конфигуратора:
1cv7.md в набор текстовых файлов и MXL таблиц. Это стандарт де-факто для использования систем контроля версий (Git, SVN) в разработке на 1С 7.7. С её помощью можно массово выгрузить все макеты конфигурации.Одной из проблем при работе с TurboMD является то, что конфигуратор помечает файл метаданных как измененный (флаг Dirty), даже если вы правите только внешние файлы. Из-за этого при закрытии программа настойчиво предлагает сохранить изменения. Для решения этой проблемы опытные разработчики используют дополнительные макросы для OpenConf, которые программно сбрасывают флаг модификации конфигурации, позволяя закрыть конфигуратор без лишних вопросов и без фактического изменения MD файла.
Подведем итог: для оперативной работы с макетами в TurboMD лучше всего использовать модифицированный VBS-скрипт, который учитывает все страницы документа docWorkBook. В дополнение к этому, внедрение обертки над функцией ИсходнаяТаблица() в коде 1С позволит вам и вашим коллегам редактировать печатные формы без прерывания работы пользователей.