Суть вопроса заключается в следующем.
Создан запрос:
Деталь 1 - Основная таблица Договор (одна запись, два поля)
Деталь 2 - Связная таблица Продукты в договоре (две записи, пять полей)
Рис.1. Вот что получается:
Рис.2. А вот как должно выглядить.
Вывод в ворд происходит в следующем порядке:
Сначала выводятся все записи одного поля, а не все поля одной записи как это логически должно быть...
Логика достигается выводом записей Продуктов договоров в таблице с одной строкой под каждый продукт, но это не приемлемо в нашем случае...
Вопрос: Есть ли возможность добиться результата как на Рис.2 без применения FastReport?
Нравится
Возможность есть, но придется попариться и вручную вставлять данные. Без изменения скриптов не обойтись.
"Агутин Алексей" написал:Возможность есть, но придется попариться и вручную вставлять данные. Без изменения скриптов не обойтись.
*с интересом потирая ладоши*
А не подскажите что менять? или хотя бы какие скрипты содержат необходимые функции? Дело в том что мне проще один раз помучится со скриптами чем потом всему отделу продаж объяснять что есть Фастрепорт...
---
Конфигурация:
TSCRM 3.3.1.59
Firebird 2.0 (v.2.0.3.12981)
"Швец Александр" написал:*с интересом потирая ладоши*
приятно слышать.
Менять придется scr_UserReportCommon. Необходимо переписать ProcessWordSelection таким образом, что когда выделение устанавливается на нужной Вам метке(проверить что это именно та метка можно с помощью GetExpressionObject(Selection.Text)) вызывается функция, которая будет вставлять данные в необходимом формате.
Будьте внимательны, так как Вам придется менять базовую функцию.
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); }
*спустя 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 Вы делаете
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); } }
В функции DoSomething(Selection) Вы прописываете операции по необходимому добавлению данных.
Спасибо, с метками более менее стало понятно...
"Агутин Алексей" написал:В функции DoSomething(Selection) Вы прописываете операции по необходимому добавлению данных.
По аналогии с базовыми функциями написал свою, но не могу понять как она отличается от оригинала...
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<DataFields.Count;i++) { if(ReplaceDots(DataFields.Items(i).Caption) == EO.FieldName) { DField = DataFields.Items(i); break; } Selection.Text = DField.Value; } }
Перебор идёт по датасету пока не будет найдено поле = ExpressionObject.DatafieldName, после чего получается Value.
Но где же перебор по записям при количестве записей > 1?
Пройдясь отладчиком по функциям отвечающим за вывод в ворд...определил что, скорее всего для решения моей задачи, нужно переписать функцию ProcessDetail, которая как раз и отвечает за вывод детали при количестве записей больше 1ой.
На данный момент вывод проходит так:
Выводится первая запись Datafield`a вместо метки <#Деталь1.П>
"BBA in Hotel, Restaurant and Resort Management"
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;
Потом выводится вторая запись DataField`a вместо той же метки <#Деталь1.П>
"Foundation (16 weeks)"
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; }
Для наглядности так же привожу шаблон отчёта:
Таблица(цы) "Программы обучения" должны отображать данные по каждой записи "Продукты в Договоре"...
Количество записей "Продукты в Договоре" должно соответствовать количеству
---
Конфигурация:
TSCRM 3.3.1.59
Firebird 2.0 (v.2.0.3.12981)