/// <summary>
 /// 绑定数据源,把模板的标签写入数据
 /// </summary>
 public void DataBind()
 {
     if (string.IsNullOrEmpty(this.TemplateFileName))
     {
         this.bindBlankTemplate();
         return;
     }
     this.initTemplate();
     //有参数表,更新模板的参数表数据字段
     if (this.dataSource.Tables.Contains("参数表"))
     {
         DataTable tabparam = this.dataSource.Tables["参数表"];
         if (tabparam.Rows.Count > 0)
         {
             DataRow drparam = tabparam.Rows[0];
             XmlNodeList xncells = this.xmldoc.SelectNodes("/*/ss:Worksheet/ss:Table/ss:Row/ss:Cell/ss:Data", this.xmlNsMgl);
             foreach (XmlNode xn in xncells)
             {
                 if (!(xn is XmlElement))
                     continue;
                 this.BindData(xn as XmlElement, drparam);
             }
         }
     }
     XmlElement xeTemplate = this.xmldoc.SelectSingleNode("/*/ss:Worksheet", this.xmlNsMgl) as XmlElement;
     XmlElement xeTpClone = xeTemplate.Clone() as XmlElement;
     //清除模板表格
     XmlNode xnRow = xeTemplate.SelectSingleNode(".//ss:Row", this.xmlNsMgl);
     while (null != xnRow)
     {
         XmlNode xnT = xnRow.NextSibling;
         if ("Row" == xnRow.LocalName)
             xnRow.ParentNode.RemoveChild(xnRow);
         xnRow = xnT;
     }
     //初始化绑定区域结果主从关系
     IDictionary<string, BindResult> listResult = new Dictionary<string, BindResult>();
     BindResult rootResult = new BindResult();
     rootResult.boundResult = Bound.ParseBound("A1:A1");
     foreach (PrintInfo pinfo in this.printInfos)
     {
         string key = pinfo.DbName;
         if (!this.dataSource.Tables.Contains(key) && PrintType.Data==pinfo.RegionType)
             continue;
         BindResult bindInstance = new BindResult();
         bindInstance.rowIndex = 0;
         bindInstance.printInfo = pinfo;
         listResult.Add(pinfo.DbName, bindInstance);
     }
     for (int i=0;i<this.printInfos.Count;i++)
     {
         string key = this.printInfos[i].DbName;
         PrintInfo pinfo = this.printInfos[i];
         DataRelation rf = null;
         if (PrintType.Text == pinfo.RegionType)
         {
             foreach (PrintInfo p in this.printInfos)
             {
                 if (PrintType.Data != p.RegionType || !this.dataSource.Tables.Contains(p.DbName))
                     continue;
                 if (pinfo.GroupName != p.GroupName)
                     continue;
                 if (this.dataSource.Tables[p.DbName].ParentRelations.Count < 1)
                     continue;
                 rf = this.dataSource.Tables[p.DbName].ParentRelations[0];
                 break;
             }
         }
         else
         {
             if (this.dataSource.Tables[key].ParentRelations.Count < 1)
                 continue;
             rf = this.dataSource.Tables[key].ParentRelations[0];
         }
         if (null == rf) continue;
         BindResult rsParent = listResult[rf.ParentTable.TableName];
         BindResult bindrs = listResult[key];
         rsParent.resultChildren.Add(key, bindrs);
         bindrs.parentResult = rsParent;
     }
     for (int i = 0; i < this.printInfos.Count; i++)
     {
         string key = this.printInfos[i].DbName;
         BindResult bindrs = listResult[key];
         if (rootResult.boundResult.Right < bindrs.printInfo.PgBound.Right)
             rootResult.boundResult.Right = bindrs.printInfo.PgBound.Right;
         if (rootResult.boundResult.Bottom < bindrs.printInfo.PgBound.Bottom)
             rootResult.boundResult.Bottom = bindrs.printInfo.PgBound.Bottom;
         if (null != bindrs.parentResult)
             listResult.Remove(key);
         else
             rootResult.resultChildren.Add(key,bindrs);
     }
     string pagePrint = "类型=文本\n数据表=页\n页范围=A1:{0}{1}\n行范围=A1:{0}{1}";
     string col="";
     int colindex = rootResult.boundResult.Right;
     while (colindex > 0)
     {
         int mod = colindex % 27;
         if (colindex > 26) mod += 1;
         col = Convert.ToString(Convert.ToChar(mod + Convert.ToInt16('A') - 1)) + col;
         colindex = colindex / 27;
     }
     pagePrint = string.Format(pagePrint, col , rootResult.boundResult.Bottom);
     rootResult.printInfo = PrintInfo.SerialFromString(pagePrint);
     rootResult.boundRow = rootResult.boundResult;
     //按照数据源的表个数循环,行号-1表示已经绑定完,子级数据递归绑定
     //把结果页xeTp加入文档
     XmlElement xeTable = this.xmldoc.SelectSingleNode("/*/ss:Worksheet/ss:Table", this.xmlNsMgl) as XmlElement;
     while (true)
     {
         bool isBreak = true;
         foreach (BindResult bindInstance in listResult.Values)
         {
             if (bindInstance.rowIndex < 0)
                 continue;
             isBreak = false; break;
         }
         if (isBreak) break;
         //分页绑定
         XmlElement xeTp = xeTpClone.CloneNode(true) as XmlElement;
         foreach (BindResult rs in listResult.Values)
         {
             rs.boundResult = null;
             rs.boundRow = null;
         }
         foreach (PrintInfo pinfo in this.printInfos)
         {
             if (!listResult.ContainsKey(pinfo.DbName))
                 continue;
             BindResult rs = listResult[pinfo.DbName];
             if (rs.rowIndex < 0 && PrintType.Data == rs.printInfo.RegionType)
                 continue;
             rs.xeTemplate = xeTp;
             rootResult.initChildBound(pinfo.DbName);
             if (null == rs.boundResult)
                 continue;
             //子级范围
             if (PrintType.Text == pinfo.RegionType && !rootResult.isComplete(pinfo.DbName))
             {
                 this.CopyCell(xeTpClone, pinfo.RowBound, rs.xeTemplate, rs.boundResult.Left, rs.boundResult.Top);
                 rs.rowIndex = -1;
             }
             else if (PrintType.Data == pinfo.RegionType && this.dataSource.Tables.Contains(pinfo.DbName))
             {
                 DataRow[] drs = this.dataSource.Tables[pinfo.DbName].Select();
                 this.BindNode(xeTpClone, drs, rs);
             }
         }
         xnRow = xeTp.SelectSingleNode(".//ss:Row", this.xmlNsMgl);
         while (null != xnRow)
         {
             XmlNode xnT = xnRow.NextSibling;
             if ("Row" == xnRow.LocalName)
                 xeTable.AppendChild(xnRow);
             xnRow = xnT;
         }
     }//while (true)
     //合并单元格
     this.MergeCell(xeTemplate);
 }
    /// <summary>
    /// 数据源页内绑定模板,完成绑定则返回-1,非法返回null,内范围超限返回
    /// </summary>
    /// <param name="xeTemplate">独立模板</param>
    /// <param name="drs">数据记录集</param>
    /// <param name="bindEnv">当前绑定结果:当前行及范围</param>
    /// <returns>绑定结果:rowIndex=-1表示绑定完毕</returns>
    private BindResult BindNode(XmlElement xeTemplate, DataRow[] drs, BindResult bindEnv)
    {
        //检查
        if (null == xeTemplate || null == drs || drs.Length < 1 || null == bindEnv
            || null == bindEnv.xeTemplate || bindEnv.rowIndex < 0 || bindEnv.rowIndex >= drs.Length)
        { if (null != bindEnv) bindEnv.rowIndex = -1; return bindEnv; }
        DataTable   tab=drs[0].Table;
        string dbName = tab.TableName;
        if (!this.printInfoList.Keys.Contains(dbName))
        { if (null != bindEnv) bindEnv.rowIndex = -1; return bindEnv; }

        ICollection<String> pinfoKeys = this.printInfoList.Keys;
        PrintInfo pinfo = this.printInfoList[dbName];
        if (null == bindEnv.boundResult)
            bindEnv.boundResult = Bound.ParseBound(pinfo.RowBound);
        bindEnv.boundRow = new Bound();
        //当前行位置ileft,itop
        int ileft = bindEnv.boundResult.Left;
        int itop = bindEnv.boundResult.Top;
        while (bindEnv.rowIndex < drs.Length)
        {
            //复制模板区域
            bindEnv.boundRow.Left = ileft;
            bindEnv.boundRow.Top = itop;
            bindEnv.boundResult.Right = bindEnv.boundRow.Right = ileft + (pinfo.RwBound.Right - pinfo.RwBound.Left);
            bindEnv.boundResult.Bottom =bindEnv.boundRow.Bottom  = itop + (pinfo.RwBound.Bottom - pinfo.RwBound.Top);
            this.CopyCell(xeTemplate, pinfo.RowBound, bindEnv.xeTemplate, ileft, itop);
            //更新父项的结果区域
            BindResult childResult = bindEnv;
            BindResult parentResult = bindEnv.parentResult;
            while (null != parentResult)
            {
                Bound bdP = parentResult.boundResult;
                Bound bdC = childResult.boundResult;
                if (bdP.Right >= bdC.Right && bdP.Bottom >= bdC.Bottom)
                    break;
                if (bdC.Right > bdP.Right)
                    bdP.Right = bdC.Right;
                if (bdC.Bottom > bdP.Bottom)
                    bdP.Bottom = bdC.Bottom;
                childResult = parentResult;
                parentResult = parentResult.parentResult;
            }
            //绑定字段值(父级字段或自身字段)
            string strTabFind = "ss:Table/ss:Row/ss:Cell[@r='{0}']";
            string strRowFind = "ss:Cell[@c='{0}']";
            XmlNode xnField=null, xnRowF=null;
            for (int i = itop; i <= bindEnv.boundResult.Bottom; i++)
            {
                if (null == xnRowF)
                {
                    xnField = bindEnv.xeTemplate.SelectSingleNode(string.Format(strTabFind, i), this.xmlNsMgl);
                    if (null == xnField)
                        continue;
                    xnRowF = xnField.ParentNode;
                }
                xnField = xnRowF.SelectSingleNode(string.Format(strRowFind, ileft), this.xmlNsMgl);
                for (int j = ileft; j <= bindEnv.boundResult.Right; j++)
                {
                    if (null == xnField)
                        xnField = xnRowF.SelectSingleNode(string.Format(strRowFind, j), this.xmlNsMgl);
                    if (null == xnField)
                        continue;
                    if (null != xnField.FirstChild && null != xnField.FirstChild.Attributes["field"])
                        this.BindData((XmlElement)xnField.FirstChild, drs[bindEnv.rowIndex]);
                    xnField = xnField.NextSibling;
                    if (null == xnField || null == xnField.FirstChild || null == xnField.FirstChild.Attributes["c"]
                        || Convert.ToString(j+1) != xnField.FirstChild.Attributes["c"].Value)
                        xnField = null;
                }
                xnRowF = xnRowF.NextSibling;
            }
            //页内绑定子级
            foreach (BindResult rs in bindEnv.resultChildren.Values)
            {
                rs.boundResult = null;
                rs.boundRow = null;
            }
            foreach (BindResult rs in bindEnv.resultChildren.Values)
            {
                PrintInfo pinfoChild = rs.printInfo;
                string key = pinfoChild.DbName;
                DataRelation rlChild = null;
                foreach (DataRelation rl in tab.ChildRelations)
                {
                    if (key != rl.ChildTable.TableName)
                        continue;
                    rlChild = rl;
                    break;
                }
                //检查配置区域是否合理,不在当前区域忽略
                if (pinfoChild.RwBound.Left < pinfo.RwBound.Left || pinfoChild.RwBound.Top < pinfo.RwBound.Top
                    || pinfoChild.RwBound.Right > pinfo.RwBound.Right || pinfoChild.RwBound.Bottom > pinfo.RwBound.Bottom)
                    continue;
                rs.xeTemplate = bindEnv.xeTemplate;
                if (rs.parentRowIndex != bindEnv.rowIndex)
                {
                    rs.parentRowIndex = bindEnv.rowIndex;
                    rs.rowIndex = 0;
                }
                //初始化计算子区域,超界则为空
                bindEnv.initChildBound(key);
                if (null == rs.boundResult)
                    continue;
                //子级范围
                if (PrintType.Text == pinfoChild.RegionType && !bindEnv.isComplete(key))
                {
                    this.CopyCell(xeTemplate, pinfoChild.RowBound, rs.xeTemplate, rs.boundResult.Left, rs.boundResult.Top);
                    rs.rowIndex = -1;
                }
                else if (PrintType.Data == pinfoChild.RegionType && null != rlChild)
                    this.BindNode(xeTemplate, drs[bindEnv.rowIndex].GetChildRows(rlChild), rs);
            }
            //检查是否下一行
            bool isNext = true;
            foreach(BindResult srChild in bindEnv.resultChildren.Values)
                if (srChild.rowIndex > -1)
                { isNext=false; break; }
            if (isNext)
                bindEnv.rowIndex++;
            if (bindEnv.rowIndex >= drs.Length)
                break;
            //根据行输出方式计算下一条记录的区域位置
            if (OutRowModel.VeriNextHori == pinfo.OutRowType)
            {
                itop = bindEnv.boundResult.Bottom + 1;
                if (itop + pinfo.RwBound.Bottom - pinfo.RwBound.Top > pinfo.PgBound.Bottom)
                {
                    itop = bindEnv.boundResult.Top;
                    ileft = bindEnv.boundResult.Right + 1;
                }
            }
            else
            {
                ileft = bindEnv.boundResult.Right+1;
                if (ileft + pinfo.RwBound.Right - pinfo.RwBound.Left > pinfo.PgBound.Right)
                {
                    ileft = bindEnv.boundResult.Left;
                    itop = bindEnv.boundResult.Bottom + 1;
                }
            }
            //检查下一个记录是否页面超限
            if (bindEnv.boundResult.Right > pinfo.PgBound.Right || bindEnv.boundResult.Bottom > pinfo.PgBound.Bottom
                || (itop + pinfo.RwBound.Bottom - pinfo.RwBound.Top) > pinfo.PgBound.Bottom
                || (ileft + pinfo.RwBound.Right - pinfo.RwBound.Left) > pinfo.PgBound.Right)
                return bindEnv;
        }//for (int i = 0; bindEnv.rowIndex < drs.Length; i++)
        //子项重置
        bindEnv.rowIndex = -1;
        foreach (BindResult srChild in bindEnv.resultChildren.Values)
            srChild.parentRowIndex = srChild.rowIndex = -1;
        return bindEnv;
    }