www.pudn.com > Cnewprint.rar > MisPrinter.cs


using System; 
using System.Drawing; 
using System.Drawing.Printing; 
 
namespace GoldPrinter 
{ 
	///  
	///	本程序为通用打印程序,单据、会计凭证、发票清单、报表、任意复杂表格、合并表格如工矿企业合同都可以由系统提供的几个默 
	///	认打印对象组合打印。 
	///	DataGrid、DataTable、MSHFlexGrid等二维形式全部可以打印。 
	///	部分对象如PrinterMargins、Sewing、GridLineFlag、GridMergeFlag等提供图例,以促进理解。 
	///	后期版本将提供XML描述、SQL数据源的打印,并用管理器管理任意多个网格、文本对象、图象等,用户可以随意定义。 
	///  
	/// 程序提供:周方勇;Email:flygoldfish@sina.com。 
	/// 请 关 注:WebMIS.Net快速开发工具,不写一行程序开发B/S架构下MIS、OA、CRM、人事管理、档案管理等数据库网页系统。简单、实用、稳定、可靠。 
	/// 下    载: 
	///			 上海奥联:WWW.AlinkSoft.COM 
	///			 用友华表:WWW.CellSoft.CC 
	///★★★★★您可以免费使用此程序,但是请您保留此说明,以维护知识产权★★★★★ 
	///  
	public class MisPrinter:IDisposable 
	{ 
		public Color BackColor = Color.White;//背景颜色 
 
		//绘图表面 
		private Graphics mGraphics;	 
		//打印文档 
		private PrintDocument mPrintDocument; 
		//下一对象的起点坐标及宽 
		private float X,Y,Width; 
 
		//翻页用 
		private int mCurrentPageIndex;		//当前页 
		private int mCurrentRowIndex;		//主数据网格的当前行 
		private int mCurrentRowIndexForFooter;	//Footer当前行 
 
		//字段 
		private int _rowsPerPage;			//每页行数,小于等于0自适应,默认 
 
		private bool _isSewingLine;			//是否打印装订线(默认无) 
		private bool _isPrinterMargins;		//是否打印有效区域矩阵(默认无) 
		private bool _isSubTotalPerPage;	//是否每页都要显示主数据网格当前页小计(默认否) 
		private string _subTotalCol;		//每页小计要指定的列 
		 
		private Sewing _sewing;				//装订,对象的线长小于0则自动设置 
		private GridBorderFlag _gridBorder;	//网格边框 
 
		#region 字段属性 
		///  
		/// 每页行数,小于等于0自适应,默认 
		///  
		public int RowsPerPage 
		{ 
			get 
			{ 
				return _rowsPerPage; 
			} 
			set 
			{ 
				int mint = value; 
				if (mint < 0) 
				{ 
					mint = -1;  
				} 
				_rowsPerPage = mint; 
			} 
		} 
 
		///  
		/// 是否打印装订线,对象的线长小于0则自动设置 
		///  
		public bool IsSewingLine 
		{ 
			get 
			{ 
				return _isSewingLine; 
			} 
			set 
			{ 
				_isSewingLine = value; 
			} 
		} 
 
		///  
		/// 是否打印有效区域矩阵 
		///  
		public bool IsPrinterMargins 
		{ 
			get 
			{ 
				return _isPrinterMargins; 
			} 
			set 
			{ 
				_isPrinterMargins = value; 
			} 
		} 
 
		///  
		/// 是否每页都要显示当前页小计(默认否) 
		///  
		public bool IsSubTotalPerPage 
		{ 
			get 
			{ 
				return _isSubTotalPerPage; 
			} 
			set 
			{ 
				_isSubTotalPerPage = value; 
			} 
		} 
 
		///  
		/// 用分号分隔的要每页小计列 
		///  
		public string SubTotalCol 
		{ 
			get 
			{ 
				return _subTotalCol; 
			} 
			set 
			{ 
				_subTotalCol = value; 
			} 
		} 
 
		///  
		/// 装订对象,对象的线长小于0则自动设置 
		///  
		public Sewing Sewing 
		{ 
			get 
			{ 
				return this._sewing; 
			} 
			set 
			{ 
				if (value != null) 
				{ 
					this._sewing = value; 
				} 
				else 
				{ 
					this._sewing.Margin = 0;		//宽度为0则不打印 
				} 
			} 
		} 
 
