записей в MS Word
Многострочный вывод
Отчёты
Разработка

Многострочный вывод двух и более записей в MS Word

Суть вопроса заключается в следующем.

Создан запрос:
Деталь 1 - Основная таблица Договор (одна запись, два поля)
Деталь 2 - Связная таблица Продукты в договоре (две записи, пять полей)

Рис.1. Вот что получается:

Рис.2. А вот как должно выглядить.

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

Логика достигается выводом записей Продуктов договоров в таблице с одной строкой под каждый продукт, но это не приемлемо в нашем случае...

Вопрос
: Есть ли возможность добиться результата как на Рис.2 без применения FastReport?

Нравится

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

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

"Агутин Алексей" написал:Возможность есть, но придется попариться и вручную вставлять данные. Без изменения скриптов не обойтись.

*с интересом потирая ладоши*

А не подскажите что менять? или хотя бы какие скрипты содержат необходимые функции? Дело в том что мне проще один раз помучится со скриптами чем потом всему отделу продаж объяснять что есть Фастрепорт...

---
Конфигурация:
TSCRM 3.3.1.59
Firebird 2.0 (v.2.0.3.12981)

"Швец Александр" написал:*с интересом потирая ладоши*

приятно слышать.
Менять придется scr_UserReportCommon. Необходимо переписать ProcessWordSelection таким образом, что когда выделение устанавливается на нужной Вам метке(проверить что это именно та метка можно с помощью GetExpressionObject(Selection.Text)) вызывается функция, которая будет вставлять данные в необходимом формате.
Будьте внимательны, так как Вам придется менять базовую функцию.

[javascript]
function ProcessWordSelection(Selection, DocumentRange, RecordsCountObject, WorkspaceWindow) {
if (Selection.Tables.Count == 1) {
if (EvaluateDetailExpression(Selection, DocumentRange, RecordsCountObject, WorkspaceWindow)) {
ProcessWordSelection(Selection, DocumentRange, RecordsCountObject, WorkspaceWindow);
}
} else {
Selection.Text = EvaluateRootExpression(Selection);
}
}

function EvaluateRootExpression(Selection) {
var RootDataset = MSWordUserReport.RootDataset;
var ExpressionObject = GetExpressionObject(Selection.Text);
var Result = GetFieldValueByCaption(RootDataset, ExpressionObject.FieldName);
if (IsEmptyValue(Result)) {
Result = '';
}
return Result;
}

function EvaluateDetailExpression(Selection, DocumentRange, RecordsCountObject, WorkspaceWindow) {
if (IsRootSectionTag(Selection, MSWordUserReport.RootDataset.Caption)) {
Selection.Text = EvaluateRootExpression(Selection);
return false;
}
var ExpressionObject = GetExpressionObject(Selection.Text);
var DetailDataset = GetDetailDatasetByName(ExpressionObject.DatasetName);
if (!Assigned(DetailDataset)) {
return false;
}
if (DetailDataset.IsEmptyPage) {
var Table = Selection.Tables.Item(1);
var RowIndex = Selection.Rows.Item(1).Index;
if (DetailDataset.Attributes('IsSummaryEnabled')) {
if (Table.Rows.Count > RowIndex) {
Table.Rows(RowIndex + 1).Delete();
}
}
Table.Rows(RowIndex).Delete();
return false;
}
return ProcessDetail(Selection, DetailDataset, DocumentRange, RecordsCountObject, WorkspaceWindow);
}
[/javascript]
*спустя 3 часа размышлений оптимизм стал угасать*

"Агутин Алексей" написал:когда выделение устанавливается на нужной Вам метке(проверить что это именно та метка можно с помощью GetExpressionObject(Selection.Text)) вызывается функция, которая будет вставлять данные в необходимом формате.

Не могу понять как это практически реализовать...
Точнее что есть ExpressionObject? В SDK не нашёл...
По примеру выше вижу свойства DatasetName и DatafieldName.
Но что тогда должна содержать GetExpressionObject(Selection.Text)?

