Доброго времени суток, коллеги!

Возникла хотелка сохранять файлы из соответствующей детали не поштучно, а кучей - все выделенные. Вариант https://community.terrasoft.ru/forum/topic/7719 не помог, видимо из-за разницы в платформах.
Как правильно реализовать на ServiceDesk 3.х?

Нравится

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

Должно работать на SD 3.x.
Почему у вас не получилось? Какие то ошибки? Предоставьте, пожалуйста, более подробную информацию.

Никаких ошибок, но и действий никаких не происходит. Оно должно отработать на Файлы - Операции - Сохранить в файл?

По идее да. Но нужно выделить через Ctrl несколько файлов на детали. Если будет выделен один - один и сохранится.

Выяснил, что не проходит проверка
if (Dat('ItemTypeID') != ft_File) {
continue;
}
и оно улетает на следующий круг цикла

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

Dat('ItemTypeID')

при сохранении именно файла, и если это значение не совпадает с ft_File - замените.

Не пойму, как заполучить Dat('ItemTypeID'). Инструкция Log.Write(1, Dat('ItemTypeID')) падает на ошибке типов

Какой у вас отладчик стоит?

Боюсь, что никакого, потому и ковыряю через запись в лог :-) Или что-то подтянулось при установке ServiceDesk, но не знаю как это запустить.

Есть возможность поставить Visual Studio? Думаю, все ровно пригодится, если будете дорабатывать конфигурацию в будущем.

