При построении пользовательского отчета MS Word с использованием детали - эта деталь отображается в самом отчете в виде таблицы. В некоторых отчетах это отображение не совсем удобно, особенно в тех случаях, когда необходимо отображение в виде списка.

Могу предложить скрыть рамки таблицы деталей следующим образом:
в скрипте scr_UseReportCommon после строки
var Table = Selection.Tables.Item(1); прописать следующее:

 
 for (var i = 1; i 8; i++) {
  Table.Borders(-i).LineStyle = 0;
 }
 Table.Borders.Shadow = false;

В результате при построении отчетов, рамки таблиц будут невидимы.

Желаю удачи!

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

 

Нравится

Поделиться

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

У меня строка

var Table = Selection.Tables.Item(1)

встречается дважды. В EvaluateDetailExpression и ProcessDetail. В каком именно месте нужно цикл добавить?

P.S. Писать

Table.Borders(-i).LineStyle = 0;

не очень хорошо. Чтобы облегчить жизнь тому кто придет после нас лучше писать

var wdLineStyleNone = 0;
Table.Borders(-i).LineStyle = wdLineStyleNone;

Кстати вот список стилей линий, может кому сгодится

wdLineStyleDashDot = 5
wdLineStyleDashDotDot = 6
wdLineStyleDashDotStroked = 20
wdLineStyleDashLargeGap = 4
wdLineStyleDashSmallGap = 3
wdLineStyleDot = 2
wdLineStyleDouble = 7
wdLineStyleDoubleWavy = 19
wdLineStyleEmboss3D = 21
wdLineStyleEngrave3D = 22
wdLineStyleInset = 24
wdLineStyleNone = 0
wdLineStyleOutset = 23
wdLineStyleSingle = 1
wdLineStyleSingleWavy = 18
wdLineStyleThickThinLargeGap = 16
wdLineStyleThickThinMedGap = 13
wdLineStyleThickThinSmallGap = 10
wdLineStyleThinThickLargeGap = 15
wdLineStyleThinThickMedGap = 12
wdLineStyleThinThickSmallGap = 9
wdLineStyleThinThickThinLargeGap = 17
wdLineStyleThinThickThinMedGap = 14
wdLineStyleThinThickThinSmallGap = 11
wdLineStyleTriple = 8

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

Добрый день!

Не подскажете простой метод вызова вордовского отчета из скрипта?
Я пытаюсь использовать функцию
ProcessPrepareWordReport
указав в ней ID записи, для которой нужно сформировать отчет.
Дело в том, что отчет вызывается по нажатию на кнопку прямо на карточке редактирования записи. Реестр находится в детали, раздела нет. А отчет привязан к родительскому разделу. Поэтому при использовании вышеуказанной функции фильтр по ID применяется на датасете раздела,а не детали. В общем, после всех поисков, выянилось, что придется писать функцию и довольно большую.

Есть ли варианты попроще???

Заранее благодарю.

Нравится

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

Здравствуйте!
Позвольте предоставлю Вам пример реализации необходимого Вам функционала в прикрепленном файле. В нем высылаю Вам скрипт необходимой функции с комментариями и пояснениями, пример шаблона отчета Word.
Я надеюсь, этот пример поможет Вам разобраться с реализацией поставленной задачи и по аналогии с этим примером Вам удасться это сделать.

Желаю удачи!

Мельникова Екатерина

Спасибо за пример.
Попробую разобраться :)

Добрый день,