---
Конфигурация:
TSCRM 3.3.1.59
Firebird 2.0 (v.2.0.3.12981)

Как Вы правильно заметили, ExpressionObject - это объект у которого есть всего два поля DatasetName и DatafieldName. Таким образом Вы в тексте делаете метку вида <#MyLabel.First> (конкретный вид метки зависит от версии). Далее в ProcessWordSelection Вы делаете
[javascript]
function ProcessWordSelection(Selection, DocumentRange, RecordsCountObject, WorkspaceWindow) {
if (Selection.Tables.Count == 1) {
var TextLabel = GetExpressionObject(Selection.Text);
if (TextLabel.DatasetName == 'MyLabel'&&TextLabel.DatafieldName == 'First'){
DoSomething(Selection);
return;
}
if (EvaluateDetailExpression(Selection, DocumentRange, RecordsCountObject, WorkspaceWindow)) {
ProcessWordSelection(Selection, DocumentRange, RecordsCountObject, WorkspaceWindow);
}
} else {
Selection.Text = EvaluateRootExpression(Selection);
}
}

[/javascript]
В функции DoSomething(Selection) Вы прописываете операции по необходимому добавлению данных.

Спасибо, с метками более менее стало понятно...

"Агутин Алексей" написал:В функции DoSomething(Selection) Вы прописываете операции по необходимому добавлению данных.

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

[javascript]
function DoSomething(Selection){
var EO = GetExpressionObject(Selection.Text);
var RootDataset = MSWordUserReport.RootDataset
try {
if (Dataset.State == dstInactive) {
return null;
}
var DataFields = RootDataset.DataFields;
var DField = null;
for (var i=0;i 1?

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

На данный момент вывод проходит так:
Выводится первая запись Datafield`a вместо метки <#Деталь1.П>
"BBA in Hotel, Restaurant and Resort Management"
[javascript]
Dataset.GotoFirst();
var RowCount = Dataset.PageRecordsCount;
PrepareDetailTable(Selection, RowCount);
var StartIndex = Selection.Rows.Item(1).Index;
var EndIndex = StartIndex + RowCount - 1;
var NewIndex = StartIndex;
var Table = Selection.Tables.Item(1);
Table.ID = 'Proceed';
var DataField = GetDataFieldFromTag(Selection, Dataset);
debugger;
if (Assigned(DataField)) {
var FieldValue = GetDataFieldValueByFieldType(DataField);
if (IsEmptyValue(FieldValue)) {
FieldValue = '';
}
Selection.Text = FieldValue;
[/javascript]

Потом выводится вторая запись DataField`a вместо той же метки <#Деталь1.П>
"Foundation (16 weeks)"
[javascript]
while (DocumentRange.Find.Execute()) {
DocumentRange.Select();
if (Selection.Tables.Count == 0) {
return true;
}
if (Selection.Tables.Item(1).ID != 'Proceed') {
return true;
}
if (Selection.Rows.Item(1).Index > EndIndex) {
break;
}
if (Selection.Rows.Item(1).Index > NewIndex) {
Dataset.GotoNext();
RecordsCountObject.ChildRecordNumber++;
if (RecordsCountObject.ChildRecordNumber % 3 == 0) {
UpdateProcessPosition(RecordsCountObject, WorkspaceWindow);
if (RecordsCountObject.CancelledByUser) {
return false;
}
}
NewIndex = Selection.Rows.Item(1).Index;
debugger;
}
DataField = GetDataFieldFromTag(Selection, Dataset);
if (Assigned(DataField)) {
var FieldValue = GetDataFieldValueByFieldType(DataField);
if (IsEmptyValue(FieldValue)) {
FieldValue = '';
}
Selection.Text = FieldValue;
debugger;
}
[/javascript]

Для наглядности так же привожу шаблон отчёта:

Таблица(цы) "Программы обучения" должны отображать данные по каждой записи "Продукты в Договоре"...

Количество записей "Продукты в Договоре" должно соответствовать количеству

---
Конфигурация:
TSCRM 3.3.1.59
Firebird 2.0 (v.2.0.3.12981)

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