Если поставите, то перед строкой
if (Dat('ItemTypeID') != ft_File) {

наберите

debugger;

и посмотрите что же все таки в Dat('ItemTypeID').

пс: перед этим не забудьте включить в реестре отладчик:

HKEY_CURRENT_USER\Software\Microsoft\Windows Script\Settings

JitDebug = 1

переустановил SreviceDesk с предлагаемыми дебаггерами. Теперь на точке "debugger;" открывается microsoft script debugger. Как в нём значение переменной посмотреть?

Здравствуйте.
Посмотрите, пожалуйста, рекомендации по использованию "debugger", перейдя по ссылке: file:///C:/Windows/help/debug/SDbug.htm

Александр, спасибо за подсказку!
Dat('ItemTypeID')=null после Dat.Open()!
Почему? IDs[i] не пуст и вполне реальный.

Андрей, Dataset.RecordsCount возвращает 1?
Если да - значит либо колонка как-то по другому называется, либо действительно у вас в колонке "Тип файла" пусто. Может вы их как-то нестандартно заливали?

пс: чтобы наверняка, выполните SELECT на сервере.

Что-то вроде (покажет все файлы для контрагента горсовет)

SELECT ItemTypeID from tbl_Files
where FileID in (select FileID from tbl_FileInAccount where AccountID in (select ID from tbl_Account where Name = 'ОАО Горсовет'))

А null там потому, что Dat открывается пустым. А пустой он потому, что в sq_FileInItem есть связка
INNER JOIN
[dbo].[tbl_FileInAccount] AS [FileInItem] ON [FileInItem].[FileID] = [tbl_Files].[ID]
На каком-то этапе [dbo].[tbl_FileInAccount] должно было подмениться на [dbo].[tbl_FileInIncident]?
Собственно, по тексту заменил
var Dat = Services.GetNewItemByUSI('ds_FileInItem');
на
var Dat = Services.GetNewItemByUSI('ds_FileInIncident');
И счастье получил. Но ведь это не правильно. При сохранении файлов из задачи или ещё откуда-то косяк будет.

Андрей, в более новых версиях уже есть массовое сохранение. Вот коробочная функция:

function SaveToFile(){
	var Dataset = FilesDetailGridArea.Dataset;
	var SelectedIDs = grdData.SelectedIDs;
	if (SelectedIDs.Count == 0) {
		return;
	}
	var Message;
	var InitialDir = EmptyStr;
	var FileName = System.CreateObject('TSObjectLibrary.Value');
	if (SelectedIDs.Count > 1) {
		var WindowCaption = "Сохранить файлы";
		var DirectoryName = System.CreateObject('TSObjectLibrary.Value');
		if (!(System.SelectDirectory(WindowCaption, InitialDir, 
			DirectoryName))) {
			return;	
		}
		var SavedFilesCount = 0;
		Dataset.DisableEvents();
		for (var i = 0; i < SelectedIDs.Count; i++) {
			var RecordID = SelectedIDs(i);
			Dataset.Locate('ID', RecordID);
			var FileType = GetFieldValueFromDisabledField(Dataset, 'ItemTypeID');
			FileName.Value =
				GetFieldValueFromDisabledField(Dataset, 'Link');
			if (!SaveToFileByFileType(Dataset, RecordID, FileName, 
				DirectoryName.Value, FileType)) {
				continue;
			}	
			SavedFilesCount++;
		}
		Dataset.EnableEvents();
		Message = FormatStr(FilesSavedMessage, SavedFilesCount, 
			SelectedIDs.Count);
		ShowInformationDialog(Message);
	} else {
		FileName.Value =
			GetFieldValueFromDisabledField(Dataset, 'Link');
		if (!SaveToFileByFileType(Dataset, FilesDetailGridArea.RecordID, 
			FileName, '', FilesDetailGridArea.FileType)) {
			return;
		}	
		if (FilesDetailGridArea.FileType != ft_File) {
			return;
		}
		Message = FormatStr(OpenFileForEditMessage,	FileName.Value);
		if (ShowConfirmationDialog(Message) == mrYes) {
			if (!OpenFileWithFullAccess(FileName.Value, true, ft_File)) {
				return;
			}
		}
	}
}
 
function SaveToFileByFileType(Dataset, RecordID, FileName, FilePath, FileType) {
	if (!FilePath) {
		FilePath = '';
	}	
	switch(FileType) {
		case ft_File:
			var FileExtension = '.' + ExtractFileExtension(FileName.Value);
			var FileFilterValue = '*' + FileExtension;
			FileFilterValue = FileFilterValue + '|' + FileFilterValue;
			var WindowCaption = "Сохранить файл";
			var InitialDir = EmptyStr;
			var IsSaving = true;
			if (FileName.Value == EmptyStr) {
				return false;
			}
			if (FilePath != '') {
				FileName.Value = FilePath + '\\' + FileName.Value;
			} else 
				if (!(System.PromptForFileName(FileName, 
					FileFilterValue, FileExtension,	WindowCaption, 
					InitialDir, IsSaving))) {
					return false;
				}
			var File = LoadFileFromDatabase(RecordID, 
				FileName.Value, false);	    
			if (!File) {
				return false;
			}
			break;
		case ft_Link:
		case ft_FolderLink:
			var FileExtension = 'lnk';
			var FileFilterValue = '*lnk';
			FileFilterValue = FileFilterValue + '|' + FileFilterValue;
			var WindowCaption = "Сохранить файл";
			var InitialDir = EmptyStr;
			var IsSaving = true;
			if (FileName.Value == EmptyStr) {
				return false;
			}
			var DestinationFileName = FileName.Value;
			FileName.Value = ExtractFileNameWithoutExtension(FileName.Value);
			if (FilePath != '') {
				FileName.Value += '.' + FileExtension;
				FileName.Value = FilePath + '\\' + FileName.Value;
			} else 
				if (!(System.PromptForFileName(FileName, 
					FileFilterValue, FileExtension,	WindowCaption, 
					InitialDir, IsSaving))) {
					return false;
				}
			var LinkCaption = ExtractFileNameWithoutExtension(FileName.Value);
			System.CreateFileLink(DestinationFileName, '', 
				LinkCaption, ExtractFilePath(FileName.Value));
			break;
		case ft_URL:
			var FileExtension = 'url';
			var FileFilterValue = '*url';
			FileFilterValue = FileFilterValue + '|' + FileFilterValue;
			var WindowCaption = "Сохранить файл";
			var InitialDir = EmptyStr;
			var IsSaving = true;
			if (FileName.Value == EmptyStr) {
				return false;
			}
			var URLPath = new String(FileName.Value);
			var Index = URLPath.indexOf('://') == -1 ? 0 : 
				URLPath.indexOf('://') + 3;
			var URLFileName = URLPath.substr(Index, URLPath.length);
			Index = URLFileName.indexOf('/') == -1 ? URLFileName.length : 
				URLFileName.indexOf('/');
			URLFileName = new String(URLFileName.substr(0, Index));
			FileName.Value = URLFileName;
			if (FilePath != '') {
				FileName.Value += '.' + FileExtension;
				FileName.Value = FilePath + '\\' + FileName.Value;
			} else 
				if (!(System.PromptForFileName(FileName, 
					FileFilterValue, FileExtension,	WindowCaption, 
					InitialDir, IsSaving))) {
					return false;
				}
			var URLFileStream = new ActiveXObject('ADODB.Stream');
			URLFileStream.Type = 2;
			URLFileStream.Mode = 3;
			URLFileStream.Open();
			URLFileStream.WriteText("[InternetShortcut]",1);
			URLFileStream.WriteText("URL=" + URLPath,1);
			URLFileStream.Position = 0;
			URLFileStream.SaveToFile(FileName.Value, 2);
			URLFileStream.Close();
			URLFileStream = null;	
			break;	
	}	
	return true;
}

Дмитрий, это был суперский вариант!
Не понятыми остались строки

                Message = FormatStr(FilesSavedMessage, SavedFilesCount, 
                        SelectedIDs.Count);
                ShowInformationDialog(Message);

на них вылетало в дебагер. Прикрыл эти строчки и всё работает!

В этих строках просто выводится сообщение пользователю сколько файлов сохранено. Можете заменить эти 2 строки на:

ShowInformationDialog('Операция завершена. Файлов сохранено: ' + SavedFilesCount);

Да, без завершающего окошка как-то скучно.
В общем, спасибо всем, вопрос изначальный можно считать решенным.
И всё-таки интересно, жесткая привязка tbl_FileInAccount в общей выборке sq_FileInItem - это ошибка, или так задумано?

Так задумано. Она действительно меняется "на лету" в зависимости от раздела, но в инструкции, на которую вы дали ссылку, этот момент не учтен.

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