$engine JScript
$uname fileopen
$dname Открыть файл в Конфигураторе
$addin global
$addin stdcommands
global.connectGlobals(SelfScript)
/* Скрипт для перехвата сохранения файлов для Снегопата и немедленного открытия файлов
* Автор : Артур Аюханов aka artbear aartbear@gmail.com
* Страница скрипта: http://snegopat.ru/scripts/wiki?name=fileopen.js
* Дата создания: 04.10.2011
* Описание : http://snegopat.ru/forum/viewtopic.php?f=3&t=33
Скрипт "Немедленное открытие файлов, сохраняемых в Конфигураторе"
Я часто работаю с отчетами/обработками, встроенными в конфигурацию, следующим образом.
Сохраняя встроенный отчет/обработку в файл, открываю этот файл (Файл - Открыть - поиск файла в папке, как правило, файлов в папке немало, секунда или две теряется ), исправляю файл
и тут же, не перезапуская Конфигуратор и Предприятие, и не выгоняя пользователей в случае рабочей базы, открываю исправленный файл в режиме Предприятия.
Уверен, что по такой схеме работаю не я один.
И вот у меня родилась мысль немного автоматизировать этот процесс:
разработчик сохраняет отчет/обработку в файл (тут как обычно),
а дальше вступает скрипт: перехватывает сохранение файла, узнает имя и путь файла, проверяет расширение этого файла,
если это внешний отчет/обработка, то скрипт предлагает немедленно открыть этот файл в Конфигураторе.
Планы: В настройках скрипта можно будет указать:
всегда открывать такие файлы без вопроса или всегда задавать вопрос,
расширения открываемых файлов - по умолчанию erf, epf
*/
var _версияСкрипта = 0.4
var selectedFileName
// Подпишемся на перехват команды сохранения во внешний файл
// Также можно бы еще подписаться на "Файл-Сохранить как", но пока оставим это Артуру
events.addCommandHandler("{55C7732C-0C33-4394-ADCA-9D15082552B6}", 32, SelfScript.self, "hookSaveToExternalFileCommand")
var viewMetadata = null;
var refs = [];
// Перехват команды. Метод вызывается сначала перед выполнением команды, потом после выполнения (если не отменили)
function hookSaveToExternalFileCommand(cmd)
{
if(cmd.isBefore)
{
selectedFileName = "";
// Подпишемся на событие открытия диалога выбора файла
events.connect(Designer, "onSelectFile", SelfScript.self)
var view = windows.getFocusedView()//windows.getActiveView()
if(!view){
} else {
viewMetadata = view;
}
}
else
{
// Отпишемся от события открытия диалога выбора файла
events.disconnect(Designer, "onSelectFile", SelfScript.self)
// И откроем сохраненный файл
if(selectedFileName.length){
OpenFile(selectedFileName);
if (viewMetadata){
//проверим есть ли модуль менеджера, и откроем его в отдельном тексте.
doOpenCurStaticObject(stdcommands.Frntend.MDSearchRefs, true);
}
}
}
}
// Функция ищет объект метаданных в контейнере по его имени
function findObject(root, name)
{
//Message(name)
var names = name.split(".") // Разобъем имя на части
for(var idx = 0; idx < names.length - 1; idx += 2)
{
var mdc = root.mdclass
for(var i = 0, c = mdc.childsClassesCount; i < c; i++)
{
var cc = mdc.childClassAt(i)
if(cc.name(1, false) == names[idx]){
root = root.childObject(i, names[idx + 1])
break
}
}
}
return root
}
// Перехват вывода в окно сообщений
function onMessage(params)
{
refs.push(params.text) // Запомним, что выводилось
params.cancel = true // Не будем реально выводить
}
// Перехват появления модального диалога
function onDoModal(dlgInfo)
{
dlgInfo.cancel = true // Просто сразу скажем, что в нем нажали OK
dlgInfo.result = mbaOK
}
function doOpenCurStaticObject(command, forceShow)
{
if(windows.modalMode != msNone)
return false
// Для начала проверим, что мы в окне метаданных
var view = viewMetadata;
if(!view)
return false
//debugger;
var state = command.getState(view)
if(!state || !state.enabled)
return false
refs = []
// Ставим перехват на вывод в окно сообщений
events.connect(Designer, "onMessage", SelfScript.self)
// Подавляем показ диалога
events.connect(windows, "onDoModal", SelfScript.self)
// Посылаем команду поиска ссылок
command.sendToView(view)
// Убираем перехваты
events.disconnect(Designer, "onMessage", SelfScript.self)
events.disconnect(windows, "onDoModal", SelfScript.self)
if(refs.length < 2)
return false
var rootObject = view.mdObj.container.rootObject
var currentObject = findObject(rootObject, refs[0].match(/"(.+)"/)[1]);
var mdc = currentObject.mdclass;
for(var i = 0, c = mdc.propertiesCount; i < c; i++)
{
var mdProp = mdc.propertyAt(i)
var mdPropName = mdc.propertyAt(i).name(1);
if (mdPropName == "МодульМенеджера"){
var text = currentObject.getModuleText(mdPropName);
if (text.length > 0){
textDoc = v8New("textdocument");
textDoc.УстановитьТекст(text);
textDoc.Показать("МодульМенеджера");
}
}
}
viewMetadata = null;
refs = [];
return true
}
// Обработчик, вызывается когда 1С использует диалог для запроса имени файла.
// Подключается и отключается в hookSaveToExternalFileCommand
function onSelectFile(selectFileData) //As ISelectFileData
{
if(selectFileData.result != sfrNormal)
{
// Значит какой-то другой обработчик до нас уже что-то сделал
if(selectFileData.result == sfrSelected && selectFileData.filesCount == 1)
{
// И при этом он не отменил операцию, и указал один файл
// Запомним его, чтобы попытаться потом открыть
selectedFileName = selectFileData.selectedFile(0)
}
return
}
// Сами получим имя файла для сохранения, чтобы знать, что открывать
// ВАЖНО. Событие "onSelectFile" генерится как при системных запросах 1С,
// так и при использовании в скриптах метода ДиалогВыбораФайла::Выбрать,
// кроме тех случаев, когда ДиалогВыбораФайла::Выбрать используется в обработчиках
// события onSelectFile, дабы избежать зацикливания.
var selDlg = v8New("ДиалогВыбораФайла", РежимДиалогаВыбораФайла.Сохранение);
selDlg.Заголовок = selectFileData.title.length ? selectFileData.title : "Сохранить во внешний отчет/обработку"
selDlg.ПолноеИмяФайла = selectFileData.initialFileName
selDlg.Каталог = selectFileData.folder
for (var i = 0 ; i < selectFileData.filtersCount; i++) {
filterVal = selectFileData.filterVal(i)
selDlg.Фильтр += selectFileData.filterDescr(i)+" ("+filterVal+")|"+filterVal + "|"
}
if(!selDlg.Выбрать())
selectFileData.result = sfrCanceled
else
{
selectedFileName = selDlg.ПолноеИмяФайла
selectFileData.addSelectedFile(selectedFileName)
selectFileData.result = sfrSelected
}
}
var Text = '00000000-0000-0000-0000-000000000000' // простой текст
var TextOem = '74d75a51-58b7-46b0-931a-f3bac20e596e' // простой текст - кодировка Dos/Oem
var Epf = '0e0e54cf-253b-4fc9-a895-26897e1a51f7' // обработки
var Erf = '6d01520c-23c6-4301-86f7-e81268f07ee3' // отчеты
var Moxel = 'e555a6fe-768f-476a-bf4b-1d945aa56099' // табличный документ
var Configuration = 'c64ce8a4-a74d-40e9-996e-feadca885e11' // файл конфигурации
var Template = '03ad782c-900b-4594-bdb7-66ed05992b8b' // файл шаблонов
var kindArray = new Array(Text, TextOem, Epf, Erf, Moxel, Configuration, Template)
function Test()
{
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function (obj, fromIndex) {
if (fromIndex == null) {
fromIndex = 0;
} else if (fromIndex < 0) {
fromIndex = Math.max(0, this.length + fromIndex);
}
for (var i = fromIndex, j = this.length; i < j; i++) {
if (this[i] === obj)
return i;
}
return -1;
};
}
assert(0, kindArray.indexOf(Text))
assertNot(-1, kindArray.indexOf(Text))
}
// try{
// _macrosTestOpenFile()
// }
// catch(e){
// Message("ошибка macrosTestOpenFile() - "+e)
// //Message("ошибка macrosTestOpenFile()") // - "+e)
// }
// JScript source code
//24.08.2011 11:34:38 orefkov добавил:
//Тут возник вопрос по поводу открытия файлов в Конфигураторе.
//В объектной модели снегопата этого нет. Однако, вспомнив, как я открывал ert-шки в Конфигураторе 7ки в опенконфе, решил тряхнуть стариной и провернуть такой же финт ушами.
//А в опенконфе я их открывал просто - добавлял имя файла в начало MRU (это список недавно открываемых файлов, появляющийся в меню Файл) и посылал команду "Открыть нулевой файл из списка MRU".
//После десяти минут проб и ошибок в JS-Immediate, все получилось.
//Итак, по порядку
//Список MRU лежит (сюрприз!!!) в профайле 1С по пути (еще сюрприз!!!) - "App/MRUFileList"
//Этот список - обычный список значений, правда значения в нем не обычные.
//С помощью ЗначениеВСтрокуВнутр разобрался, что там лежит, а с помощью ЗначениеИзСтрокиВнутр - смог создать нужное мне значение.
//В этом значении главное - путь к файлу и какой-то гуид, очевидно обозначающий тип документа, который должен открывать этот файл. Для текстовых доков гуид прост - сплошные нули. Для других видов доков надо исследовать, перебирая значения из MRUFileList, и смотря на них через ЗначениеВСтрокуВнутр
//Далее просто впихнул свое значение в начало списка, сохранил весь список в профайл, и послал нужную команду.
//Вот код:
function _macrosTestOpenFile()
{
//var filepath = "c:\\test\\snegopat\\core\\std\\scripts\\0_global_context.js"
var filepath = "T:\\Snegopat\\Starter\\scripts\\configCaption.js"
Message("1")
try{
OpenFile(filepath)
}
catch(e){ Message("Неудача") }
Message("2")
try{
OpenFile(filepath, "")
}
catch(e){ Message("Неудача") }
Message("3")
try{
OpenFile(filepath, "1")
Message("Неудача")
}
catch(e){}
}
function assert(p1, p2)
{
if (p1 != p2)
throw "Значение <"+p1+"> не равно <"+p2+">, а ожидали равенство";
}
function assertNot(p1, p2)
{
if (p1 == p2)
throw "Значение <"+p1+"> равно <"+p2+">, а ожидали неравенство";
}
//Еще один параметр в методе OpenFile - тип документа (их лучше задать символьными константами)
//Если тип не передан, попытаться найти его по расширению файла.
//Если расширение непонятное, использовать нулевой гуид.
//
//то есть чтобы можно было пользоваться так:
//$addin fileopen of
//fo.OpenFile(path)
//fo.OpenFile(path, fo.TextOEM)
//fo.OpenFile(path, fo.Template)
//и тд и тп.
//
function OpenFile(filepath) //, filekind)
{
Message("Открываем файл "+filepath)
// Подготовим наше значение для MRU - списка
kind = Text
// if (filekind)
// kind = filekind
// if (-1 == kindArray.indexOf(kind))
// throw "Неверный параметр filekind = "+filekind
var mruItem = ЗначениеИзСтрокиВнутр('{"#",36973550-6bbb-11d5-bf72-0050bae2bc79,\n' +
'{1,\n' +
'{"file://' + filepath + '",0},' + kind + '}\n' +
'}')
// Получим текущий список MRU из настроек
var mru = profileRoot.getValue("App/MRUFileList")
// Если там уже есть наше значение, удалим его
var hasInMru = mru.НайтиПоЗначению(mruItem)
if(hasInMru)
mru.Удалить(hasInMru)
// Если список полон, удалим последний элемент
if(mru.Количество() == 8)
mru.Удалить(7)
// Вставим значение для нашего файла в начало списка
mru.Вставить(0, mruItem)
// Сохраним MRU-список обратно в настройки
profileRoot.setValue("App/MRUFileList", mru)
// И зашлем команду
stdcommands.Frame.RecentFile.getState()
stdcommands.Frame.RecentFile.send(0)
return true
}
//Вот так пытливый ум преодолевает преграды.
//ЗЫ: Для просмотра MRU использовался следующий код:
function macrosИсследоватьMRU()
{
var mru = profileRoot.getValue("App/MRUFileList")
for(var i = new Enumerator(mru); !i.atEnd(); i.moveNext())
{
Message("v=" + ЗначениеВСтрокуВнутр(i.item().Значение), mExc3)
}
}
//В просмотре профайла мне помогло scripts\devtools\pflview.js