с вызовом отчета все ясно.
теперь возникли вопросы по заполнению таблицы в этом отчете.
Поясните, пожалуйста, как заполнить таблицу с известным количеством столбцов и динамическим количествыом строк?
В примере разобраться с этим заполнением не удалось :(

Заранее спасибо!!!

Здравствуйте!
Для реализации необходимого Вам функционала вызова отчета Word из скрипта могу предложить следующий пример:

function Main() {
    //Создаем объект WORD и открываем шаблон
    var FileName = 'c:\\rep_test.doc';
       var Word = new ActiveXObject('Word.Application');
       Word.Documents.Open(FileName);
       var Selection = Word.Selection;
 
       //Находим метку, которая содержится в таблице и определяем сколько вставить строчек
       var RowsToInsert = 10; //В данном случае вставляем 10 строчек (это может быть кол-во записией датасета)
       if (Selection.Find.Execute('<<NumberMark>>')) {
        if (Selection.Tables.Count > 0) {
            //Если условие выполнилось - то Selection есть таблица. И вставляем строчки в нее
            Selection.InsertRowsBelow(RowsToInsert - 1);
            var Table = Selection.Tables(1);
            //Перебираем все строчки начиная со второй (1-я это заголовок)
            for (var i = 2; i <= Table.Rows.Count; i++) {
                Table.Columns(1).Cells(i).Range.Text = 'Левая колонка';        
                Table.Columns(2).Cells(i).Range.Text = 'Правая колонка';
            }            
        }
    }    
       Word.Visible = true;
}

Надеюсь, это Вам поможет разобраться с поставленной задачей.

Желаю удачи!

Мельникова Екатерина

Добрый день, Екатерина.
У меня схожая проблема.

Возникло несколько вопросов:
1. В скрипте, что вы здесь выложили есть строчка

WordRecord = OpenWordTemplate('rep_test');//<<--------Введите название!!!	

Здесь имеется ввиду название отчета Word, которое присутствует в разделе Инструменты->Отчеты?

2. Мой отчет в формате Word должен заполняться данными из грида на основе MemoryDataset, т.о. отчет не будет привязан к запросу.
Как мне создать такой отчет в системе? Ведь при создании отчета поле с указанием запроса обязательно.

"Мельникова Екатерина" написал:
var FileName = 'c:\\rep_test.doc';
var Word = new ActiveXObject('Word.Application');
Word.Documents.Open(FileName);

В этом коде указан 'c:\\rep_test.doc' в качестве пути к файлу. Где храниться этот файл? На локальной машине, где происходит разработка, или на сервере?
Мне необходимо, чтобы сотрудник с любого компьютера в локальной сети смог сформировать данный очет.

Здравствуйте, Валерия. Отвечу по порядку на Ваши вопросы.

1) В строке

OpenWordTemplate('rep_test')

действительно нужно указать название отчета Word.

2) Что касается отчета на основе MemoryDataset, то могу Вам сообщить, что построение подобного отчета будет очень трудоемкой задачей. Это связано с тем, что отчет пользовательский и поле с указанием запроса обязательно. Уточните, насколько критичной является задача реализации отчета на основе MemoryDataset. Возможно, будет проще реализовать отчет на основе простого Dataset.

3) Строка

var FileName = 'c:\\rep_test.doc';

была приведена исключительно в качестве примера.
Если необходимо хранить файл на сервере, то в этой строке нужно прописать сетевой путь.
Файл также может храниться в разделе "Библиотека" приложения Terrasoft CRM (или каком-либо другом разделе). В этом случае нужно прописать функцию, которая этот файл "считает" (функцию Вы сможете найти в скрипте конфигурации scr_FileUtils).

Желаю удачи!

Екатерина, дело в том, что в моей задаче MemoryDataset должен формироваться пользователем и хранить их не нужно.
Он выбирает несколько строк из окна справочника, эти данные записываются в грид на основе MemoryDataset, а затем на основе их должен формироваться отчет в формате Word.

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

1. Создать шаблон документа Word точно также, как для пользовательского запроса, т.е. с указанием меток в формате Датасет.Название_поля, где необходимо заполнение данных. Затем загрузить этот отчет в библиотеку. Потом в момент, когда необходимо поднять отчет, создавать объект Word, загрузить в него необходимый шаблон, и при работе с отчетом, т.е. заполнение данных, использовать MemoryDataset точно также как и стандартный Датасет.

2.
Создать временную таблицу, указать в этой таблице какое-нибудь уникальное поле, типа Owner или номер сессии, в момент заполнения MemoryDataset заполнять и временную таблицу. На основании этой таблицы построить пользовательский запрос, а по нему пользовательский отчет, только наложить фильтр по уникальному полю, т.к. есть возможность, что больше чем один пользователь будет строить отчет в одно и тоже время. И не забывать очищать таблицу, после работы с отчетом.

Желаю удачи!

Спасибо, сейчас работаю над первым вариантом.

Екатерина, спасибо за полезный код.
Заметил одну проблемку: когда открыт Word перед моими глазами и я пытаюсь в невидимом режиме сделать замену меток в другом документе, то выскакивают диалоговые окна, которые просят о подтверждении замены.
Как это можно обойти, кто-то знает?

Пожалуйста, уточните, данное сообщение появляется при вызове отчета MS Word из Terrasoft или при обычной работе с MS Word?

