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

  • колонка - соотв колонка в запросе (AccID - AccID)
  • источник - для каждого id свой источник (например для AccID - dsAccID)
  • поля для отображения в большинстве случаев не заданы, но если их задавать - ничего не меняется (например для AccID - AccName)

На форме я создал LookupDataControl-ы, в DataLink поставил датасет моего запроса, а у каждого LookupDataControl-а поставил соответствующее DataFieldName из датасета.

В итоге я получил форму с неактивными серыми полями фильтрации.

В результате хотел получить форму, которая фильтрует мой запрос в соответствии с параметрами и работает при наличии незаполненных LookupDataControl-ов.

Подскажите что я делаю не так?
v.3.3.2

*на всякий случай прикрепил сервисы

Нравится

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

** сначала я использовал LookupControl и в коде присваивал фильтру его значение. Но при этом если оставить поле пустым, то запрос не сработает.

function btnOKOnClick(Control) {
...
 
	var AccountID = edtAccount.Value;
    var StartDate = PeriodDataset('DateFrom');
	var FinishDate = PeriodDataset('DateTo');
 
	// parameters for report
	ReportPreviewer.Report.Attributes('fromDate') = StartDate;
	ReportPreviewer.Report.Attributes('toDate') = FinishDate;
 
    dsReport.SelectQuery.Parameters.ItemsByName('AccountID').Value = AccountID;
    dsReport.SelectQuery.Parameters.ItemsByName('DateBegin').Value = StartDate;
    dsReport.SelectQuery.Parameters.ItemsByName('DateEnd').Value = FinishDate; 
 
...
    SendNotify(Self, MSG_OK); 
    Self.Close(); 

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

Это было бы слишком легко ) - датасет установлен и у полей можно выбирать справочники. Я попробовал поставить в поле справочника датасета галочку - отображать выпадающим списком, список так же серый, однако видно что данные в нем те что нужно, только выбрать их нельзя.

Может быть я не правильно подхожу к вопросу:
Могу ли я в принципе использовать связку LookupDataControl и поля фильтрации датасета для реализации моей задачи? Либо мне нужно использовать LookupControl?
Правильно ли я сконструировал сервисы моего отчета (как я описал в 1 посте).

По общей логике Вы все сделали правильно.
Только нужно атрибуты присваивать отчету в формате ReportPreviewer.Report.Attributes('...') = ..., т.е. не получать отчет через USI, а брать его из ReportPreviewer.
Далее, по полям. Указанные симптомы проявляются, если возникла ошибка при открытии датасета. В присланных сервисах в датасете ds_SalesByCorporateClients для большинства полей справочника у Вас не прописано поле для отображение. Да их и нет, они не вытягиваются через запрос на выборку sq_SalesByCorporateClients. Вам нужно в sq_ сделать присоединения (join) по таблицам, которые содержат информацию по полям справочника и вытянуть еще по колонке с отображаемым полем для каждого поля ID. Например, для AccountTypeID нужно присоединить таблицу tbl_AccountType и из нее вытянуть Name, дав этой колонке алиас AccountTypeName, затем это поле указать, как поле для отображения в поле AccountTypeID датасета.
Думаю, это решение текущей проблемы.

по атрибутам - я же вроде так и делал:
ReportPreviewer.Report.Attributes('fromDate') = StartDate;
ReportPreviewer.Report.Attributes('toDate') = FinishDate;

по полям:
Я пытался выставить поля для отображения но столкнулся с проблемой - в главной таблице есть несколько внешних ключей из одной таблицы. Меня это как то сбило с толку, подумал что так быть не должно. Как решить такую проблему?

Если быть точнее - то поля TransporterID OwnerID AccountID таблицы Doc - все явл внешними полями для Acc, я теряюсь как правильно составлять запрос.

Пример в запросе:
Поле с псевдонимом TransporterID должно быть Doc.TransporterID
поле с псевдонимом TransporterName дожно быть Acc.Name но веть еще есть OwnerID AccountID, очевидно что моя проблема в недопонимании такого типа фильтрации, но все же проблема есть ...

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

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

прикрепляю сервисы, надеюсь на подсказку.

На этот раз с запросом и датасетом вроде все в порядке. Говорю "вроде", потому что тех полей, которых нет в базовых таблицах, я все же не вижу в запросе на выборку, одни пустые поля. Так же не вижу и небазовые датасеты и таблицы, добавленные Вами. Остается только догадываться. Идеальным вариантом было бы Ваше письмо на support и возможность предоставить резервную копию базы, чтобы можно было протестировать, в чем же именно ошибка. Возможно я уже спрашивал и Вы ответили, что не можете предоставить копию. В таком случае необходимы тексты sql-запросов для создания всех таблиц, которых нет в базовой версии. Выполнив их я создам такую же структуру базы. Желательны (но не обязательны, можно и наполнить) также дампы данных из этих таблиц и из новых справочников. Таким образом я смогу повторить структуру Вашей базы хотя бы в части возникновения ошибки. Рекомендую перейти к решению проблемы в режиме e-mail, так как проблема является индивидуальной, общие рекомендации уже были даны, а конкретное ее решение регламентами как раз и предусмотрено проводить в режиме переписки.

