/// <summary> /// Calculates the actual spreadsheet range that will be printed. This is given by: /// 1)If you specified non zero values on PrintRange, this will be used. /// 2)If any value in PrintRange is zero and there is a Print Area defined on the /// spreadsheet, the Print Area will be used. /// 3)If there is no PrintRange and no Print Area defined, the visible cells on the /// sheet will be printed. /// </summary> ///<returns>The area that will be exported.</returns> public TXlsCellRange CalcPrintArea() { Workbook.Recalc(false); PdfCanvas = new PdfWriter(); PdfGraphics RealCanvas = new PdfGraphics(PdfCanvas); PrepareCanvas(); IFlxGraphics aCanvas = RealCanvas; FRenderer.SetCanvas(aCanvas); try { FRenderer.CreateFontCache(); try { return(FRenderer.InternalCalcPrintArea(FPrintRange)[0]); } finally { FRenderer.DisposeFontCache(); } } finally { FRenderer.SetCanvas(null); } }
/// <summary> /// Exports the associated xls workbook to a graphics stream. You need to provide a /// Graphics object with the correct dimensions. (To get the needed dimensions, use <see cref="GetRealPageSize()"/> /// </summary> /// <param name="imgData">Graphics where the image will be stored. Set it to null to skip the page.</param> /// <param name="exportInfo"> Information needed to export, cached for speed. The first time you call this method (or when you change xls.ActiveSheet), make exportInfo=null</param> public bool ExportNext(Graphics imgData, ref TImgExportInfo exportInfo) { FRenderer.CreateFontCache(); try { Bitmap bmp = null; try { if (imgData == null) { bmp = BitmapConstructor.CreateBitmap(1, 1); imgData = Graphics.FromImage(bmp); imgData.PageUnit = GraphicsUnit.Point; } IFlxGraphics aCanvas = new GdiPlusGraphics(imgData); GraphicsUnit OriginalUnits = imgData.PageUnit; try { imgData.PageUnit = GraphicsUnit.Point; FRenderer.SetCanvas(aCanvas); try { if (exportInfo == null) { exportInfo = GetExportInfo(aCanvas); } exportInfo.IncCurrentPage(); if (exportInfo.CurrentPage > exportInfo.TotalPages) { return(false); } int SaveActiveSheet = Workbook.ActiveSheet; try { Workbook.ActiveSheet = exportInfo.CurrentSheet; int CurrentLogicalPage = -1; if (ResetPageNumberOnEachSheet) { CurrentLogicalPage = exportInfo.ActiveSheet.FCurrentPage; } else { CurrentLogicalPage = exportInfo.CurrentPage; } TOneImgExportInfo OneResult = exportInfo.ActiveSheet; if (LastInitSheet != exportInfo.CurrentSheet) { TXlsCellRange ra; int p; RectangleF[] r; FRenderer.InitializePrint(aCanvas, OneResult.PageBounds, OneResult.PageBounds, OneResult.PrintRanges, out r, out p, out ra); LastInitSheet = exportInfo.CurrentSheet; } if (bmp == null) { OnBeforePaint(new ImgPaintEventArgs(imgData, CalcPageBounds(exportInfo.ActiveSheet.PageBounds), exportInfo.CurrentPage, exportInfo.ActiveSheet.CurrentPage, exportInfo.TotalPages)); } FRenderer.GenericPrint(aCanvas, OneResult.PageBounds, OneResult.PrintRanges, CurrentLogicalPage, OneResult.PaintClipRect, exportInfo.TotalLogicalPages(ResetPageNumberOnEachSheet), bmp == null, OneResult.PagePrintRange, ref OneResult.FCurrentPrintArea); aCanvas.ResetClip(); if (bmp == null) { OnAfterPaint(new ImgPaintEventArgs(imgData, CalcPageBounds(exportInfo.ActiveSheet.PageBounds), exportInfo.CurrentPage, exportInfo.ActiveSheet.CurrentPage, exportInfo.TotalPages)); } } finally { Workbook.ActiveSheet = SaveActiveSheet; } } finally { FRenderer.SetCanvas(null); } } finally { imgData.PageUnit = OriginalUnits; } } finally { if (bmp != null) { bmp.Dispose(); imgData.Dispose(); } } } finally { FRenderer.DisposeFontCache(); } return(true); }
/// <summary> /// Raises the <see cref="PrintDocument.PrintPage"/> event. It is called before a page prints. /// </summary> /// <remarks> /// This method is overridden to print an Excel document. /// After doing its own work, it will call <see cref="PrintDocument.PrintPage"/> so you can draw your own thing over it. /// </remarks> /// <param name="e">A <see cref="PrintPageEventArgs"/> that contains the event data.</param> protected override void OnPrintPage(PrintPageEventArgs e) { // There is a bug in Vs2005 (but not in 2003) where the VisibleClipBounds property does not change with the PageUnit, and it remains the same as when the graphics was created. // See http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=230594 (VisibleClipBounds does not produce correct results for different PageUnit) // So, we are going to store the VisibleClipBounds here. It looks like if we do not call e.Graphics.Save, things work fine. // Other bug in the framework (and this is also in .NET 1.1) //This code alone in an OnPrintPage event: /* * e.Graphics.PageUnit=GraphicsUnit.Inch; * RectangleF r = e.Graphics.VisibleClipBounds; * e.Graphics.PageUnit=GraphicsUnit.Point; * * Font fnt = new Font("arial", 12, FontStyle.Underline); * e.Graphics.DrawString("hello", fnt, Brushes.Tomato, 100, 100); * * will not print the underline, even if printing to a virtual printer. * (preview will work fine). If instead of GraphicsUnit.Inch we use GraphicsUnit.Display, * Underline gets drawn in the wrong place! * * Using GraphicsUnit.Point in both places seems to fix it. */ RectangleF VisibleClipInches100; GraphicsUnit SaveUnits = e.Graphics.PageUnit; try { e.Graphics.PageUnit = GraphicsUnit.Point; //NEEDS TO BE Point, since this is what we will use later. Other unit will confuse GDI+. VisibleClipInches100 = e.Graphics.VisibleClipBounds; VisibleClipInches100 = new RectangleF(VisibleClipInches100.X / 72F * 100, VisibleClipInches100.Y / 72F * 100, VisibleClipInches100.Width / 72F * 100, VisibleClipInches100.Height / 72F * 100); } finally { e.Graphics.PageUnit = SaveUnits; } if (FRenderer == null || FRenderer.Workbook == null) { return; } System.Drawing.Drawing2D.GraphicsState InitialState = e.Graphics.Save(); try { IFlxGraphics aCanvas = new GdiPlusGraphics(e.Graphics); //We could change the interpolation mode for images here. //e.Graphics.InterpolationMode = InterpolationMode.HighQualityBilinear; //e.Graphics.SmoothingMode = SmoothingMode.HighQuality; //e.Graphics.PageUnit=GraphicsUnit.Display; //Display is not reliable as unit as it might change depending on the device. We will be using Point. e.Graphics.PageUnit = GraphicsUnit.Point; if (AntiAliasedText) { e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; } if (CurrentSheetPage == 1) { FRenderer.SetCanvas(aCanvas); MyPrintRange = FRenderer.InternalCalcPrintArea(FPrintRange); if (CurrentWorkbookPage == 1 && AllVisibleSheets) { TotalWorkbookPages = GetPagesToPrint(e, aCanvas, VisibleClipInches100); } FRenderer.InitializePrint(aCanvas, ConvertToUnits(e.PageBounds, false), ConvertToMargins(e.Graphics, e.PageBounds, VisibleClipInches100, false), MyPrintRange, out PaintClipRect, out TotalSheetPages, out PagePrintRange); if (!AllVisibleSheets) { TotalWorkbookPages = TotalSheetPages; } PagesToPrint = TotalWorkbookPages; if (CurrentWorkbookPage == 1) //skip the first non printing pages. { if (PrinterSettings.FromPage > 0 && PrinterSettings.ToPage >= PrinterSettings.FromPage) { PagesToPrint = Math.Min(PrinterSettings.ToPage, TotalWorkbookPages); for (int i = 1; i < PrinterSettings.FromPage; i++) { if (CurrentWorkbookPage > TotalWorkbookPages) { return; } OnBeforePrintPage(e); FRenderer.GenericPrint(aCanvas, ConvertToUnits(e.PageBounds, false), MyPrintRange, 0, PaintClipRect, 0, false, PagePrintRange, ref CurrentPrintArea); IncCurrentPage(); } } } } if (CurrentWorkbookPage <= PagesToPrint) { int CurrentPage = ResetPageNumberOnEachSheet ? CurrentSheetPage : CurrentWorkbookPage; int TotalPages = ResetPageNumberOnEachSheet ? TotalSheetPages : TotalWorkbookPages; OnBeforePrintPage(e); FRenderer.GenericPrint(aCanvas, ConvertToUnits(e.PageBounds, false), MyPrintRange, CurrentPage, PaintClipRect, TotalPages, true, PagePrintRange, ref CurrentPrintArea); IncCurrentPage(); } e.HasMorePages = CurrentWorkbookPage <= PagesToPrint; } finally { e.Graphics.Restore(InitialState); } base.OnPrintPage(e); }