Как в Terrasoft проверить существует файл или директория на диске или сервере или же нет?
Ну и соответственно вернуть true или false.

Нравится

1 комментарий

Что-то я рано о помощи просить стал.
Делается так:

var filepath='C:\\testfile.txt';
var fso=new ActiveXObject('Scripting.FileSystemObject');
if (fso.FileExists(filepath)) {
   //true
} else {
   //false
}
Показать все комментарии

Ниже предоставлено описание, как создать опцию «Открыть папку с файлом» для кнопки "Операции"
.
1. Открываем окно wnd_FilesDetailGridArea
2. На вкладке «Невизуальные» создаем новый ActionMenuItem
3. Вводим необходимые свойства
4. На событие OnExecute добавляем в функцию подобный код:

var Dataset = dlData.Dataset;
var Link = Dataset.Values('Link');
var folderpath = Link.substring(0,Link.lastIndexOf("\\"))
var oShell = new ActiveXObject("Shell.Application");
oShell.Open(folderpath);

5. Сохраняем изменения

1

Нравится

Поделиться

0 комментариев
Показать все комментарии

В этом блоге хочу рассказать о развитии Drag&Drop в версии 3.4.x+
Никому не секрет, что DataGrid «умеет» принимать файлы с помощью Drag&Drop. Такая функциональность реализована на детали «Файлы». Но, для того, чтобы файлы извлечь с детали «Файлы», к примеру, прикрепить к письму, требуется совершать операции по сохранению его на жесткий диск, а уж потом перемещать куда нужно. Данный способ манипулирования файлами занимает много времени. Поэтому, в DataGrid был добавлен функционал полноценного Drag&Drop. Теперь есть возможность сохранять файлы только с помощью мыши. Также, весьма немаловажным бонусом, появилась возможность копировать и вставлять файлы с помощью комбинаций Ctrl+C/Ctrl+V. Именно с помощью этих операций не обойтись при переносе файлов внутри системы (файлы из одной записи в другую, из одного раздела – в другой). Плюс к выше сказанному появилась «автогенерация файлов по формату». Т.е., при нажатии Ctrl+V система анализирует содержимое буфера и генерирует (+ сохраняет) файл нужного формата.
Поддерживаемые форматы:

  1. Все изображения. Любое изображение будет сохранено в PNG формате (даже если Вы нажали Print Screen, то система сгенерирует Вам готовый файл)
  2. RTF. Любой форматированный текст буде сохранен в формате *.rtf
  3. HTML. Любой текст с HTML разметкой будет сохранен в *.html файл
  4. TEXT. Любой текст, который не является RTF – будет сохранен в *.txt файл

Дальше речь пойдет о реализации этих возможностей. Для начала пройдемся по имеющимся, а также новым свойствам:
Pic 1

  • CanCopySystemObjects – свойство, которое разрешает или запрещает копирование с помощью Ctrl+C
  • CanDragDropSystemObjects – знакомое свойство с предыдущих версий, которое разрешает или запрещает Drag&Drop в систему. Однако, в 3.4.x оно еще отвечает и за Drag&Drop из системы
  • CanPasteSystemObjects – свойство, которое разрешает или запрещает вставку с помощью Ctrl-V

Также, помимо свойств, появились новые события:
Pic 2

  1. OnGetSystemObjectNames – в обработчике события нужно заполнить имена файлов, которые будут копироваться (файлы будут сохранены под этими именами и расширениями). По количеству имен в списке будут генерироваться события OnGetSystemObjectData
  2. OnGetSystemObjectData - это событие придет столько раз, сколько было задано имен файлов в обработчике события OnGetSystemObjectNames. И при каждом вызове будет прислан Index файла, данные которого нужны. В обработчике необходимо вернуть поток данных согласно индексу файла
  3. OnPasteSystemObject – данное событие будет генерироваться при нажатии Ctrl+V. В него будет передан список файлов, которые нужно сохранить
  4. OnGetSystemObjectText – данное событие генерируется в том случае, когда «приемник» файла не может принять файл, но может принять текст. Поэтому в обработчике можно изменить текст, который будет передан

