废话不说,直接上干货
1,在VS2010.NET中想要使用CrystalReport Viewer 13.0 必须先去SAP官网下载免费的插件:CRforVS_13_0_3.exe。
2,用Visual C#新建一个WinForm,在工具栏--组件--右击“选择项...”在出现的一堆列表中选择
3,在IDE的菜单上方,选择XXX项目--属性--目标框架。可能是从原来的“.NET Framework 4 Client Profile”→“.NET Framework 4”
4,更改项目的app.config内的内容,如下:
<?xml version="1.0"?>
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
</configuration>
5,基本工作结束了,接下来是如何动态显示你的水晶报表
水晶报表是一开始就利用Crystal Report 2008绑定XML为数据源做好的模板.rpt,而XML则是需要动态加载的。
重载下窗体的Load函数:
private void crystalReportViewer1_Load(object sender, EventArgs e)
{
//获取和设置包含该应用程序的目录的名称 result: X:\xxx\xxx\ (.exe文件所在的目录+"\")
string dir = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
string iniFilePath = dir+"CrystalRepoConfig.ini";
ReadIniFile iniFile = new ReadIniFile(iniFilePath);
bool isExist = iniFile.ExistINIFile();
if (!isExist)
{
System.Windows.Forms.MessageBox.Show("配置文件路径不正确:" + iniFilePath);
return;
}
bool hasPath = iniFile.ValueExists("CrystalReport", "DatafilePath");
if (!hasPath)
{
System.Windows.Forms.MessageBox.Show("配置文件CrystalRepoConfig.ini中对应样品文件路径不正确");
return;
}
hasPath = iniFile.ValueExists("CrystalReport", "TemplatePath");
if (!hasPath)
{
System.Windows.Forms.MessageBox.Show("配置文件CrystalRepoConfig.ini中对应报表文件路径不正确");
return;
}
string xmlfilePath = iniFile.ReadValue("CrystalReport", "DatafilePath");
string templatePath = iniFile.ReadValue("CrystalReport", "TemplatePath"); ;
System.Windows.Forms.MessageBox.Show("报表打开中…请稍等");
ReportDocument rd = new ReportDocument();
rd.Load(templatePath);
DataSet ds = new DataSet();
ds.ReadXml(xmlfilePath);
rd.SetDataSource(ds);
this.crystalReportViewer1.ReportSource = rd;
this.crystalReportViewer1.RefreshReport();
}
}
代码中的核心语句也就最后的7句,新建一个dataset的实例,即XML,传入路径并加载。新建一个水晶报表的实例,即rpt文件,传入路径并加载。最后绑定到Viewer上并显示。
而路径的加载选用了轻便的ini配置文件
public class ReadIniFile
{
public string FileName; //INI文件名
//声明读INI文件的API函数
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section, string key, string def, byte[] retVal, int size, string filePath);
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
public ReadIniFile(string INIPath)
{
FileName = INIPath;
}
public string ReadValue(string section, string key)
{
StringBuilder strBuffer = new StringBuilder(255);
int bufLen = GetPrivateProfileString(section, key, "", strBuffer, strBuffer.Capacity, FileName);
return strBuffer.ToString();
}
private void GetStringsFromBuffer(Byte[] Buffer, int bufLen, StringCollection Strings)
{
Strings.Clear();
if (bufLen != 0)
{
int start = 0;
for (int i = 0; i < bufLen; i++)
{
if ((Buffer[i] == 0) && ((i - start) > 0))
{
String s = Encoding.GetEncoding(0).GetString(Buffer, start, i - start);
Strings.Add(s);
start = i + 1;
}
}
}
}
//从Ini文件中,将指定的Section名称中的所有Ident添加到列表中
public void ReadSection(string Section, StringCollection Idents)
{
Byte[] Buffer = new Byte[16384];
//Idents.Clear();
int bufLen = GetPrivateProfileString(Section, null, null, Buffer, Buffer.GetUpperBound(0),
FileName);
//对Section进行解析
GetStringsFromBuffer(Buffer, bufLen, Idents);
}
//检查某个Section下的某个键值是否存在
public bool ValueExists(string Section, string Ident)
{
StringCollection Idents = new StringCollection();
ReadSection(Section, Idents);
return Idents.IndexOf(Ident) > -1;
}
// 验证文件是否存在
public bool ExistINIFile()
{
return File.Exists(FileName);
}
}
利用的是水晶报表的pull模式,但又用xml代替了数据库,达到了轻简,易用的目的。