Я исследовал множество различных способов динамического изменения соединения источника данных здесь, в StackOverflow. Я использовал и проверял почти все примеры C# и vb.net, которые я мог найти, но как-то все будет не так, как должно.Динамическое изменение типа базы данных, источника и т. Д. В Crystal Reports (для Visual Studio 2012)
Идея нашего проекта заключается в изменении соединений источника данных из старых отчетов - с использованием dll xBase - с crdb_ado.dll с поставщиком VFPOLEDB для подключения к файлам DBF Visual Foxpro (каждый файл, представляющий одну таблицу) ,
Я скачал последнюю Кристал Developer Версия для Visual Studio (2012) здесь: http://scn.sap.com/docs/DOC-35074 Чтобы иметь возможность использовать эти компоненты непосредственно в VS без ссылок на библиотеки DLL в Program Files - бизнес-объект каталог (как показано в другие примеры).
Я попытался проверить содержимое через отладчик VS более старого «обновленного» отчета (см. Код ниже) вместе с недавно созданным отчетом в Crystal Reports (последняя версия, в которой используется правильный путь и настройки для подключения к dbf), поэтому они совпадают.
Однако я столкнулся с этими проблемами:
- код способен изменить все параметры и атрибуты, но сохранить его отменяет все изменения (файл НЕ только для чтения)
- Изменение table.location throws a com исключение (перевод: не удалось загрузить данные базы данных, ошибка в отчете)
- То же самое происходит, когда «прикреплять» объект документа отчета к программе просмотра отчетов о кристалле.
- reportDocument.VerifyDatabase() явно не удается
- Для насколько я могу судить, все настройки являются, кажется, в обоих файлах
Дев среда Windows 7/64bit/VS 2012 Pro. На этом компьютере установлены Crystal Reports (XI или 2011). Все наши отчеты были созданы с версиями 9 и 11 Crystal Reports.
Ниже приведен один из адаптированных примеров кода, который изменил все атрибуты или параметры (кроме расположения таблицы). Я также использовал примеры, которые использовали объекты Propertybag, но они не работали.
reportDocument1.Load("path to document");
// also tried adding these two lines as a test
reportDocument1.DataSourceConnections.Clear();
reportDocument1.DataSourceConnections[0].SetConnection(@"c:\testreports","",false);
//changing of table data connections
foreach (Table table in reportDocument1.Database.Tables)
{
ChangeTableLogonInfo(table);
}
// ---
private void ChangeTableLogonInfo(Table table)
{
// server = place containing *.DBF files
table.LogOnInfo.ConnectionInfo.ServerName = @"c:\testreports\";
// set to empty string (looking at generated report in CrRep)
table.LogOnInfo.ConnectionInfo.DatabaseName = "";
table.LogOnInfo.ConnectionInfo.UserID = "";
table.LogOnInfo.ConnectionInfo.Password = "";
// create logon properties
var connectionAttributes = new DbConnectionAttributes();
connectionAttributes.Collection.Set("Collating Sequence","Machine");
connectionAttributes.Collection.Set("Data Source", @"c:\testreports");
connectionAttributes.Collection.Set("Locale Identifier", 1033);
connectionAttributes.Collection.Set("OLE DB Services", -5);
connectionAttributes.Collection.Set("Provider", "VFPOLEDB"); //eg: SQLOLEDB
connectionAttributes.Collection.Set("Use DSN Default Properties",false);
// CLEAR and SET NEW attributes for the given table
table.LogOnInfo.ConnectionInfo.Attributes.Collection.Clear();
table.LogOnInfo.ConnectionInfo.Attributes.Collection.Add(new NameValuePair2 { Name = "Database DLL", Value = "crdb_ado.dll" });
table.LogOnInfo.ConnectionInfo.Attributes.Collection.Add(new NameValuePair2 { Name = "QE_DatabaseName", Value = "" });
table.LogOnInfo.ConnectionInfo.Attributes.Collection.Add(new NameValuePair2 { Name = "QE_DatabaseType", Value = "OLE DB (ADO)" });
table.LogOnInfo.ConnectionInfo.Attributes.Collection.Add(new NameValuePair2 { Name = "QE_LogonProperties", Value = connectionAttributes });
table.LogOnInfo.ConnectionInfo.Attributes.Collection.Add(new NameValuePair2 { Name = "QE_ServerDescription", Value = @"c:\testreports" });
table.LogOnInfo.ConnectionInfo.Attributes.Collection.Add(new NameValuePair2 { Name = "QE_SQLDB", Value = true });
table.LogOnInfo.ConnectionInfo.Attributes.Collection.Add(new NameValuePair2 { Name = "SSO Enabled", Value = false });
// gives a COM error
try
{
table.Location = "some-table-name";
}
catch (Exception e)
{
// handling
}
}
Мы заметили что-то «раздражающее» в самих Crystal Reports. Интересно, имеет ли это какое-то отношение к этому:
Когда мы хотели изменить соединение xbase через сам CR, мы не можем указать его из «xbase connection dbf» в «соединение vfpoledb dbf» (если вы понимаете мою точка) без потери всех полей в отчете.
Я попытался установить 32 и 64-разрядные версии версии разработчика VS CR, но это ничего не меняет.
Кроме того, следующий фрагмент кода работает в Visual FoxPro (и я могу прочитать эти преобразованные файлы в своем средстве просмотра документов Crystal Reports).Это просто раздражает, оно не может быть легко сделано в C# (кажется :))
lotest = CREATEOBJECT("crystalruntime.application.9")
lorap = lotest.openreport("c:\factuur.rpt")
loData = loRap.Database
LOCAL lnI
lnI = 1
FOR EACH loTable IN lodata.tables
loconn = loTable.connectionproperties
loTable.dllname = "crdb_odbc.dll"
loConn.DeleteAll
IF lnI = 1
loCOnn.Add("Database", "Hoofding")
ELSE
loCOnn.Add("Database", "Detail")
ENDIF
loConn.Add("Database Type","ODBC")
loConn.Add("DSN","DBFACTw")
lnI = lnI + 1
ENDFOR
loRap.Saveas("c:\Factuur2.rpt",2048)
Любые идеи или предложения? Спасибо
У меня такая же проблема, но не с использованием ReportAppServer, так как я просто запускаю отчет локально. Я не могу, чтобы жизнь меня определяла, откуда происходит название базы данных - это, конечно, не похоже, что она публично раскрыта. Проверка с помощью отражателя выглядит так, как будто в моей сборке (9.2.3333.0), даже если она запутана, похоже, передает информацию из ConnectionInfo вниз в неуправляемый код. this._obfuscatedtablename_ (connectionInfo.ServerName, connectionInfo.DatabaseName, connectionInfo.UserID, connectionInfo.Password, true); – agrath