Маленьким, но приятным бонусом, появилась возможность отображать иконки, зарегистрированные в Windows согласно расширению файла:
Pic 3
Для того, нужно в обработчике OnGetRowDrawInfo, параметру ImageName нужно установить значение имени файла с расширением. Причем имя значения не имеет, так как поиск будет происходить только по расширению файла. Пример:

function OnGetRowDrawInfo(DataGrid, Color, TextColor, ImageName, Font) {
ImageName.Value = 'File.docx'; //Все элементы будут отображать иконку Word’а
ImageName.Value = 'File.xls' //Все будут отображать иконку Excel
}

Перед тем, как подвести итог, я предоставлю код реализации этих возможностей:

//Эта функция идентична для сохранения файлов как на
//событие OnDragDropSystemObjects, так и на OnPasteSystemObjects
function InsertSystemObjects(SystemObjectsList) {
        var FilesArray = SystemObjectsList.CommaText.split(',');
        var FileNames = System.CreateObject('TSObjectLibrary.StringsList');
        for (var i = 0; i FilesArray.length; i++) {
                FileNames.Clear();
                var Path = FilesArray[i];
                while (Path.indexOf('"', 0) != -1) {
                        Path = Path.replace('"', '')
                }
                FileNames.Add(Path);
                if (!CheckFileExists(Path)) {
                        AddObject(ft_FolderLink, Path, 1, null);
                } else {
                        AddObject(ft_File, FileNames, 1, null);
                }      
        }
}
 
//Реакция на Drag&Drop
function grdDataOnDragDropSystemObjects(DataGrid, DataGridColumn, SystemObjectsList, DestinationRowID, DropMode, WithCtrl) {
        InsertSystemObjects(SystemObjectsList);
}

//Реакция на Ctrl+V
function grdDataOnPasteSystemObjects(DataGrid, DataGridColumn, SystemObjectsList, SelectedIDs) {
        InsertSystemObjects(SystemObjectsList);
}

//Запрос имен объектов, который нужно копировать
//Если, в обработчике , вы запретите копировать какой-то
//файл (не передадите его имя), то в обработчике события
//OnGetSystemObjectData вам также нужно реализовывать
//дополнительные проверки
function grdDataOnGetSystemObjectNames(DataGrid, SourceDataGrid, SelectedIDs, SystemObjectNames) {
        var Dataset = GetSingleItemByCode('ds_Files', 'SystemObjectsFileDetail');
        var FileDataDataField = Dataset.DataFields.ItemsByName('FileData');
        EnableDatasetFilters(Dataset, false, 'ID');
        EnableDatasetField(Dataset, FileDataDataField, false);  
        Dataset.Open();
        for (var i = 0; i SelectedIDs.Count; i++) {
                if (!Dataset.Locate('ID', SelectedIDs(i))) {
                        continue;
                }
                SystemObjectNames.Add(Dataset('Link'));
        }
        Dataset.Close();
}

//Как было сказано выше - это событие генерируется для
//каждого файла, имя которого было указано в обработчике
//события OnGetSystemObjectNames. Порядок в списке
//файлов совпадает с порядком генерации события.
//Т.е., параметр SystemObjectIndex – это индекс в списке имен файлов
function grdDataOnGetSystemObjectData(DataGrid, SourceDataGrid, SelectedIDs, SystemObjectIndex, SystemObjectData) {
        if (!SelectedIDs) {
                return;
        }
       
        if (SystemObjectIndex >= SelectedIDs.Count) {
                return;
        }
        var RecordID = SelectedIDs(SystemObjectIndex);
        var Dataset = GetSingleItemByCode('ds_Files', 'SystemObjectsFileDetail');
        var FileDataDataField = Dataset.DataFields.ItemsByName('FileData');
        ApplyDatasetFilter(Dataset, 'ID', RecordID, true);
        EnableDatasetField(Dataset, FileDataDataField, true);
        Dataset.Open();
        //Из Blob поля мы просто сохраняем значение в поток SystemObjectData
        Dataset.DataFields.ItemsByName('FileData').GetValAsBlob(SystemObjectData);
        Dataset.Close();
}