"Гук Елена" написал:Пожалуйста, уточните, данное сообщение появляется при вызове отчета MS Word из Terrasoft или при обычной работе с MS Word?

Вот так я работаю с MS Word - через скрипт.

// Функция выполняет замену текста strFrom на текст strTo
function WordReplaceMark(Selection, strFrom, strTo){
   Selection.Find.Execute(strFrom, false, false, false, false, false, true, 0,
      false, strTo, 2);
}
 
function Main() {
   var FileName = ''; // Путь к документу на компьютере пользователя
   var WordObject = GetWordObject();
   WordObject.Documents.Add(FileName);
   var Selection = WordObject.Selection;
   Selection.WholeStory();
   // Проставляем город, в котором формируется документ
   var City = 'г. Харьков';
   WordReplaceMark(Selection, '<<City>>', City);
   WordObject.Documents.Item(1).SaveAs(WordRecord.FileName);
   WordObject.Documents.Item(1).Close(true);	
   WordObject.Quit(true);
}

ПС: не пойму почему у меня нет прав на просмотр собственноручно добавленного файла постом выше - 1.jpg

"Кошкаров Андрей" написал:ПС: не пойму почему у меня нет прав на просмотр собственноручно добавленного файла постом выше - 1.jpg

Андрей попробуйте сейчас.

"Maxim Alynkin" написал:Андрей попробуйте сейчас.

Спасибо, теперь я вижу картинку :)

Андрей, сообщение не будет появляться, если Вы немного измените Вашу функцию WordReplaceMark: вместо первой двойки вставите 0. Этот параметр (Wrap) отвечает за действие, которое выполняется при достижении границы документа во время поиска: 0 - не продолжать поиск; 1 - начать поиск с начала (конца) документа; 2 - спросить пользователя.

В итоге, функция будет выглядеть так:

function WordReplaceMark(Selection, strFrom, strTo){
   Selection.Find.Execute(strFrom, false, false, false, false, false, true, 0,
      false, strTo, 2);
}

"Лабьяк Олег Игоревич" написал:Андрей, сообщение не будет появляться, если Вы немного измените Вашу функцию WordReplaceMark: вместо первой двойки вставите 0.

Спасибо, Олег. Вы как всегда выручаете дельным советом. :twisted:
Подправил соответсвенно выше выложенную мной функцию.

Добрый день!

Не могли бы объяснить в данной функции
где ищется шаблон, что это за датасет ds_Library, через запросы смотрел в нем нет информации
Я так понял что в этой библиотеке должны быть шаблоны отчетов word?

function FindFileInfoInLibraryByCode(Code) {
var LibraryID = GetDatasetIDByFieldValue('ds_Library', 'Code', Code);
var Dataset = Services.GetNewItemByUSI('ds_FileInLibrary');
ApplyDatasetFilter(Dataset, 'LibraryID', LibraryID, true);
Dataset.Open();
var FileInfo = new Object();
FileInfo.FileID = Dataset.ValAsStr('ID');
FileInfo.FileName = Dataset.ValAsStr('Link');
Dataset.Close();
return FileInfo;
}

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

ds_Library - это датасет раздела "Библиотека".
В примере, видимо, в библиотеку был добавлен шаблон и далее од туда забирается ссылка на файл шаблона.

С этим разобрался всё получилось, по нажатию кнопки печать из карточки договора печатается нужный договор.

Вопрос.

Можно ли сделать отчет fast report c тем же датасетом и запросом, который я уже имею и выводить отчет не из карточки договора а как стандартный fast report (т.е. подключить через отчеты) и в момент формирования перехватить его, произвести нужные расчеты и вывести шаблон word заранее сохраненный в библиотеке?

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

Не совсем понимаю что Вы понимаете под "произвести нужные расчеты", но перехватить отчет можно на функции function ShowReport(Report, FilterForm).
Там же, после нужных Вам расчетов, тем же самым способом, можно вывести и Word отчет по шаблону из библиотеки.

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

Установил debugger в функции ShowReport(Report, FilterForm)

Формирую отчет с типом фильтрации для выделенных записей, точка остановы не срабатывает.
Срабатывает только при вызове отчета с фильтрацией для всех записей и вызове формы фильтрации.

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

Пользовательские отчеты строятся на основании пользовательских запросов. При построении такого запроса выбирается основная таблица, и далее, через связи, можно вытянуть не только информацию с полей данной таблицы, но и любые другие поля, связанные с этой таблицей. К примеру если выбрать основную таблицу "Контрагенты", можно также вытянуть информацию о счетах, продажах контрагента и т.д.

