/// <summary> /// /// </summary> /// <param name="p_def"></param> /// <param name="p_index"></param> /// <returns></returns> int GetPageIndex(List <PageDefine> p_def, int p_index) { for (int i = 0; i < p_def.Count; i++) { PageDefine def = p_def[i]; if (p_index >= def.Start && p_index < def.Start + def.Count) { return(i); } } throw new Exception("给定位置不在页面中!"); }
/// <summary> /// 垂直分页 /// </summary> /// <param name="p_rowPage"></param> /// <param name="p_topHeight"></param> /// <param name="p_inItem"></param> void VerPageBreak(ref PageDefine p_rowPage, ref double p_topHeight, bool p_inItem = true) { // 上页结束 if (p_inItem && VerPageEnd != null) { _pageEnding = true; VerPageEnd(this, p_rowPage); _pageEnding = false; } PageDefine next = new PageDefine(); next.Start = p_rowPage.Start + p_rowPage.Count; Rows.Add(next); p_topHeight = 0; p_rowPage = next; }
/// <summary> /// 水平分页 /// </summary> /// <param name="p_colPage"></param> /// <param name="p_leftWidth"></param> /// <param name="p_inItem"></param> void HorPageBreak(ref PageDefine p_colPage, ref double p_leftWidth, bool p_inItem = true) { //上页结束 if (p_inItem && HorPageEnd != null) { _pageEnding = true; HorPageEnd(this, p_colPage); _pageEnding = false; } PageDefine next = new PageDefine(); next.Start = p_colPage.Start + p_colPage.Count; Cols.Add(next); p_leftWidth = 0; p_colPage = next; }
/// <summary> /// 切换页面时在旧页重复表尾 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> void OnPageEnd(object sender, PageDefine e) { if (_footer != null && (_item as RptTable).RepeatFooter) { int index = _data.Current; RptTblFooterInst inst = _footer.Clone() as RptTblFooterInst; RptRegion region = new RptRegion( e.Start + e.Count, _region.Col, inst.Item.RowSpan, inst.Item.ColSpan); inst.Region = region; inst.Output(); _data.Current = index; // 顺次下移 if (_curPart != null) { _curPart.Region.Row = region.Row + region.RowSpan; } } }
/// <summary> /// 是否需要垂直分页 /// </summary> /// <param name="p_item"></param> /// <returns></returns> public bool TestPageBreak(RptItemInst p_item) { RptRegion region = p_item.Region; PageDefine rowPage = Rows[Rows.Count - 1]; int lastRow = rowPage.Start + rowPage.Count; int deltaRow = region.Row + region.RowSpan - lastRow; RptItemBase item = p_item.Item; double topHeight = 0; if (deltaRow > 0) { topHeight = rowPage.Size.Sum(); } else { for (int i = 0; i < region.Row - rowPage.Start; i++) { topHeight += rowPage.Size[i]; } } return(topHeight + item.Height > BodyHeight - TblFooterHeight); }
/// <summary> /// 渲染输出 /// </summary> public void Render() { int start; RptRootInst inst = _info.Inst; List <double> rows = new List <double>(); // 填充空行空列,统计所有行高列宽 foreach (PageDefine page in inst.Rows) { // 页面之间的缝隙,为避免打印时分页边框不正常! rows.Add(RptRootInst.PageGap); // 记录页面开始行索引 start = rows.Count; page.Offset = start; // 页眉行 if (inst.HeaderHeight > 0) { rows.Add(inst.HeaderHeight); } // 内容行 double total = 0; foreach (double height in page.Size) { rows.Add(height); total += height; } // 填充空行 if (total < inst.BodyHeight) { rows.Add(inst.BodyHeight - total); } // 页脚行 if (inst.FooterHeight > 0) { rows.Add(inst.FooterHeight); } page.Total = rows.Count - start; } List <double> cols = new List <double>(); foreach (PageDefine page in inst.Cols) { // 页面之间的左侧间隔缝隙 cols.Add(RptRootInst.PageGap); // 记录页面开始列索引 start = cols.Count; page.Offset = start; double total = 0.0; foreach (double width in page.Size) { cols.Add(width); total += width; } // 填充空列 if (total < inst.BodyWidth) { cols.Add(inst.BodyWidth - total); } page.Total = cols.Count - start; } // 创建Worksheet _ws = new Worksheet(rows.Count, cols.Count); // 不显示选择区黑框和触摸时的两圈,改用 Excel.ShowSelection 控制 //_ws.SelectionBorderColor = Colors.Transparent; //_ws.TouchSelectionGripperBackgroundColor = Colors.Transparent; // 单元格不可编辑,图表可拖动 _ws.LockCell = true; // Wp始终不可编辑 if (Kit.IsPhoneUI) { _ws.Protect = true; } _info.Sheet = _ws; // 初始化行高列宽 for (int i = 0; i < rows.Count; i++) { _ws.Rows[i].Height = rows[i]; } for (int i = 0; i < cols.Count; i++) { _ws.Columns[i].Width = cols[i]; } // 输出所有项 foreach (RptPage page in _info.Inst.Pages) { PageDefine define = page.Rows; int startRow = define.Start; int offsetRow = define.Offset; int rowTotal = define.Total; int offsetBody = offsetRow + (page.HeaderItems.Count > 0 ? 1 : 0); define = page.Cols; int startCol = define.Start; int offsetCol = define.Offset; page.UpdatePageNum(); // 页眉 if (page.HeaderItems.Count > 0) { foreach (RptTextInst item in page.HeaderItems) { // 不渲染超出的列 int tempCol = offsetCol + item.Item.Col; if (tempCol < cols.Count) { RenderText(item, offsetRow, tempCol); } } } // 内容 foreach (RptOutputInst item in page.Items) { RptChartInst chart; int row = item.Region.Row - startRow + offsetBody; int col = item.Region.Col - startCol + offsetCol; RptTextInst txt = item as RptTextInst; if (txt != null) { Cells.Data.Cell tmpCell; CellRange range; RptText text = txt.Item as RptText; var dataRow = (txt.Item as RptText).Data; var renderCell = RenderText(txt, row, col); if (row > startRow && dataRow.Bool("hidetopdup")) { tmpCell = _ws[row - 1, col]; if (tmpCell.Tag != null && txt.Item.Data.Bool("hidetopdup") && tmpCell.Text == renderCell.Text) { range = _ws.GetSpanCell(row - 1, col); if (range != null) { tmpCell = _ws[range.Row, range.Column]; } if (tmpCell.ColumnSpan == renderCell.ColumnSpan) { tmpCell.RowSpan += renderCell.RowSpan; } } } if (col > startCol && dataRow.Bool("hideleftdup")) { tmpCell = _ws[row, col - 1]; if (tmpCell.Tag != null && txt.Item.Data.Bool("hidetopdup") && tmpCell.Text == renderCell.Text) { range = _ws.GetSpanCell(row, col - 1); if (range != null) { tmpCell = _ws[range.Row, range.Column]; } if (tmpCell.RowSpan == renderCell.RowSpan) { tmpCell.ColumnSpan += renderCell.ColumnSpan; } } } } else if ((chart = (item as RptChartInst)) != null) { ((RptChart)chart.Item).Render(_ws, row, col); } } // 页脚 if (page.FooterItems.Count > 0) { foreach (RptTextInst item in page.FooterItems) { // 不渲染超出的列 int tempCol = offsetCol + item.Item.Col; if (tempCol < cols.Count) { RenderText(item, offsetRow + rowTotal - 1, tempCol); } } } } }
/// <summary> /// 补充报表项及左上的行列定义,处理分页 /// </summary> /// <param name="p_item"></param> void PrepareItem(RptItemInst p_item) { RptRegion region = p_item.Region; RptItemBase item = p_item.Item; PageDefine rowPage = Rows[Rows.Count - 1]; PageDefine colPage = Cols[Cols.Count - 1]; int lastRow = rowPage.Start + rowPage.Count; int lastCol = colPage.Start + colPage.Count; int deltaRow = region.Row + region.RowSpan - lastRow; int deltaCol = region.Col + region.ColSpan - lastCol; //已经垂直分页 if (region.Row < rowPage.Start && region.Row + region.RowSpan > rowPage.Start) { deltaRow = region.RowSpan - rowPage.Count; region.Row = rowPage.Start; } //已经水平分页 if (region.Col < colPage.Start && region.Col + region.ColSpan > colPage.Start) { deltaCol = region.ColSpan - colPage.Count; region.Col = colPage.Start; } // 无需补充 if (deltaRow <= 0 && deltaCol <= 0) { return; } // 补充行定义 if (deltaRow > 0) { // 页面已有的总高 double topHeight = rowPage.Size.Sum(); int blankRow = deltaRow - region.RowSpan; double heights = 0; if (blankRow < 0) { for (int i = 0; i < deltaRow; i++) { heights += item.Part.GetRowHeight(item.Row + item.RowSpan - deltaRow + i); } //需要分页 if (!_pageEnding && topHeight + heights > (BodyHeight - TblFooterHeight) && region.Row != rowPage.Start) { VerPageBreak(ref rowPage, ref topHeight); //从元素的起始位置开始分页 for (int j = 0; j < region.RowSpan; j++) { double height = item.Part.GetRowHeight(item.Row + j); rowPage.Size.Add(height); topHeight += height; } } else { //不需要分页 for (int i = 0; i < deltaRow; i++) { double height = item.Part.GetRowHeight(item.Row + item.RowSpan - deltaRow + i); if (topHeight + height > (BodyHeight - TblFooterHeight))//元素高度大于页面高度,截断 { height = (BodyHeight - TblFooterHeight - topHeight) < 0 ? 0 : BodyHeight - TblFooterHeight - topHeight; } rowPage.Size.Add(height); topHeight += height; } } } else { for (int i = 0; i < deltaRow; i++) { double height = item.Part.GetRowHeight(item.Row + item.RowSpan - deltaRow + i); if (i == blankRow) { for (int j = i; j < deltaRow; j++) { heights += item.Part.GetRowHeight(item.Row + item.RowSpan - deltaRow + j); } } // 在报表项上 bool inItem = lastRow + i >= region.Row; if (height > BodyHeight - TblFooterHeight) { height = BodyHeight - TblFooterHeight; } if (i == blankRow && heights > BodyHeight - TblFooterHeight) { heights = BodyHeight - TblFooterHeight; } // 需要垂直分页 bool verBreak = (i == blankRow) ? (topHeight + heights > BodyHeight - TblFooterHeight) : (topHeight + height > BodyHeight - TblFooterHeight); if (!_pageEnding && verBreak) { VerPageBreak(ref rowPage, ref topHeight, inItem); } rowPage.Size.Add(height); topHeight += height; } } // 重新计算行位置 region.Row = rowPage.Start + rowPage.Count - region.RowSpan; } //补充列定义 if (deltaCol > 0) { // 页面已有的宽度 double leftWidth = colPage.Size.Sum(); int blankCol = deltaCol - region.ColSpan; double widths = 0; //不需要补充空行 if (blankCol < 0) { for (int i = 0; i < deltaCol; i++) { widths += Info.Root.Cols[item.Col + item.ColSpan - deltaCol + i]; } //需要分页 if (!_pageEnding && leftWidth + widths > BodyWidth && region.Col != colPage.Start) { HorPageBreak(ref colPage, ref leftWidth); //从元素的起始位置开始分页 for (int j = 0; j < region.ColSpan; j++) { double width = Info.Root.Cols[item.Col + j]; colPage.Size.Add(width); leftWidth += width; } } else { //不需要分页 for (int i = 0; i < deltaCol; i++) { double width = Info.Root.Cols[item.Col + item.ColSpan - deltaCol + i]; if (leftWidth + width > BodyWidth)//元素宽度大于页面宽度,截断 { width = (BodyWidth - leftWidth) < 0 ? 0 : BodyWidth - leftWidth; } colPage.Size.Add(width); leftWidth += width; } } } else { //需要空行补充 for (int i = 0; i < deltaCol; i++) { double width = Info.Root.Cols[item.Col + item.ColSpan - deltaCol + i]; if (i == blankCol) { for (int j = i; j < deltaCol; j++) { widths += Info.Root.Cols[item.Col + item.ColSpan - deltaCol + j]; } } // 在报表项上 bool inItem = lastCol + i >= region.Col; // 需要水平分页 bool horBreak = (i == blankCol) ? (leftWidth + widths > BodyWidth) : (leftWidth + width > BodyWidth); if (!_pageEnding && horBreak) { HorPageBreak(ref colPage, ref leftWidth, inItem); } colPage.Size.Add(width); leftWidth += width; } } // 重新计算列位置 region.Col = colPage.Start + colPage.Count - region.ColSpan; } }
/// <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); } }