Важно для разработчика:

  1. События OnGetSystemObjectNames, OnGetSystemObjectData и OnGetSystemObjectText начинают приходить только после того, как вы нажали Ctrl+V или отпустили кнопку мыши (при перетаскивании файлов) вне зависимости от того наше ли это приложение, или же стороннее
  2. События OnGetSystemObjectNames, OnGetSystemObjectData и OnGetSyestemObjectText в качестве параметра SelectedIDs принимают список IDs записей, которые действительно были скопированы (это важно). Этот список может не совпадать с DataGrid.SelectedIDs или SourceDataGrid.SelectedIDs. Связано это с тем, что вы можете переносить файлы, к примеру, с одного договора – в другой, и при этом DataGrid == SourceDataGrid (ведь это та же деталь), а при переходе на другую запись основного реестра применится фильтр для детали, и SourceDataGrid .SelectedIDs уже будет содержать совершенно другие значения
  3. В событие OnGetSystemObjectNames в качестве параметра SystemObjectNames приходит уже созданный IStringsList, Вам не нужно его создавать или же уничтожать – нужно только заполнить
  4. В событие OnGetSystemObjectData в качестве параметра SystemObjectData приходит уже созданный IStream. Вам достаточно просто записать в него значение. Создавать или уничтожать его также не нужно
  5. Событие OnGetSystemObjectText приходит только тогда, когда «приемник» не может принять файл(ы) (к примеру, при вставке в открытый документ Word). В нем можно указать текст, который необходимо вставить
  6. Вы можете пропустить копирование какого-либо файла. Для этого достаточно внести изменения в код обработчика OnGetSystemObjectData:
  7. //Чтобы отменить копирование файла не обязательно его
    //отсутствие в списке файлов, достаточно отменить его по индексу
    function grdDataOnGetSystemObjectData(DataGrid, SourceDataGrid, SelectedIDs, SystemObjectIndex,   SystemObjectData) {
            if (!SelectedIDs) {
                    return;
            }
           
            if (SystemObjectIndex >= SelectedIDs.Count) {
                    return;
            }
           //К примеру мне не хочется, чтобы пользователь
           //скопировал 2-й выбранный файл
           //Для этого достаточно выйти из функции, не
           //заполняя поток SystemObjectData
           If (SystemObjectIndex == 1) {
              return;
    }
  8. Перемещение между DataGrid внутри системы осуществляется разными способами, в зависимости от установленных свойств. Рассмотрим 2 случая:
    1. Перемещение по умолчанию
    2. Pic 4

    3. Копирование файла(ов)
    4. Pic 5

      При манипуляции комбинациями Ctrl+C/Ctrl+V все аналогично, только учитывается свойство CanPasteSystemObjects

    Собственно, это все, что я хотел рассказать о развитии Drag&Drop’а.

    Приятной работы!

    P.S. Вся функциональность доступна в версиях 3.4.0.99+ и 3.4.1.16+

Нравится

Поделиться

2 комментария

Подскажите, есть ли возможность обновиться с версии 3.3.2.310 до версии 3.4? Необходимо получить возможность перетягивания файлов из Террасофт в письмо MS Outlook.
С какими проблемами можно столкнуться при этом (совместимость конфигурации 3.3.2 с версией бинарных файлов 3.4, прочее)?

Андрей, обновление возможно. Как один из вариантов - развернуть 3.4 и перенести данные из 3.3.2 на уровне БД. Также, необходимо согласовать изменение лицензий с ответственным менеджером со стороны Terrasoft.

Показать все комментарии

В Terrasoft есть очень удобная функция - добавление файла на деталь путем перетаскивания из проводника. Чтобы добавлять ярлык на файл путем перетаскивания, нужны следующие изменения конфигурации:

1. Открыть скрипт scr_FilesDetailGridArea в Terrasoft Administrator (C:\Program Files\Terrasoft\Bin\TSAdmin.exe)
2. Найти в скрипте обработчик события function grdDataOnDragDropSystemObjects
3. Заменить в нем следующую строку

AddObject(ft_File, FileNames, 1, null);

На строки

if(GetControlKeysState().AltPressed == true){
        AddObject(ft_Link, FileNames, 1, null);                
}else                  
AddObject(ft_File, FileNames, 1, null);

4. Сохранить и закрыть.

Нравится

Поделиться

0 комментариев
Показать все комментарии

Подскажите, как можно отследить закрытие Вордовского файла открытого с детали Файлы раздела Документы (файл изначально находится в базе данных, при этом в открытый файл изменения не вносились).
Понадобилось это чтобы автоматизировать блокировку и разблокировку файлов при их открытии и соответственно закрытии.

Нравится

4 комментария

Ищите в этом направлении (на sdk):
IFileChangeNotifier
Пример есть в scr_FilesDetailGridArea.
Сам пока не трогал, т.к. не было подобных задач, посему больше не подскажу)