как вариант - если у вас есть возможность контакта с Константином Пихало (а на сколько я знаю, вы трудитесь в 1 здании), то я думаю будет легче взять у него базу для нашей компании (уральские авиалинии)). Получится ли?

И еще 1 фундаментальный вопрос - зачем нужны пользовательские фильтры в запросах и как их юзать?

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

Спасибо за материал по пользовательским фильтрам.

Насчет решения задачи в режиме e-mail - я вас поддерживаю, так будет гораздо проще.
Вашей почты я не знаю, вот моя рабочая: v.kaukin@uralairlines.ru.

Вопрос остается пока не решенным.

Пока что я выбрал альтернативный путь решения этой задачи, написав код примерно следующего содержания.
Использовал LookupControl-ы. Если подскажите в чем же всетаки проблема, буду признателен :)

function btnOKOnClick(Control) {
//debugger;
	var Report = Services.GetNewItemByUSI('fr_SalesByCorporateClients');
    var ReportPreviewer = Self.Attributes('ReportPreviewer');
    var dsReport = ReportPreviewer.DatasetByUSI('ds_SalesByCorporateClients');
    var dsReport1 = ReportPreviewer.DatasetByUSI('ds_SalesByCorporateClientsNew'); 
 
    // verification
    var PeriodDataset = dlData.Dataset;
	if (IsEmptyValue(PeriodDataset('DateFrom')) || 
		IsEmptyValue(PeriodDataset('DateTo'))) 
	{
		ShowWarningDialog("Поля 'Дата с' и 'Дата по' являются обязательными для заполнения");
		return false;
	}
 
    // get vals of edits
    var AccountID = edtCustomer.Value;
    var DocumentTypeID = edtDocumentType.Value;
    var OfferingID = edtOffering.Value;
    var TransporterID = edtTransporter.Value;
    var CityFromID = edtCityFrom.    
    var CityToID = edtCityTo.Value;
    var ServiceClassID = edtServiceClass.Value;	
    var OwnerID = edtOwner.Value;
    var DateBegin = PeriodDataset('DateFrom');
    var DateEnd = PeriodDataset('DateTo');
 
    // parameters for fastreport
    ReportPreviewer.Report.Attributes('fromDate') = DateBegin;
    ReportPreviewer.Report.Attributes('toDate') = DateEnd;
 
//#1   
    ApplyDatasetFilter(dsReport,'AccountID', AccountID, !IsEmptyValue(AccountID)); 
    ApplyDatasetFilter(dsReport,'DocumentTypeID', DocumentTypeID, !IsEmptyValue(DocumentTypeID)); 
    ApplyDatasetFilter(dsReport,'OfferingID', OfferingID, !IsEmptyValue(OfferingID)); 
    ApplyDatasetFilter(dsReport,'TransporterID', TransporterID, !IsEmptyValue(TransporterID)); 
    ApplyDatasetFilter(dsReport,'CityFromID', CityFromID, !IsEmptyValue(CityFromID)); 
    ApplyDatasetFilter(dsReport,'CityToID', CityToID, !IsEmptyValue(CityToID)); 
    ApplyDatasetFilter(dsReport,'ServiceClassID', ServiceClassID, !IsEmptyValue(ServiceClassID)); 
    ApplyDatasetFilter(dsReport,'OwnerID', OwnerID, !IsEmptyValue(OwnerID)); 
    ApplyDatasetFilter(dsReport,'DateBegin', DateBegin, !IsEmptyValue(DateBegin)); 
    ApplyDatasetFilter(dsReport,'DateEnd', DateEnd, !IsEmptyValue(DateEnd));    
 
//#2
    dsReport1.SelectQuery.Parameters.ItemsByName('AccountID').Value = AccountID;
    dsReport1.SelectQuery.Parameters.ItemsByName('DateBegin').Value = DateBegin;
    dsReport1.SelectQuery.Parameters.ItemsByName('DateEnd').Value = DateEnd;
 
    // close window
    SendNotify(Self, MSG_OK); // Посылка сообщения необходима для старта показа окна отчета
    Self.Close(); // Закрываем окно фильтрации - оно больше не нужно        
}

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

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