		///  
		/// 网格边框 
		///  
		public GridBorderFlag GridBorder 
		{ 
			get 
			{ 
				return this._gridBorder; 
			} 
			set 
			{ 
				this._gridBorder = value; 
			} 
		} 
 
		#endregion 
 
		//********************打印对象********************	 
		private Title _title;				//主标题 
		private Caption _caption;			//副标题 
		private Top _top;					//简单的一行三列打印样式,第一列居左,第三列居右,中间列居中 
		private Header _header;				//正文网格主体之上的几行几列的标注说明 
		 
		private MultiHeader _multiHeader;	//正文网格主体标题头可能需要多层合并表头说明 
		private Body _body;					//*正文网格主体,必须,打印以此为基准 
		protected Footer _footer;			//正文网格主体之下的几行几列的标注说明 
		private Bottom _bottom;				//简单的一行三列打印样式,第一列居左,第三列居右,中间列居中 
 
		#region 打印对象字段属性 
 
		#region Title、Caption 
		///  
		/// 获取或设置打印主标题,可以是文本,也可以是定义更多特性的Title对象 
		///  
		public object Title 
		{ 
			get 
			{ 
				return this._title; 
			} 
			set 
			{	 
				if (value != null) 
				{ 
					if (value.GetType().ToString() == "System.String") 
					{ 
						if (this._title == null) 
						{ 
							this._title = new Title(); 
						} 
						this._title.Text = (string)value; 
					} 
					else if(value.GetType().ToString() == "GoldPrinter.Title") 
					{ 
						this._title = (GoldPrinter.Title)value; 
					} 
				} 
			} 
		} 
 
		///  
		/// 获取或设置打印副标题,可以是文本,也可以是定义更多特性的Caption对象 
		///  
		public object Caption 
		{ 
			get 
			{ 
				return this._caption; 
			} 
			set 
			{	 
				if (value != null) 
				{ 
					if (value.GetType().ToString() == "System.String") 
					{ 
						if (this._caption == null) 
						{ 
							this._caption = new Caption(); 
						} 
						this._caption.Text = (string)value; 
					} 
					else if(value.GetType().ToString() == "GoldPrinter.Caption") 
					{ 
						this._caption = (GoldPrinter.Caption)value; 
					} 
				} 
			} 
		} 
		#endregion 
 
		#region 或取或设置网格头、底,可以是以'|'分隔的字符串或或一维数组或具有更多特性的Top/Bottom对象 
		///  
		/// 或取或设置网格头,可以是以'|'分隔的字符串或或一维数组或具有更多特性的Top对象 
		///  
		public object Top 
		{ 
			get 
			{ 
				return this._top; 
			} 
			set 
			{	 
				if (value != null) 
				{ 
					if (value.GetType().ToString() == "System.String" || value.GetType().ToString() == "System.String[]") 
					{ 
						if (this._top == null) 
						{ 
							this._top = new Top(); 
						} 
						this._top.DataSource = value; 
					} 
					else if(value.GetType().ToString() == "GoldPrinter.Top") 
					{ 
						this._top = (GoldPrinter.Top)value; 
					} 
				} 
			} 
		} 
 
		///  
		/// 或取或设置网格底,可以是以'|'分隔的字符串或或一维数组或具有更多特性的Bottom对象 
		///  
		public object Bottom 
		{ 
			get 
			{ 
				return this._bottom; 
			} 
			set 
			{	 
				if (value != null) 
				{ 
					if (value.GetType().ToString() == "System.String" || value.GetType().ToString() == "System.String[]") 
					{ 
						if (this._bottom == null) 
						{ 
							this._bottom = new Bottom(); 
						} 
						this._bottom.DataSource = (string)value; 
					} 
					else if(value.GetType().ToString() == "GoldPrinter.Bottom") 
					{ 
						this._bottom = (GoldPrinter.Bottom)value; 
					} 
				} 
			} 
		} 
		#endregion 
 
 
		public object Header 
		{ 
			get 
			{ 
				return _header; 
			} 
			set 
			{ 
				this._header = (GoldPrinter.Header)value; 
				 
			} 
		} 
 
		public object MultiHeader 
		{ 
			get 
			{ 
				return _multiHeader; 
			} 
			set 
			{ 
				this._multiHeader = (GoldPrinter.MultiHeader)value; 
			} 
		} 
 
