fileopen.js at [13d9869e32] Вы: nobody
Вход

File fileopen.js as of check-in [13d9869e32]


$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")

// Перехват команды. Метод вызывается сначала перед выполнением команды, потом после выполнения (если не отменили)
function hookSaveToExternalFileCommand(cmd)
{
    if(cmd.isBefore)
    {
        selectedFileName = ""
        // Подпишемся на событие открытия диалога выбора файла
        events.connect(Designer, "onSelectFile", SelfScript.self)
    }
    else
    {
        // Отпишемся от события открытия диалога выбора файла
        events.disconnect(Designer, "onSelectFile", SelfScript.self)
        // И откроем сохраненный файл
        if(selectedFileName.length)
            OpenFile(selectedFileName)
    }
}

// Обработчик, вызывается когда 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