protected override void OnPrintPage(PrintPageEventArgs e) { base.OnPrintPage(e); if (m_PageCount == 0) { m_HeaderHeight = this.GetHeaderHeight(e.Graphics); m_TitleHeight = this.GetTitleHeight(e.Graphics); m_FooterHeight = this.GetFooterHeight(e.Graphics); m_PageCount = this.PrecalculatePageCount(e); m_PageNo = 1; } if (m_RangeToPrint.IsEmpty()) { return; } if (m_BorderPen == null) { m_BorderPen = new Pen(Color.Black); } RectangleF area = new RectangleF(e.MarginBounds.Left, e.MarginBounds.Top + m_HeaderHeight + (m_NextRowToPrint == RangeToPrint.Start.Row ? m_TitleHeight : 0), e.MarginBounds.Width, e.MarginBounds.Height - m_HeaderHeight - (m_NextRowToPrint == RangeToPrint.Start.Row ? m_TitleHeight : 0) - m_FooterHeight); this.DrawHeader(e.Graphics, new RectangleF(e.MarginBounds.Left, e.MarginBounds.Top, e.MarginBounds.Width, m_HeaderHeight), m_PageNo, m_PageCount); if (m_PageNo == 1) { this.DrawTitle(e.Graphics, new RectangleF(e.MarginBounds.Left, e.MarginBounds.Top + m_HeaderHeight, e.MarginBounds.Width, m_TitleHeight), m_PageNo, m_PageCount); } List <int> columnHasTopBorder = new List <int>(); List <int> rowHasLeftBorder = new List <int>(); RangeCollection printedRanges = new RangeCollection(); int pageFirstRow = m_NextRowToPrint; int pageFirstColumn = m_NextColumnToPrint; int pageLastColumn = RangeToPrint.End.Column; // Pre-calculate width of the table in current page float pageColumnWidth = 0; for (int i = m_NextColumnToPrint; i <= RangeToPrint.End.Column; i++) { float colWidth = this.GetColumnWidth(e.Graphics, i); if (i == m_NextColumnToPrint && colWidth > area.Width) { colWidth = area.Width; } if (pageColumnWidth + colWidth <= area.Width) { pageColumnWidth += colWidth; } else { break; } } // Support for fixed row repeat if (RepeatFixedRows && m_Grid.ActualFixedRows > RangeToPrint.Start.Row) { m_NextRowToPrint = RangeToPrint.Start.Row; } float curY = area.Top; while (m_NextRowToPrint <= RangeToPrint.End.Row) { // If repeated rows are printed, resume printing next rows if (RepeatFixedRows && m_NextRowToPrint >= m_Grid.ActualFixedRows && m_NextRowToPrint < pageFirstRow) { m_NextRowToPrint = pageFirstRow; } float rowHeight = this.GetRowHeight(e.Graphics, m_NextRowToPrint); // Check if row fits in current page if (curY + rowHeight > area.Bottom) { break; } float curX = area.Left; while (m_NextColumnToPrint <= pageLastColumn) { float colWidth = this.GetColumnWidth(e.Graphics, m_NextColumnToPrint); // Check if column fits in current page if (curX + colWidth > area.Right) { // If single column does not fit in page, force it if (m_NextColumnToPrint == pageFirstColumn) { colWidth = area.Right - curX; } else { pageLastColumn = m_NextColumnToPrint - 1; break; } } RectangleF cellRectangle; Position pos = new Position(m_NextRowToPrint, m_NextColumnToPrint); GridRange range = m_Grid.PositionToCellRange(pos); // Check if cell is spanned if (range.ColumnsCount > 1 || range.RowsCount > 1) { Size rangeSize = m_Grid.RangeToSize(range); // Is the first position, draw allways if (range.Start == pos) { cellRectangle = new RectangleF(curX, curY, rangeSize.Width, rangeSize.Height); printedRanges.Add(range); } else { // Draw only if this cell is not already drawn on current page if (!printedRanges.ContainsCell(pos)) { // Calculate offset float sX = curX; for (int i = pos.Column - 1; i >= range.Start.Column; i--) { float cw = this.GetColumnWidth(e.Graphics, i); sX -= cw; } float sY = curY; for (int i = pos.Row - 1; i >= range.Start.Row; i--) { float cw = this.GetRowHeight(e.Graphics, i); sY -= cw; } cellRectangle = new RectangleF(sX, sY, rangeSize.Width, rangeSize.Height); printedRanges.Add(range); } else { cellRectangle = RectangleF.Empty; } } } else { cellRectangle = new RectangleF(curX, curY, colWidth, rowHeight); } if (!cellRectangle.IsEmpty) { SourceGrid.Cells.ICellVirtual cell = this.m_Grid.GetCell(pos); if (cell != null) { CellContext ctx = new CellContext(m_Grid, pos, cell); RectangleF clip = new RectangleF(Math.Max(cellRectangle.Left, area.Left), Math.Max(cellRectangle.Top, area.Top), Math.Min(cellRectangle.Right, area.Left + pageColumnWidth) - Math.Max(cellRectangle.Left, area.Left), Math.Min(cellRectangle.Bottom, area.Bottom) - Math.Max(cellRectangle.Top, area.Top)); Region prevClip = e.Graphics.Clip; try { e.Graphics.Clip = new Region(clip); this.DrawCell(e.Graphics, ctx, cellRectangle); } finally { // Restore clip region e.Graphics.Clip = prevClip; } // Check if left border can be drawn in current page if (!ContainsInRange(rowHasLeftBorder, range.Start.Row, range.End.Row) && cellRectangle.Left >= area.Left) { e.Graphics.DrawLine(m_BorderPen, cellRectangle.Left, clip.Top, cellRectangle.Left, clip.Bottom); AddRange(rowHasLeftBorder, range.Start.Row, range.End.Row); } // Check if top border can be drawn in current page if (!ContainsInRange(columnHasTopBorder, range.Start.Column, range.End.Column) && cellRectangle.Top >= area.Top) { e.Graphics.DrawLine(m_BorderPen, clip.Left, cellRectangle.Top, clip.Right, cellRectangle.Top); AddRange(columnHasTopBorder, range.Start.Column, range.End.Column); } // Check if right border can be drawn in current page if (cellRectangle.Right <= area.Right) { e.Graphics.DrawLine(m_BorderPen, cellRectangle.Right, clip.Top, cellRectangle.Right, clip.Bottom); } // Check if bottom border can be drawn in current page if (cellRectangle.Bottom <= area.Bottom) { e.Graphics.DrawLine(m_BorderPen, clip.Left, cellRectangle.Bottom, clip.Right, cellRectangle.Bottom); } } } // Set next column position curX += colWidth; m_NextColumnToPrint++; } // Set next row Y position curY += rowHeight; m_NextRowToPrint++; m_NextColumnToPrint = pageFirstColumn; } // If we have not reached last column, we will continue on next page if (pageLastColumn != RangeToPrint.End.Column) { m_NextRowToPrint = pageFirstRow; m_NextColumnToPrint = pageLastColumn + 1; } else { m_NextColumnToPrint = RangeToPrint.Start.Column; } this.DrawFooter(e.Graphics, new RectangleF(e.MarginBounds.Left, e.MarginBounds.Bottom - m_FooterHeight, e.MarginBounds.Width, m_FooterHeight), m_PageNo, m_PageCount); // If we have not reached last row we will continue on next page e.HasMorePages = (m_NextRowToPrint <= RangeToPrint.End.Row); // If there are no more pages, release resources if (e.HasMorePages) { m_PageNo++; } }
public virtual void Export(GridVirtual grid, System.Drawing.Graphics graphics, GridRange rangeToExport, System.Drawing.Point destinationLocation) { if (rangeToExport.IsEmpty()) { return; } System.Drawing.Point cellPoint = destinationLocation; using (DevAge.Drawing.GraphicsCache graphicsCache = new DevAge.Drawing.GraphicsCache(graphics)) { for (int r = rangeToExport.Start.Row; r <= rangeToExport.End.Row; r++) { int rowHeight = grid.Rows.GetHeight(r); for (int c = rangeToExport.Start.Column; c <= rangeToExport.End.Column; c++) { Rectangle cellRectangle; Position pos = new Position(r, c); Size cellSize = new Size(grid.Columns.GetWidth(c), rowHeight); GridRange range = grid.PositionToCellRange(pos); //support for RowSpan or ColSpan //Note: for now I draw only the merged cell at the first position // (this can cause a problem if you export partial range that contains a partial merged cells) if (range.ColumnsCount > 1 || range.RowsCount > 1) { //Is the first position if (range.Start == pos) { Size rangeSize = grid.RangeToSize(range); cellRectangle = new Rectangle(cellPoint, rangeSize); } else { cellRectangle = Rectangle.Empty; } } else { cellRectangle = new Rectangle(cellPoint, cellSize); } if (cellRectangle.IsEmpty == false) { Cells.ICellVirtual cell = grid.GetCell(pos); CellContext context = new CellContext(grid, pos, cell); ExportCell(context, graphicsCache, cellRectangle); } cellPoint = new Point(cellPoint.X + cellSize.Width, cellPoint.Y); } cellPoint = new Point(destinationLocation.X, cellPoint.Y + rowHeight); } } }