		public object Body 
		{ 
			get 
			{ 
				return _body; 
			} 
			set 
			{ 
				_body = (GoldPrinter.Body)value; 
			} 
		} 
 
		public object Footer 
		{ 
			get 
			{ 
				return this._footer; 
			} 
			set 
			{ 
				this._footer = (GoldPrinter.Footer)value; 
			} 
		} 
 
		#endregion 
 
 
		//还可以将此程序稍微修改,用一个集体管理,动态加载打印对象,形成任意多个网格的组合体,打印任意复杂的网格 
 
		public MisPrinter() 
		{ 
			mCurrentPageIndex = 1; 
			_rowsPerPage = 0; 
			mCurrentRowIndex = 0; 
			mCurrentRowIndexForFooter = 0; 
			_isSewingLine = false; 
			_isPrinterMargins = false; 
			_isSubTotalPerPage = false; 
			_subTotalCol = ""; 
 
			_sewing = new Sewing(0,SewingDirectionFlag.Left); 
			mPrintDocument = new PrintDocument(); 
			_body = new Body();			//主要对象,所以实例化 
			_gridBorder = GridBorderFlag.Double; 
 
		} 
 
		#region IDisposable 成员 
 
		public virtual void Dispose() 
		{ 
			//... 
		} 
 
		#endregion 
 
		///  
		/// 获取或设置数据主体网格的数据源 
		///  
		public object DataSource 
		{ 
			get 
			{ 
				return this._body.DataSource; 
			} 
			set 
			{ 
				this._body.DataSource = value; 
			} 
		} 
 
		///  
		/// 页面设置对话框,如果需要,国庆期间继续开放,敬请关注 
		///  
		public void PageSetup() 
		{ 
			PrinterPageSetting	printerPageSetting;	 
			printerPageSetting = new PrinterPageSetting(mPrintDocument); 
			printerPageSetting.PrintPage += new PrintPageDelegate(this.PrintPageEventHandler); 
 
			printerPageSetting.ShowPageSetupDialog(); 
		} 
 
		///  
		/// 打印,如果需要,国庆期间继续开放,敬请关注 
		///  
		public void Print() 
		{ 
			PrinterPageSetting	printerPageSetting; 
			printerPageSetting = new PrinterPageSetting(mPrintDocument); 
			printerPageSetting.PrintPage += new PrintPageDelegate(this.PrintPageEventHandler); 
 
			printerPageSetting.ShowPrintSetupDialog();			 
		} 
 
		///  
		/// 打印预览,如果需要,国庆期间继续开放,敬请关注 
		///  
		public void Preview() 
		{ 
			PrinterPageSetting	printerPageSetting;		 
			printerPageSetting = new PrinterPageSetting(mPrintDocument); 
			printerPageSetting.PrintPage += new PrintPageDelegate(this.PrintPageEventHandler); 
 
			printerPageSetting.ShowPrintPreviewDialog();		 
		} 
 
		//绘制		 
		private void PrintPageEventHandler(object obj,System.Drawing.Printing.PrintPageEventArgs ev) 
		{ 
			Graphics g = ev.Graphics ; 
			 
			this.mGraphics = g; 
 
			g.Clear(this.BackColor); 
 
			try 
			{	 
				bool blnMore = this.Draw(g); 
				 
				if (blnMore) 
				{ 
					ev.HasMorePages = true; 
					mCurrentPageIndex++; 
				} 
				else 
				{ 
					ev.HasMorePages = false;	 
					this.mCurrentPageIndex = 1; 
				} 
			} 
			catch(Exception e) 
			{ 
				System.Windows.Forms.MessageBox.Show(e.Message); 
			} 
		} 
 
 
		/// 对象打印接口 
		private void OutObject(IDraw outer) 
		{ 
//			this.mGraphics.ResetTransform(); 
			if (outer != null) 
			{ 
				outer.Graphics = this.mGraphics; 
				outer.PrintDocument = this.mPrintDocument; 
				outer.Sewing = this.Sewing; 
				outer.RectangleF = new RectangleF(X,Y,Width,outer.Height);	 
				outer.Draw(); 
				this.Y  += outer.RectangleF.Height; 
			} 
		} 
 
		#region 绘制过程 
 