Юрий, добрый день.

Попробуйте изменить некоторые функции из scr_FilesDetailGridArea следующим образом:

function SetFileIsChanged(FileChangeNotifier, FileName, FileID) {
	var Dataset = FilesDetailGridArea.ChangedFilesDataset;
	if (IsCanSaveChangeFile(FileID)) {
		Dataset.Append();
		Dataset.ValAsGUID('ID') = FileID;
		Dataset.ValAsStr('Name') = FileName;
		Dataset.Post();
		RefreshGrid();
		if (ShowConfirmationDialog(DoYouWantToSaveChangedFileToDatabase) ==
				mrYes) {
			SaveFileInDataBase(FileID, FileName);
			UnlockFile();
			dlData.Dataset.RefreshRecord(FileID, false);
			Dataset.Delete();
			RefreshGrid();
		} else {
			UnlockFile();
		}
	}
}
 
function grdDataOnDblClick(Control) {
	if (amiOpen.IsEnabled){
		LockFile();
		EditObject(true);
	}
}
 
function amiSaveOnExecute(ActionMenuItem) {
	SaveToFile();
	UnlockFile();
}
 
function amiSaveChangedFilesOnExecute(ActionMenuItem) {
	SaveChangedFiles();
	UnlockFile();
}
 
function amiOpenOnExecute(ActionMenuItem, Sender) {
	LockFile();
	EditObject(false);
	UpdateButtons();
}

В присоединённом файле выделено красным, что именно нужно изменить.

Олег, рекомендованное решение корректно работает только если открытый файл изменялся, если его открыть, просмотреть и закрыть, то блокировка не снимается.

Юрий, дело в том, что на текущий момент нет возможности отследить момент завершения работы с файлом. У объекта, который связан с файлом, есть возможность подписаться на событие OnFileChange и OnFileDelete. Поэтому в решении момент сохранения файла в БД воспринимается как сигнал к разблокировке файла. Согласен, что в некоторых случаях это не совсем верно, но пока другой более подходящей возможности нет.

В следующих версиях Terrasoft уже запланирована возможность обработки и других событий файлов, поэтому вскоре эту задачу можно будет решить (только для MS Office).

Показать все комментарии

У версії 3.2.0.х в деталі "Файли" відсутній механізм  видалення файлу з групи. Для вирішення цієї проблеми потрібно додати відповідні пункти в меню видалення та в контексне меню в сервісі wnd_FilesDetailGridArea. А в сервіс scr_FilesDetailGridArea додати обробники подій на ці кнопки та функцію:

