我在 StackOverflow 上研究了许多不同的方法来动态更改数据源连接。我使用并验证了我能找到的几乎所有 c# 和 vb.net 示例,但不知何故,事情并没有按应有的方式进行。
我们项目的想法是将数据源连接从旧报告(使用 xBase dll)更改为 crdb_ado.dll,并使用 VFPOLEDB 提供程序连接到 Visual Foxpro DBF 文件(每个文件代表一个表)。
我在这里下载了 Visual Studio (2012) 的最新 Crystal Developer 版本:http: //scn.sap.com/docs/DOC-35074 为了能够直接在 VS 中使用这些组件,而无需在程序文件中引用 dll -业务对象目录(如在其他示例中所见)。
我尝试通过较旧的“更新”报告(参见下面的代码)的 VS 调试器以及 Crystal Reports 中新创建的报告(最新版本,它使用正确的路径和设置连接到 dbf)来验证内容,因此它们匹配向上。
但是,我遇到了这些问题:
- 该代码能够更改所有参数和属性,但保存它会丢弃所有更改(文件不是只读的)
- 更改 table.location 会引发com 异常(翻译:无法加载数据库数据,报告错误)
- 将报表文档对象“附加”到水晶报表查看器时也会发生同样的情况。
- reportDocument.VerifyDatabase() 明显失败
- 据我所见,所有设置都出现在两个文件中
开发环境为 windows 7/64bit/VS 2012 Pro。Crystal Reports(XI 或 2011)安装在这台机器上。我们所有的报表都是使用 Crystal Reports 版本 9 和 11 创建的。
下面是修改后的代码示例之一,它确实更改了所有属性或参数(表格位置除外)。我还使用了使用 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 本身有一些“烦人”的东西。我想知道它是否与它有关:
当我们想通过 CR 本身更改 xbase 连接时,我们不能将其从“xbase 连接 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)
有什么想法或建议吗?谢谢