		//*****这段代码确实太长了,应该用重构的手法进行处理,不过,我这里主要是让大家从头到尾的顺利的看下去 
		//*****在下一个版本的源代码中我会整理,大家也可以试一试。 
		private bool Draw(Graphics g) 
		{ 
			bool blnHasMorePage = false;		//是否还有下一页标记 
 
			if (this._body.Rows < 0) 
			{ 
				throw new Exception("打印主要网格不能为空,请用Body设置!"); 
			} 
 
			Printer printer = new Printer(); 
			printer.Graphics = g; 
			printer.PrintDocument = this.mPrintDocument; 
			printer.Sewing = this.Sewing; 
			 
			//初起打印起点坐标及打印区域的宽 
			Y = printer.PrinterMargins.Top; 
			X = printer.PrinterMargins.Left; 
			Width = printer.PrinterMargins.Width; 
 
			#region 画打印区域及装订线 
			if (IsPrinterMargins) 
			{ 
				printer.DrawPrinterMargins(); 
			} 
			if (IsSewingLine && _sewing.Margin > 0) 
			{ 
				//对象的线长小于0则自动设置 
				if (this._sewing.LineLen < 0) 
				{ 
					if (this._sewing.SewingDirection == SewingDirectionFlag.Left) 
					{ 
						this._sewing.LineLen = printer.PageHeight; 
					} 
					else if (this._sewing.SewingDirection == SewingDirectionFlag.Top) 
					{ 
						this._sewing.LineLen = printer.PageWidth; 
					} 
 
				} 
				printer.Sewing = this._sewing; 
				printer.DrawSewing(); 
			} 
			#endregion 
			 
			//正标题每页必重复打印,无需判断 
			if (_title != null) 
			{	 
				OutObject(_title); 
			} 
 
			if (_caption != null && (mCurrentPageIndex == 1 || _caption.IsDrawAllPage)) 
			{ 
				if (_caption != null) 
				{	 
					if (_title != null) 
					{ 
						_caption.MoveY = this._title.Height + 5; 
					} 
					OutObject(_caption); 
				} 
			} 
 
			if (_title != null || _caption != null) 
			{ 
				Y += 20;	//标题与下面有一定距离 
			} 
 
			if (_top != null && (mCurrentPageIndex == 1 || _top.IsDrawAllPage)) 
			{ 
				OutObject(_top); 
			} 
 
			if (_header != null && (mCurrentPageIndex == 1 || _header.IsDrawAllPage)) 
			{ 
				OutObject(_header); 
			} 
 
			if (_title != null || _caption != null || _top.IsDrawAllPage || _header.IsDrawAllPage) 
			{ 
				Y += 5;	//网格与页头距离 
			} 
 
			if (_multiHeader != null && (mCurrentPageIndex == 1 || _multiHeader.IsDrawAllPage)) 
			{ 
				OutObject(_multiHeader); 
				 
			} 
 
			#region 主体数据网格 
 
			//计算有效高度,便于分页 
			float validHeight = printer.PrinterMargins.Height - (Y - printer.PrinterMargins.Top); 
			if(_footer != null && _footer.IsDrawAllPage) 
			{ 
				validHeight -= this._footer.Height; 
			} 
			if(_bottom != null && _bottom.IsDrawAllPage) 
			{ 
				validHeight -= this._bottom.Height; 
			} 
			if (validHeight < 0) 
			{ 
				throw new Exception("预留给打印主要网格的空间太小,请适当调整!");			 
			} 
 
			//有效高度中当前页行数 
			int mRowsInCurPage = 0; 
			mRowsInCurPage = (int)(validHeight/(float)(this._body.RowHeight)); 
 
			//如果指定每页行数,则以其为主 
			if (this.RowsPerPage > 0 && this.RowsPerPage < mRowsInCurPage) 
			{ 
				mRowsInCurPage = this.RowsPerPage; 
			} 
 
			if (this.IsSubTotalPerPage) 
			{ 
				mRowsInCurPage--; 
			} 
 
			//************以Body为主************ 
			string[,] mArrGridText;			//保留当前页文本,用于页小计 
			GoldPrinter.Body mbody; 
			 
			//如果指定每页行数,则以其为主 
			if (this.RowsPerPage > 0 && this.RowsPerPage < mRowsInCurPage) 
			{ 
				mbody = new Body(mRowsInCurPage,this._body.Cols); 
			} 
			else 
			{ 
				//否则自适应 
				if (mRowsInCurPage > (this._body.Rows - this.mCurrentRowIndex)) 
				{ 
					mRowsInCurPage = this._body.Rows - this.mCurrentRowIndex; 
				} 
				mbody = new Body(mRowsInCurPage,this._body.Cols);			 
			} 
			mbody.ColsAlignString = this._body.ColsAlignString; 
 
			//存当前页的二维文本 
			mArrGridText = new string[mRowsInCurPage,this._body.Cols]; 
			for(int i = 0 ; i < mRowsInCurPage && mCurrentRowIndex < this._body.Rows ; i++) 
			{ 
				for(int j = 0 ; j < this._body.Cols ; j++) 
				{ 
					mArrGridText[i,j] = this._body.GetText(mCurrentRowIndex,j); 
				}					 
				mCurrentRowIndex++; 
			} 
 
			mbody.GridText = mArrGridText; 
			OutObject(mbody);					 
 
			//判断是否要分页,只要数据网格行数据大于数据网格行指针,则还有下一页 
			if (mCurrentRowIndex < this._body.Rows) 
			{ 
				blnHasMorePage = true; 
			} 
 
			#region 打印每页小计,只需要将当前数组用循环累计就OK了,这段程序应专门重构为一个函数,读者可以自己试一试 
			if (_isSubTotalPerPage && _subTotalCol != "") 
			{ 
				try 
				{ 
					GoldPrinter.MultiHeader mhSubTotal = new MultiHeader(1,this._body.Cols); 
					mhSubTotal.Graphics = g; 
					mhSubTotal.PrintDocument = this.mPrintDocument; 
					mhSubTotal.Sewing = this._sewing;		 
 
					mhSubTotal.RectangleF = new RectangleF(X,Y,Width,mhSubTotal.Height);		 
					//循环 
					//.... 
					mhSubTotal.SetText(0,0,"本页小计"); 
					mhSubTotal.SetText(0,1,"本页小计"); 
				 
					string[] marrSubTotalCol = this._subTotalCol.Split(';'); 
					Double mdblSubTotal = 0f; 
					int mintCol = 0; 
 
					for(int i = 0 ; i < marrSubTotalCol.Length ; i ++) 
					{ 
						mintCol = int.Parse(marrSubTotalCol[i].Substring(0,1)); 
 
						for(int j = 0 ; j < mArrGridText.GetLength(0) ; j++) 
						{ 
							mdblSubTotal += Double.Parse(mArrGridText[j,mintCol]);					 
						} 
						mhSubTotal.SetText(0,mintCol,mdblSubTotal.ToString()); 
					} 
 
 
					mhSubTotal.Draw();			 
 
					Y += mhSubTotal.Height; 
				} 
				catch(Exception e) 
				{} 
			} 
			#endregion 
 
			#endregion  
 
			Y += 5;	//网格与页底距离 
 
 
			//打印页脚与最底 
			if (_footer != null) 
			{ 
				if (blnHasMorePage == false || _footer.IsDrawAllPage) 
				{	 
					//这里不再做判断了,读者自己对照Body的处理方法去试验,以加深理解,实际上应是注释的部分 
					OutObject(_footer); 
					/* 
					if (_footer.IsDrawAllPage) 
					{ 
						OutObject(_footer); 
					} 
					else 
					{ 
						//与Body同样的处理 
					} 
					*/ 
				} 
			} 
 
			if (_bottom != null) 
			{ 
				if (blnHasMorePage == false || _bottom.IsDrawAllPage) 
				{ 
					if (_bottom.IsDrawAllPage) 
					{ 
						OutObject(_bottom); 
					} 
					else 
					{ 
						//计算有效高度 
						validHeight = printer.PrinterMargins.Height - (Y - printer.PrinterMargins.Top); 
						if (validHeight < _bottom.Height) 
						{ 
							blnHasMorePage = true; 
						} 
						else 
						{ 
							OutObject(_bottom); 
						} 
						 
					} 
				} 
			} 
 
			//画边框 
			DrawBorder(g,this._multiHeader,mbody); 
 
			mbody = null; 
 
			return blnHasMorePage; 
		} 
		#endregion 
 