function CurrentGroupClear(){
        var Dataset = dlData.Dataset;
        var FileID = Dataset('ID');
        var FileGroupID = Self.Attributes('FileGroupID');
        var FilesDataset = GetSingleItemByCode('ds_FileInItem', 'CurrentGroupClear');
        FilesDataset.FetchRecordsCount = 1;
        ApplyDatasetFilter(FilesDataset, 'ID', FileID, true);
        FilesDataset.Open();
        if (!FilesDataset.IsEmptyPage) {
                FilesDataset.Edit();
                FilesDataset('FileGroupID') = null;
                FilesDataset.Post();
        }
        FilesDataset.Close();
       
        var UpdateQuery =
                GetSingleItemByCode('uq_UpdateFileGroup', 'CurrentGroupClear');
        UpdateQuery.ColumnsValues.ItemsByName('FileGroupID').Value = null;
        UpdateQuery.Parameters('OldFileGroupID').Value = FileGroupID;
        UpdateQuery.Parameters('NewFileGroupID').Value = null;
        try {
         UpdateQuery.Execute();
        }catch(e){
        }
        Dataset.Close();
        Dataset.Open();
}

Можна, звичайно, завантажити виправлені сервіси. Тоді майте на увазі, вони україномовні.

Автор цієї функції Артем Репко:cool::twisted:

Нравится

Поделиться

7 комментариев
        try {
         UpdateQuery.Execute();
        }catch(e){
        }

Вы "глушите" все исключения. Зачем?

Були не бажані. Інакше не глушив би :wink:. В Террасофт CRM іноді бувають виключення, які простіше заглушити ніж зрозуміти. Подивіться по конфігурації таких заглушок вистачає.

Ну тогда можно обернуть весь код функции, почему только Execute запроса? :smile:

Це вже на ваш смак :smile:

Ну просто интересно :smile:
Ошибки в Execute запроса на Update будут точно такими же как строчках чуть выше:

                FilesDataset.Edit();
                FilesDataset('FileGroupID') = null;
                FilesDataset.Post();

Почему там Вы не обернули в try..catch?

Теоретично, так. Олександр, виникла потреба поставити затичку. SQL-запит виконується успішно, а Execute() викликає помилку.

Те саме виникає при злитті знайдених зв'язків після перевірки на дублі.

Показать все комментарии

Существует ли возможность удаления файла, находящегося на локальном диске, из скрипта Terrasoft?

Нравится

2 комментария
function DeleteFile(filespec) {
var fso = new ActiveXObject(Scripting.FileSystemObject); fso.DeleteFile(filespec); 
}

Строки с факью для разработчиков
http://community.terrasoft.ua/developer/faq

Спасибо.

Показать все комментарии

Здравствуйте!

Предлагаю Вашему вниманию некоторую реализацаю возможности выгрузки фильтров динамической группы в файл (*.xml) и загрузки для другой динамической группы.

Подробная инструкция прикреплена.

Приятной работы!

Нравится

Поделиться

0 комментариев
Показать все комментарии

Если при создании отчета Word перед Вами стоит задача вставить в этот отчет картинку (изображение), хранящееся на закладке "Файлы" менеджера деталей записи, могу Вам предложить один из вариантов решения.

1. Прежде всего хочу обратить Ваше внимание на то, что рисунок из закладки "Файлы" менеджера деталей не получится поместить куда-либо без предварительной выгрузки его на диск. Поэтому для этого сперва необходимо использовать стандартную функцию LoadFileFromDatabase (ID, FileName, IsTemporary, WithNativeFileName),которая описана в скрипте scr_FileUtils.
2. Далее в момент создания отчета необходимо вызывать объект Word.
В свою очередь объект Word содержит Selection, который позволяет выполнять многие операции в том числе вставку картинки. Пример его использования для вставки картинки следующий:

Selection.InlineShapes.AddPicture ('имя файла картинки с указанием пути', false, true).

'Имя файла картинки с указанием пути' Вы получите в результате отработки LoadFileFromDatabase.
В результате изображение поместится в начало отчета Word.

Для того, чтобы изображение помещалось не в начало документа Word, а в любое другое место, можем посоветовать следующее:
1. Вставить с текст шаблона MS Word метку, например >.
2. Затем в скрипте реализовать примерно следующее:

if (Selection.Find('>')){
//вставка в то самое место, где найдена метка
}

Желаю удачи!

С уважением,
Мельникова Екатерина

Нравится

