Как получить оператор SQL SELECT, используемый в отчете Crystal?
В настоящее время я работаю над программой на C#, которая позволяет нашим пользователям запускать, просматривать и экспортировать пакет Crystal Reports. Отчеты были сделаны с использованием графического интерфейса Crystal Reports 2008. Одна из основных причин для этого - позволить нам сохранять гиперссылки при экспорте отчета Crystal Report в PDF. Моя программа делает это, экспортируя в RTF, а затем преобразовывает RTF в PDF. Если кто-нибудь знает менее запутанный метод сохранения гиперссылок при конвертации в PDf, я бы хотел услышать это, но это не мой текущий вопрос.
Я провел множество тестов по оптимизации моей программы, чтобы экспорт занимал как можно меньше времени. Из того, что я видел, запрос приложения к данным, а затем привязка набора результатов к отчету Crystal Report - самый быстрый способ. Моя проблема в том, что я не могу жестко запрограммировать запросы в программе, их нужно получить из самого Crystal Report.
В Crystal Reports 2008 есть опция "Показать запрос SQL" в меню "База данных". Это вызывает окно с запросом SQL, используемым для данного отчета. Это именно то, что мне нужно, чтобы получить изнутри моего приложения. Я загрузил отчет Crystal и во время отладки перебрал объект ReportDocument, пытаясь найти запрос, но безуспешно.
Итак, мой вопрос: Есть ли какой-либо метод, который позволил бы мне вытащить запрос, используемый данным Crystal Report?
2 ответа
Итак, dotjoe дал мне все подсказки, которые мне нужны, чтобы решить это. Следующий код можно использовать для извлечения текста команды из отчета Crystal.
public string getCommandText(ReportDocument rd)
{
if (!rd.IsLoaded)
throw new ArgumentException("Please ensure that the reportDocument has been loaded before being passed to getCommandText");
PropertyInfo pi = rd.Database.Tables.GetType().GetProperty("RasTables", BindingFlags.NonPublic | BindingFlags.Instance);
return ((dynamic)pi.GetValue(rd.Database.Tables, pi.GetIndexParameters()))[0].CommandText;
}
Это выглядит немного грязно, но это имеет какой-то смысл, когда вы начинаете пробираться через него. По сути, он использует отражение, чтобы получить значение свойства CommandText, с небольшой добавленной динамикой, чтобы обойти динамические свойства в ReportDocument.
Это тянет за собой текст команды, но у меня не было времени на какие-либо тесты кода. Я уверен, что сделаю некоторые изменения, как только у меня будет время поработать с этим. Я понятия не имею, что происходит с отчетами, в которых не используются "команды SQL". Я отправлю комментарий, как только я проверю это дальше.
- Скотт
PS Для этого необходимо, чтобы вы ссылались на стандартные библиотеки отражений / динамиков, а также на следующие библиотеки Crystal Report:
crystaldecisions.reportappserver.datadefmodel
crystaldecisions.crystalreports.engine
crystaldecisions.shared
Я понимаю, что это очень старый вопрос, но подумал, что я бы предложил альтернативу для тех, кто сталкивается с этим, но нуждается в целевой структуре 3.5 (динамическая недоступна в 3.5).
Для работы этого решения вам понадобятся следующие ссылки.
using CrystalDecisions.ReportAppServer.DataDefModel;
using CrystalDecisions.CrystalReports.Engine;
Тогда просто получите доступ к ClientDoc
взаимодействовать со следующим и возвращать список командных текстовых строк.
private static List<string> GetCommandText(CrystalDecisions.CrystalReports.Engine.ReportDocument report)
{
var rptClientDoc = report.ReportClientDocument;
return rptClientDoc.DatabaseController.Database.Tables.OfType<CommandTable>()
.Select(cmdTbl => cmdTbl.CommandText).ToList();
}