		private void DrawBorder(Graphics g,MultiHeader multiHeader,Body body) 
		{ 
			//网格边框矩阵 
			RectangleF mrecGridBorder; 
			float x,y,width,height; 
			 
			width = body.RectangleF.Width; 
			height = body.RectangleF.Height; 
			if (multiHeader != null) 
			{ 
				x = multiHeader.RectangleF.X; 
				y = multiHeader.RectangleF.Y; 
				height += multiHeader.RectangleF.Height; 
			} 
			else 
			{ 
				x = body.RectangleF.X; 
				y = body.RectangleF.Y; 
			} 
			if (this.IsSubTotalPerPage) 
			{ 
				GoldPrinter.MultiHeader m = new MultiHeader(1,1); 
				height += m.RowHeight; 
				m = null; 
			} 
			 
			mrecGridBorder = new RectangleF(x,y,width,height); 
			Pen pen = new Pen(Color.Black,1); 
 
			GoldPrinter.DrawRectangle dr = new DrawRectangle(); 
			dr.Graphics = g; 
			dr.RectangleF = mrecGridBorder; 
			dr.Pen = pen; 
 
			switch (GridBorder) 
			{ 
				case GridBorderFlag.Single: 
					dr.Draw(); 
					break; 
				case GridBorderFlag.SingleBold: 
					dr.Pen.Width = 2; 
					dr.Draw(); 
					if (multiHeader != null) 
					{ 
						dr.RectangleF = body.RectangleF; 
						dr.DrawTopLine(); 
					} 
					break; 
				case GridBorderFlag.Double: 
					dr.Draw(); 
					mrecGridBorder = new RectangleF(x-2,y-2,width+4,height+4); 
					dr.RectangleF = mrecGridBorder; 
					dr.Draw(); 
					break;				 
				case GridBorderFlag.DoubleBold: 
					dr.Draw(); 
					mrecGridBorder = new RectangleF(x-2,y-2,width+4,height+4); 
					dr.RectangleF = mrecGridBorder; 
					dr.Pen.Width = 2; 
					dr.Draw(); 
					break;				 
			} 
			 
		} 
 
 
		#region 将打印的相关信息输出WriteMetricsToConsole(PrintPageEventArgs ev) 
		/* 
		public void WriteMetricsToConsole(PrintPageEventArgs ev) 
		{ 
			Graphics g = ev.Graphics; 
			Console.WriteLine ("*****Information about the printer*****"); 
			Console.WriteLine("纸张的大小  ev.PageSettings.PaperSize:" + ev.PageSettings.PaperSize); 
			Console.WriteLine("打印分辨率  ev.PageSettings.PrinterResolution:" + ev.PageSettings.PrinterResolution); 
			Console.WriteLine("旋转的角度  ev.PageSettings.PrinterSettings.LandscapeAngle" + ev.PageSettings.PrinterSettings.LandscapeAngle); 
			Console.WriteLine(""); 
			Console.WriteLine ("*****Information about the page*****"); 
			Console.WriteLine("页面的大小  ev.PageSettings.Bounds:" + ev.PageSettings.Bounds);  
			Console.WriteLine("页面(同上)  ev.PageBounds:" + ev.PageBounds);  
			Console.WriteLine("页面的边距    ev.PageSettings.Margins.:" + ev.PageSettings.Margins);  
			Console.WriteLine("页面的边距    ev.MarginBounds:" + ev.MarginBounds);  
 
			Console.WriteLine("水平分辨率    ev.Graphics.DpiX:" + ev.Graphics.DpiX );  
			Console.WriteLine("垂直分辨率    ev.Graphics.DpiY:" + ev.Graphics.DpiY );  
 
			ev.Graphics.SetClip(ev.PageBounds); 
			Console.WriteLine("ev.Graphics.VisibleClipBounds:" + ev.Graphics.VisibleClipBounds); 
 
			SizeF drawingSurfaceSize = new SizeF( 
													ev.Graphics.VisibleClipBounds.Width * ev.Graphics.DpiX/100, 
													ev.Graphics.VisibleClipBounds.Height * ev.Graphics.DpiY/100); 
			Console.WriteLine("drawing Surface Size in Pixels" + drawingSurfaceSize); 
		} 
		*/ 
		#endregion 
 
	}//End class 
}//End Namespace