public class RdlcHelper
{
/// <summary>
/// 对应XML 的文件地址,每个RdlcHelper实体操作 只对应一个文件,不管是本地的还是服务器上的
/// </summary>
public string RdlcFile { get; private set; }
public RdlcHelper()
{
}
#region 从rdlc文件里面读取字段和字段类型
/// <summary>
///
/// </summary>
/// <param name="fileName">RDLC文件地址</param>
//public RdlcHelper(string fileName)
//{
// RdlcFile = fileName;
////创建xml对象
//XmlDocument xdoc = new XmlDocument();
////加载xml地址
//xdoc.Load(fileName);
////获取根节点
//XmlNode xReport = xdoc.DocumentElement;
////获取根节点的名称空间
//string xmlns = xReport.Attributes["xmlns"].Value;
////获取或设置用于在 XML 绑定中执行可以识别命名空间的 XPath 查询
//XmlNamespaceManager xnm = new XmlNamespaceManager(xdoc.NameTable);
////加载命名空间
//xnm.AddNamespace("tk", xmlns);
////查找指定的节点
//XmlNode node = xdoc.SelectSingleNode("/tk:Report/tk:DataSets/tk:DataSet/tk:Fields", xnm);
//if (node == null)
// return;
//FieldList = new Fields();
////遍历节点属性值
//foreach (System.Xml.XmlNode xn in node.ChildNodes)
//{
// FieldList.Add(new Field(xn));
//}
//}
#endregion
/// <summary>
/// 搜索xml方法
/// </summary>
/// <param name="list">搜索条件的集合</param>
/// <param name="xmlKey">xml键</param>
/// <returns>本地xml地址</returns>
public bool SearchXmlFile(Filters list, string SaveUrl, string rdlcPath, out string ErrMsg)
{
try
{
ErrMsg = string.Empty;
XmlDocument xd = SearchXmlFile(list, rdlcPath, out ErrMsg);
if (string.IsNullOrEmpty(ErrMsg))
{
xd.Save(SaveUrl);
return true;
}
else
{
return false;
}
}
catch (Exception ex)
{
ErrMsg = ex.Message;
return false;
}
}
public XmlDocument SearchXmlFile(Filters list, string rdlcPath, out string ErrMsg)
{
ErrMsg = string.Empty;
try
{
//创建xml对象
XmlDocument xd = new XmlDocument();
//加载xml地址
xd.Load(rdlcPath);
//获取根节点
XmlNode xReport = xd.DocumentElement;
//获取根节点的名称空间
string xmlns = xReport.Attributes["xmlns"].Value;
//获取或设置用于在 XML 绑定中执行可以识别名称空间的 XPath 查询
XmlNamespaceManager xnm = new XmlNamespaceManager(xd.NameTable);
//加载xml名称空间
xnm.AddNamespace("tk", xmlns);
xnm.AddNamespace("rp", xmlns);
//获取字段的节点,有两中类型节点
XmlNode node = xd.SelectSingleNode("/tk:Report/tk:Body/rp:ReportItems/rp:Table", xnm);
if (node == null)
node = xd.SelectSingleNode("/tk:Report/tk:Body/tk:ReportItems/rp:Matrix", xnm);
if (node == null)
return xd;
XmlElement Filters = GetFilters(list, xd, xmlns);
//搜索条件节点不为空
if (Filters != null)
{
node.AppendChild(Filters);
}
return xd;
}
catch (Exception ex)
{
ErrMsg = ex.Message;
return null;
}
}
private XmlElement GetFilters(Filters list, XmlDocument xd, string xmlns)
{
//创建一个xml元素对象(搜索条件节点)
XmlElement filters = null;
//创建(搜索条件节点)
if (list.Count > 0)
{
filters = xd.CreateElement("Filters");
filters.SetAttribute("xmlns", xmlns);
}
//用来做判断条件
AndOrEnums andOr = AndOrEnums.None;
foreach (Filter fi in list)
{
//创建搜索条件xml节点
XmlElement Filter = xd.CreateElement("Filter");
XmlElement FilterExpression = xd.CreateElement("FilterExpression");
//判断是否连续都是Equal条件,是就往节点里面追加参数值并把搜索条件改成In
if (andOr == AndOrEnums.Or)
{
//获取最后一个Filter节点
XmlNode lastChild = filters.LastChild;
//获取条件节点
XmlNode nodeFilter = lastChild.SelectSingleNode("Operator");
nodeFilter.InnerText = "In";
//获取值的节点
XmlNode nodeFilterValues = lastChild.SelectSingleNode("FilterValues");
//值子节点添加到值的节点
nodeFilterValues.AppendChild(FilterType(fi, xd));
}
else
{
//字段
if (fi.Field.TypeCode == TypeCode.String)
FilterExpression.InnerText =string.Format( "=TRIM(Fields!{0}.Value)", fi.Field.Name);
else if (fi.Field.TypeCode == TypeCode.DateTime)
FilterExpression.InnerText =string.Format( "=CDate(Fields!{0}.Value).Date()",fi.Field.Name);
else
FilterExpression.InnerText =string.Format( "=Fields!{0}.Value", fi.Field.Name );
Filter.AppendChild(FilterExpression);
//条件
XmlElement Operator = xd.CreateElement("Operator");
if (fi.OperatorType == OperatorEnums.Like && fi.Field.TypeCode != TypeCode.String)
Operator.InnerText = OperatorEnums.Equal.ToString();
else
Operator.InnerText = fi.OperatorType.ToString();
Filter.AppendChild(Operator);
//参数
XmlElement FilterValues = xd.CreateElement("FilterValues");
FilterValues.AppendChild(FilterType(fi, xd));
Filter.AppendChild(FilterValues);
filters.AppendChild(Filter);
}
andOr = fi.AndOr;
}
return filters;
}
private XmlElement FilterType(Filter fi, XmlDocument xd)
{
XmlElement FilterValue = xd.CreateElement("FilterValue");
TypeCode type = fi.Field.TypeCode;//.FiltersType;
string value = fi.Value;//.Values;
//判断字段类型
if (type == TypeCode.Decimal)
FilterValue.InnerText = string.Format("=CDEC({0})", value);
else if (type == TypeCode.Int32)
FilterValue.InnerText = string.Format("=INT({0})", value);
else if (type == TypeCode.Boolean)
FilterValue.InnerText = string.Format("=CBool({0})", value);
else if (type == TypeCode.Byte)
FilterValue.InnerText = string.Format("=CByte({0})", value);
else if (type == TypeCode.Char)
FilterValue.InnerText = string.Format("=CChar({0})", value);
else if (type == TypeCode.Double)
FilterValue.InnerText = string.Format("=CDbl({0})", value);
else if (type == TypeCode.Int64)
FilterValue.InnerText = string.Format("=CInt({0})", value);
else if (type == TypeCode.Object)
FilterValue.InnerText = string.Format("=CObj({0})", value);
else if (type == TypeCode.Single)
FilterValue.InnerText = string.Format("=CSng({0})", value);
else if (type == TypeCode.DateTime)
FilterValue.InnerText = string.Format("=CDate(\"{0}\").Date()", value);
else if (fi.OperatorType == OperatorEnums.Like) // 判断条件是否为like,是在值后面加*
FilterValue.InnerText = "*" + fi.Value + "*";
else
FilterValue.InnerText = fi.Value;
return FilterValue;
}
}
public enum OperatorEnums
{
Equal,
Like,
NotEqual,
GreaterThan,
GreaterThanOrEqual,
LessThan,
LessThanOrEqual,
TopN,
BottomN,
TopPercent,
BottomPercent,
In,
}
public enum AndOrEnums
{
None ,
And,
Or,
}
public class Filter
{
public Field Field { get; set; }
public OperatorEnums OperatorType { get; set; }
public string Value { get; set; }
public AndOrEnums AndOr { get; set; }
public Filter() { }
public Filter(Field field, string strOperatorType, string value, AndOrEnums andOr)
{
Field = field;
OperatorEnums operatorType = (OperatorEnums)Enum.Parse(typeof(OperatorEnums), strOperatorType, true);
OperatorType = operatorType;
Value = value;
AndOr = andOr;
}
public Filter(Field field, OperatorEnums operatorType, string value, AndOrEnums andOr)
{
Field = field;
OperatorType = operatorType;
Value = value;
AndOr = andOr;
}
}
public class Filters : List<Filter>
{
// 用于替代ReportSearch中的SerachAndOr方法,代码未整理,命名--(测试版)
public new void Add(Filter a)
{
Filter last = null;
if (this.Count > 0)
last = this[this.Count - 1];
if (last != null)
{
if (last.Field == a.Field && last.OperatorType == a.OperatorType && a.OperatorType == OperatorEnums.Equal)
{
last.AndOr = AndOrEnums.Or;// "or";
}
else if (!string.IsNullOrEmpty(a.Field.Name))
last.AndOr = AndOrEnums.And;// "and";
else
last.AndOr = AndOrEnums.None;
}
base.Add(a);
}
}
public class Field
{
public string Name { get; set; }
public TypeCode TypeCode { get; set; }
public Fields FieldList { get; private set; }
public Field()
{
}
public Field(DataTable dt)
{
FieldList = new Fields();
foreach (DataColumn c in dt.Columns)
{
Field f = new Field();
f.Name = c.ColumnName;
f.TypeCode = Field.GetTypeCode(c.DataType.FullName);
FieldList.Add(f);
}
}
#region
//public Field(XmlNode xmlNode)
//{
// Name = xmlNode.Attributes["Name"].Value;
// if (xmlNode.HasChildNodes)
// {
// foreach (XmlNode node in xmlNode.ChildNodes)
// {
// if (node.LocalName.ToUpper() == "TYPENAME")
// {
// TypeCode = GetTypeCode(node.InnerText);
// break;
// }
// }
// }
//}
//public Field(string name, string typeCode)
//{
// Name = name;
// TypeCode = GetTypeCode(typeCode);
//}
#endregion
public static TypeCode GetTypeCode(string value)
{
switch (value)
{
case "System.String":
return TypeCode.String;
case "System.Decimal":
return TypeCode.Decimal;
case "System.Byte[]":
return TypeCode.Byte;
case "System.DateTime":
return TypeCode.DateTime;
case "System.Int32":
return TypeCode.Int32;
case "System.bool":
return TypeCode.Boolean;
case "System.Boolean":
return TypeCode.Boolean;
case "System.Single":
return TypeCode.Single;
case "System.Short":
return TypeCode.Int16;
case "System.Double":
return TypeCode.Double;
case "System.Char":
return TypeCode.Char;
case "System.Object":
return TypeCode.Object;
case "System.Integer":
return TypeCode.Int32;
default:
{
LogHelper.Warn(string.Format("Not Match Type:{0}", value));
return TypeCode.String;
}
}
}
}
public class Fields : List<Field>
{
public Field Find(string name)
{
return this.Find(delegate(Field f) { return f.Name == name; });
}
}