/// <summary> /// 输出到指定页面 /// </summary> /// <param name="p_page"></param> public void Output(RptPage p_page) { foreach (RptTextInst item in _children) { item.OutputHeader(p_page); } }
/// <summary> /// 切换页面时在新页重复表头 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void OnPageBegin(object sender, RptPage e) { if (_header != null && (_item as RptTable).RepeatHeader) { int index = _data.Current; RptTblHeaderInst inst = _header.Clone() as RptTblHeaderInst; RptRegion region = new RptRegion( e.Rows.Start, _region.Col, inst.Item.RowSpan, inst.Item.ColSpan); inst.Region = region; double height = _item.Part.GetRowHeight(region.Row + region.RowSpan - e.Rows.Start); if (e.Rows.Size.Count > 0 && height != e.Rows.Size[0]) { e.Rows.Size[0] = height; } inst.Output(); _data.Current = index; // 顺次下移 if (_curPart != null) { _curPart.Region.Row = region.Row + region.RowSpan; } } }
/// <summary> /// 创建输出页面 /// </summary> /// <param name="p_x"></param> /// <param name="p_y"></param> /// <returns></returns> RptPage CreatePage(int p_x, int p_y) { if (p_x >= PageCols) { PageCols = p_x + 1; } RptPage page = new RptPage(p_x, p_y, this); Pages.Add(page); if (p_x > 0) { HorPageBegin?.Invoke(this, page); } if (p_y > 0) { VerPageBegin?.Invoke(this, page); } // 输出新页面时重复页眉页脚 if (Header != null) { Header.Clone().Output(page); } if (Footer != null) { Footer.Clone().Output(page); } return(page); }
/// <summary> /// 输出报表项 /// </summary> /// <param name="p_item">报表项</param> public void OutputItem(RptOutputInst p_item) { PrepareItem(p_item); // 报表项所在页位置 int pageX = GetPageIndex(Cols, p_item.Region.Col); int pageY = GetPageIndex(Rows, p_item.Region.Row); RptPage page = GetPage(pageX, pageY); if (page == null) { page = CreatePage(pageX, pageY); } if (p_item.Parent is RptTblRowInst && p_item.Region.Row != p_item.Parent.Region.Row) { p_item.Region.Row = p_item.Parent.Region.Row; } page.AddItem(p_item); }
/// <summary> /// 切换页面时在新页重复行头 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void OnHorPageBegin(object sender, RptPage e) { RptMatrix matrix = base._item as RptMatrix; if (!matrix.HideRowHeader && matrix.RepeatRowHeader) { _isHasHorBreak = true; RptRootInst root = sender as RptRootInst; //不存在定义,取第一页定义添加到当前页定义 //添加的定义应该以矩阵开始行(列)为开始位置 if (!e.IsColHasDefine()) { e.Cols.Size.InsertRange(0, root.Cols[0].Size.GetRange(matrix.Col, matrix.RowHeader.ColSpan)); } else if (!e.IsRowHasDefine()) { e.Rows.Size.InsertRange(0, root.Rows[0].Size.GetRange(matrix.Row, matrix.ColHeader.RowSpan)); } int span = matrix.RowHeader.ColSpan; int start = e.Cols.Start; //外层列号变更 if (_outPutPart == MtxOutPutPart.Cells) { _regCells.Col = start + span; } else { _regColHeader.Col = start + span; } //再次递归调用时确保数据完整 //行头Region RptRegion headerClone = _regRowHeader.Clone(); //数据源记录索引 int index = RptData.Current; //外部输出的行头索引 int rowIndex = _rowIndex; //外部正在输出的部分 RptMtxHeaderInst curPart = _rowPart; if (!matrix.HideColHeader && !matrix.HideRowHeader) { RptTextInst newCorner = CornerInst.Clone(); newCorner.Region = new RptRegion(_regRowHeader.Row - matrix.ColHeader.RowSpan, start, matrix.ColHeader.RowSpan, matrix.RowHeader.ColSpan); newCorner.Output(); } //从已输出的索引处开始输出 for (int i = rowIndex; i < RowHeaderInsts.Count; i++) { RptMtxHeaderInst instClone = RowHeaderInsts[i].Clone(); _rowPart = instClone; instClone.Region = new RptRegion(_regRowHeader.Row, start, instClone.Item.RowSpan, instClone.Item.ColSpan); //输出过程中可能触发分页事件,提前计算新行位置,输出后还原 _regRowHeader.Row += matrix.ColHeader.RowSpan; instClone.Output(); _regRowHeader.Row -= matrix.ColHeader.RowSpan; _regRowHeader.Row += 1; //下次输出位置已经输出过,不再输出 if (_rowUsed.Contains(_regRowHeader.Row) && _colUsed.Contains(start)) { break; } _rowIndex++; } _rowPart = curPart; _rowIndex = rowIndex; RptData.Current = index; _regRowHeader = headerClone.Clone(); //后移 span 个格 if (_outPutPart == MtxOutPutPart.Cells) { _cellPart.Region.Col = start + span; } else { _colPart.TxtInsts[0].Region.Col = start + span; } //将占用列加入到列表 for (int i = 0; i < span; i++) { if (!_colUsed.Contains(start + i)) { _colUsed.Add(start + i); } } } }
/// <summary> /// 切换页面时在新页重复列头 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void OnVerPageBegin(object sender, RptPage e) { RptMatrix matrix = base._item as RptMatrix; if (!matrix.HideColHeader && matrix.RepeatColHeader) { RptRootInst root = sender as RptRootInst; //当不存在水平分页时,加入列头的定义 if (!_isHasHorBreak) { e.Rows.Size.InsertRange(0, root.Rows[0].Size.GetRange(matrix.Row, matrix.ColHeader.RowSpan)); } int span = matrix.ColHeader.RowSpan; int start = e.Rows.Start; //外层列号变更 if (_outPutPart == MtxOutPutPart.Cells) { _regCells.Row = start + span; } else { _regRowHeader.Row = start + span; } //再次递归调用时确保数据完整 //行头Region RptRegion headerClone = _regColHeader.Clone(); //数据源记录索引 int index = RptData.Current; //外部输出的列头索引 int colIndex = _colIndex; //外部正在输出的部分 RptMtxHeaderInst curPart = _colPart; if (!matrix.HideColHeader && !matrix.HideRowHeader) { RptTextInst newCorner = CornerInst.Clone(); newCorner.Region = new RptRegion(start, _regColHeader.Col - matrix.RowHeader.ColSpan, matrix.ColHeader.RowSpan, matrix.RowHeader.ColSpan); newCorner.Output(); } for (int i = _colIndex; i < ColHeaderInsts.Count; i++) { RptMtxHeaderInst instClone = ColHeaderInsts[i].Clone(); _colPart = instClone; instClone.Region = new RptRegion(start, _regColHeader.Col, instClone.Item.RowSpan, instClone.Item.ColSpan); //输出过程中可能触发分页事件,提前计算新列位置,输出后还原 _regColHeader.Col += matrix.RowHeader.ColSpan; instClone.Output(); _regColHeader.Col -= matrix.RowHeader.ColSpan; _regColHeader.Col += 1; //下次输出位置已经输出过,不再输出 if (_colUsed.Contains(_regColHeader.Col) && _rowUsed.Contains(start)) { break; } _colIndex++; } _colPart = curPart; _colIndex = colIndex; RptData.Current = index; _regColHeader = headerClone.Clone(); //后移 span 个格 if (_outPutPart == MtxOutPutPart.Cells) { _cellPart.Region.Row = start + span; } else { _rowPart.TxtInsts[0].Region.Row = start + span; } //将占用行加入到列表 for (int i = 0; i < span; i++) { if (!_rowUsed.Contains(start + i)) { _rowUsed.Add(start + i); } } } }
/// <summary> /// 输出到指定页的页脚 /// </summary> /// <param name="p_page"></param> public void OutputFooter(RptPage p_page) { _page = p_page; p_page.FooterItems.Add(this); ParseValue(); }
/// <summary> /// 自动行高时重置行高,前提: /// 1. AutoHeight为true /// 2. 只占一行 /// 3. 当前输出位置在页的末尾 /// 4. 测量高度大于原高度 /// </summary> /// <param name="p_item"></param> /// <param name="p_height"></param> public void SyncRowHeight(RptTextInst p_item, double p_height) { PageDefine rows = p_item.Page.Rows; RptRegion region = p_item.Region; // 只支持当前输出位置在页的末尾,非末尾情况效率太低! if (region.Row != rows.Start + rows.Count - 1) { return; } // 无需调整 int index = rows.Count - 1; if (p_height <= rows.Size[index] || _pageEnding) { return; } // 上部高度 double topHeight = 0; for (int i = 0; i < index; i++) { topHeight += rows.Size[i]; } // 当前页能放下 if (topHeight + p_height <= BodyHeight - TblFooterHeight) { rows.Size[index] = p_height; return; } // 需要垂直分页 // 记录同行项 RptPage prePage = p_item.Page; var sameRowItems = (from item in prePage.Items where item.Region.Row == region.Row select item).ToList(); rows.Size.RemoveAt(index); if (VerPageEnd != null) { _pageEnding = true; VerPageEnd(this, rows); _pageEnding = false; } PageDefine next = new PageDefine(); next.Start = rows.Start + rows.Count; Rows.Add(next); // 重新计算行位置 int newIndex = next.Start + next.Count; double validHeight = BodyHeight - TblFooterHeight - next.Size.Sum(); if (p_height > validHeight) { p_height = validHeight; } next.Size.Add(p_height); // 处理同行项 RptPage page = CreatePage(prePage.X, prePage.Y + 1); foreach (var item in sameRowItems) { item.Region.Row = newIndex; prePage.Items.Remove(item); page.AddItem(item); } }