Создал отчет FR со своей формой.
Необходимо отфильтровать запрос по множеству параметров, для этого я создал запрос с парами - параметр id : одноименный фильтр сравнения.
Далее в датасете для для всех указанных пар я создал поля типа "Справочник" и задал им соответствующие значения:
- колонка - соотв колонка в запросе (AccID - AccID)
- источник - для каждого id свой источник (например для AccID - dsAccID)
- поля для отображения в большинстве случаев не заданы, но если их задавать - ничего не меняется (например для AccID - AccName)
На форме я создал LookupDataControl-ы, в DataLink поставил датасет моего запроса, а у каждого LookupDataControl-а поставил соответствующее DataFieldName из датасета.
В итоге я получил форму с неактивными серыми полями фильтрации.
В результате хотел получить форму, которая фильтрует мой запрос в соответствии с параметрами и работает при наличии незаполненных LookupDataControl-ов.
Подскажите что я делаю не так?
v.3.3.2
*на всякий случай прикрепил сервисы
Нравится
** сначала я использовал 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(); // Закрываем окно фильтрации - оно больше не нужно }
Создано обращение, в рамках которого на указанный адрес Вам отправлено письмо.