Поделиться

6 комментариев

Большое спасибо!

Тот же механизм надо использовать, если надо вставить в отчет Word поле "Описание" (которое Blob)?

В случае, если надо вставить в отчет Word поле "Описание", тогда можно для выгрузки воспользоваться функцией:

function LoadFileFromDataset(FileName, Dataset, DataFieldName) {                 
            var BlobField = Dataset.DataFields.ItemsByName(DataFieldName);
            BlobField.SaveToFile(FileName);
            return FileName;
}

А

Selection.InlineShapes.AddPicture ('имя файла картинки с указанием пути', false, true)

должно работать в принципе без изменений.

Желаю удачи!

Добавление в код строки с Selection.Find('<>') вызывает ошибку выполнения Microsoft JScript: "Объект не поддерживает это свойство или метод". В чем может быть дело?

"Еременко Надежда Валерьевна" написал:

Добавление в код строки с Selection.Find('<>') вызывает ошибку выполнения Microsoft JScript: "Объект не поддерживает это свойство или метод". В чем может быть дело?


Добрый день!
Надежда, какую версию Terrasoft Вы используете?

версия XRM 3.3.
Решить проблему удалось с помощью следующего кода:

Selection.Find.Text = "<>";
 
if (Selection.Find.Execute())
{
       //вставка в то самое место, где найдена метка
}
Показать все комментарии

При работе с приложением иногда возникает необходимость добавить файл на деталь менеджера деталей Файлы сразу в несколько разделов. Приведу пример. При добавлении файла на закладку менеджера деталей Файлы раздела Контрагенты, возникает необходимость добавить этот же файл на аналогичную закладку раздела Контакты для основного контакта контрагента. Для того, чтобы не размещать в приложении несколько одинаковых файлов и тем самым не увеличивать размер базы данных, можно файл размещать только на одну из закладок (например в разделе Контрагенты), а в другом разделе на закладке Файлы размещать ссылку на это файл (например в разделе Контакты). Для реализации вышеописанной функциональности необходимо изменить функцию function InsertFilesLink(FileID) из скрипта scr_FilesDetailGridArea. Внизу приведен код, который нужно отладить для того, чтобы он выполнял заданную функциональность

   function InsertFilesLink(FileID) {             var InsertQuery = FilesDetailGridArea.InsertQueryLink;             var ColumnsValues = InsertQuery.ColumnsValues;     ColumnsValues.ItemsByName('FileID').Value = FileID;     ColumnsValues.ItemsByName(BaseGridArea.ItemIDFieldName).Value =                         FilesDetailGridArea.ParentItemID;     var ID = Connector.GenGUID();     ColumnsValues.ItemsByName('ID').Value = ID;     InsertQuery.Execute();     if (BaseGridArea.ItemIDFieldName == 'AccountID') { //определяем, является ли деталь, деталью в контрагентах             if (!FilesDetailGridArea.ContactInsertQueryLink) {                         FilesDetailGridArea.ContactInsertQueryLink =                                                             Services.GetNewItemByUSI('iq_fileInContact');             }             var InsertQueryContact = FilesDetailGridArea.ContactInsertQueryLink;             var ColumnsValuesContact = InsertQueryContact.ColumnsValues;             ColumnsValuesContact .ItemsByName('FileID').Value = FileID;             var AccountID = FilesDetailGridArea.ParentItemID;             ColumnsValuesContact .ItemsByName('ContactID').Value = GetPrimaryContactByAccountID(AccountID);               var ID = Connector.GenGUID();             ColumnsValuesContact .ItemsByName('ID').Value = ID;             InsertQueryContact.Execute();     } }  

Для того, чтобы функция выполнялась корректно Вам необходимо создать функцию GetPrimaryContactByAccountID(AccountID), которая по заданному AccountID определит Оснойной контакт этого контрагента и отладить предоставленный нами код в отладчике скриптов. Аналогично может быть реализована подобная функциональность и в других разделах. С уважением, Коваленко Ирина

Нравится

Поделиться

1 комментарий