По поводу момента, когда строится отчет Fast Report - Вы правы. В зависимости от типа, мы можем "поймать" этот момент как в функции function ShowSingleRecordReport(ReportCode, FilteredDatasetCode, GridDatasetID, FilterName) так и в function ShowSelectedRecordsReport(ReportCode, FilteredDatasetCode, GridDatasetIDs, FilterForm) скрипта scr_ReportUtils.

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

Да, да, извиняюсь, несколько таблиц можно!
А вот можно ли вывести сумму прописью? Используя AmountToStr() ?

И как поймать вывод отчета при использовании отчета с типом фильтрации для всех записей?
Для выделенных записей, стабильно при отладки проваливается в функцию ShowSelectedRecordsReport()
А вот при "для всех записей" игнорирует функцию ShowSingleRecordReport(), debugger там точно установлен, попадет лишь в ShowReport().

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

По поводу суммы прописью в отчете Word почитайте здесь.

Функция

function ShowReport(Report, FilterForm) {
	var PreviewWindow = Services.GetNewItemByUSI(BaseFastReportPreviewWindowUSI);
	SetAttribute(PreviewWindow, 'Report', Report);
	if (Assigned(FilterForm)) {
		SetAttribute(PreviewWindow, 'FilterForm', FilterForm);
	}
	SetAttribute(PreviewWindow, 'ShowFilterForm', true);
 
	SetLocalizbleAttributes(Report);
 
 
	PreviewWindow.Build();
	PreviewWindow.Prepare();
}

это и есть та самая функция, которая строит отчет по всем записям.

Я читал эту тему, по её содержанию сделал вывод, что в word сумму прописью не получить без программного обработки.
По поводу функции для всех записей, понял, буду сегодня разбираться...
И для полного счастья)))), поясните для чего тогда служит функция ShowSingleRecordReport()

Здравствуйте, Ринат.

Данная функция используется в разделе "Опросы" для отображения результатов ответов какого либо контакта по опросу:

function ShowInterviewResultReport(Attributes) {
	var ReportDataset = GetSingleItemByCode('ds_Report', 'ReportInterviewResult');
	var Columns = ReportDataset.SelectQuery.Items(0).Columns;
	DisableAllColumns(Columns);
	var FieldNames = ['Code', 'FilteredDatasetCode']; 
	EnableColumnsByArray(Columns, true, FieldNames);
	ApplyDatasetIDFilter(ReportDataset, riInterviewResult, true);
	ReportDataset.Open();
	try {
		if (IsDatasetEmpty(ReportDataset)) {
			return;
		}
		var ReportUSICode = ReportDataset.Values('Code');
		var FilteredDatasetCode = ReportDataset.Values('FilteredDatasetCode');
		var Report = Services.GetNewItemByUSI(ReportUSICode);
		if (!Attributes) {
			var Attributes = GetNewDictionary();
		}
		ShowSingleRecordReport(ReportUSICode, FilteredDatasetCode, 
			Attributes('InterviewID'), 'InterviewID');
	} finally {
		ReportDataset.Close();
	}
}

Спасибо будем знать!

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

Если при создании отчета 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())
{
       //вставка в то самое место, где найдена метка
}
Показать все комментарии

Добрий день, Уважаемые!
Предлагаю Вам решение, реализующее печать нескольких копий документов Word без их визуального открытия. В качестве параметров функция получает полный путь к файлу и количество копий документа.

/* Печать документов */
function PrintDocuments(FileName, Count) {
try {
System.BeginProcessing();
System.ProcessMessages();
var Word = new ActiveXObject("Word.Application");
var Doc = Word.Documents.Open(FileName);
var IsError = false;
try {
Word.PrintOut(false, false, 0, "", "", "", 0, Count);
} catch(e) {
Log.Write(e.description);
IsError = true;
}
Word.Quit();
} finally {
System.EndProcessing();
}
if (!IsError) {
ShowInformationDialog("Документ успешно распечатан.");
} else {
ShowInformationDialog("При печати документа возникли ошибки.");
}
}

/* Пример использования: */
function Main() {
var Path = Connector.WorkingDirectory;
var FileName = Path + "\Test.doc";
PrintDocuments(FileName, 2);
}

Пока все. :)

Нравится

Поделиться

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