public RptPage(int p_x, int p_y, RptRootInst p_root) { _root = p_root; X = p_x; Y = p_y; HeaderItems = new List <RptTextInst>(); Items = new List <RptOutputInst>(); FooterItems = new List <RptTextInst>(); }
/// <summary> /// 构造报表实例 /// </summary> /// <param name="p_inst"></param> public async Task Build(RptRootInst p_inst) { Inst = p_inst; await Header.Build(); await Body.Build(); await Footer.Build(); }
/// <summary> /// 输出单列表头表尾可重复表格布局 /// </summary> void OutputTable() { _region.RowSpan = 0; _data.Current = 0; RptRootInst root = Inst; RptRegion region; if (_header != null) { _header.Output(); region = _header.Region; _region.RowSpan = region.Row + region.RowSpan - _region.Row; } root.VerPageBegin += OnPageBegin; root.VerPageEnd += OnPageEnd; RptTable tbl = _item as RptTable; if (tbl.Footer != null && tbl.RepeatFooter) { root.TblFooterHeight = tbl.Footer.Height; } foreach (RptTblPartInst inst in _rows) { _curPart = inst; RptItemBase item = inst.Item; region = new RptRegion( _region.Row + _region.RowSpan, _region.Col, item.RowSpan, item.ColSpan); inst.Region = region; inst.Output(); _region.RowSpan = region.Row + region.RowSpan - _region.Row; } _curPart = null; root.TblFooterHeight = 0.0; root.VerPageBegin -= OnPageBegin; root.VerPageEnd -= OnPageEnd; if (_footer != null) { RptItemBase item = _footer.Item; region = new RptRegion( _region.Row + _region.RowSpan, _region.Col, item.RowSpan, item.ColSpan); _footer.Region = region; _footer.Output(); _region.RowSpan = region.Row + region.RowSpan - _region.Row; } _data.Current = 0; }
public override async Task Build() { RptRootInst inst = _part.Inst; if (string.IsNullOrEmpty(Tbl)) { return; } // 使用时再加载 var rptData = await inst.Info.GetData(Tbl); if (rptData == null) { return; } RptMatrixInst matrixInst = new RptMatrixInst(this); matrixInst.RptData = rptData; ReBuildData(matrixInst.RptData.Data); inst.Body.AddChild(matrixInst); if (!HideRowHeader && !HideColHeader) { RptTextInst corner = new RptTextInst(Corner.Item); matrixInst.CornerInst = corner; } //列头 BuildHeader(rptData, ColHeader, matrixInst); //行头 BuildHeader(rptData, RowHeader, matrixInst); //数据 foreach (RptMtxHeaderInst rowHeaderInst in matrixInst.RowHeaderInsts) { foreach (RptMtxHeaderInst colHeaderInst in matrixInst.ColHeaderInsts) { RptText cell = GetCellByRowCol(rowHeaderInst.MtxRowsRow, colHeaderInst.MtxRowsCol); if (cell != null) { RptTextInst txtInst = new RptTextInst(cell); Dictionary <string, string> filter = new Dictionary <string, string>(); foreach (string key in rowHeaderInst.Filter.Keys) { filter.Add(key, rowHeaderInst.Filter[key]); } foreach (string key in colHeaderInst.Filter.Keys) { filter.Add(key, colHeaderInst.Filter[key]); } txtInst.Filter = filter; matrixInst.AddCell(txtInst); } } } }
/// <summary> /// 构造报表项实例 /// </summary> public override Task Build() { RptRootInst inst = Root.Inst; RptTblHeaderInst header = new RptTblHeaderInst(this); if (inst.CurrentTable != null) { inst.CurrentTable.Header = header; } inst.CurrentParent = header; return(BuildChild()); }
/// <summary> /// 构造报表项实例 /// </summary> /// <param name="p_filter"></param> public Task Build(Dictionary <string, string> p_filter) { RptRootInst inst = Root.Inst; RptTblGroupHeaderInst header = new RptTblGroupHeaderInst(this); if (p_filter != null && p_filter.Count > 0) { header.Filter = p_filter; } if (inst.CurrentParent is RptTblPartInst) { header.Index = (inst.CurrentParent as RptTblPartInst).Index; } if (inst.CurrentTable != null) { inst.CurrentTable.AddRow(header); } inst.CurrentParent = header; return(BuildChild()); }
/// <summary> /// 构造报表项实例 /// </summary> public override async Task Build() { RptRootInst inst = _part.Inst; string tblName = _data.Str("tbl"); if (string.IsNullOrEmpty(tblName)) { return; } // 使用时再加载数据 var rptData = await inst.Info.GetData(tblName); if (rptData == null) { return; } // 无数据不加载 _part.Inst.Body.AddChild(new RptChartInst(this)); }
/// <summary> /// 构造报表项实例 /// </summary> public override Task Build() { RptRootInst inst = Root.Inst; RptTblRowInst row = new RptTblRowInst(this); RptTblRowInst preRow = inst.CurrentParent as RptTblRowInst; if (preRow == null) { RptTblPartInst prePart = inst.CurrentParent as RptTblPartInst; row.Index = (prePart == null || prePart.Index == 0) ? 0 : prePart.Index + 1; } else { row.Index = preRow.Index + 1; } if (inst.CurrentTable != null) { inst.CurrentTable.AddRow(row); } inst.CurrentParent = row; return(BuildChild()); }
/// <summary> /// 构造报表项实例 /// </summary> public override Task Build() { RptRootInst inst = _part.Inst; RptTextInst txt = new RptTextInst(this); if (_parent != null) { inst.CurrentParent.AddChild(txt); } else if (_part.PartType == RptPartType.Header) { inst.Header.AddChild(txt); } else if (_part.PartType == RptPartType.Footer) { inst.Footer.AddChild(txt); } else { inst.Body.AddChild(txt); } return(Task.CompletedTask); }
/// <summary> /// 输出报表项内容 /// </summary> protected override void DoOutput() { RptText item = _item as RptText; RptRootInst root = Inst; root.OutputItem(this); ParseValue(); if (!item.AutoHeight || _region.RowSpan > 1) { return; } // 处理自动行高 double height = 0; Kit.RunSync(() => { // 测量文本的实际高度 TextBlock tb = new TextBlock(); tb.TextWrapping = item.WordWrap ? TextWrapping.Wrap : TextWrapping.NoWrap; tb.FontFamily = new FontFamily(item.FontFamily); tb.FontSize = item.FontSize; if (item.Bold) { tb.FontWeight = FontWeights.Bold; } if (item.Italic) { tb.FontStyle = FontStyle.Italic; } tb.Text = Text; tb.Width = Width - 8 - item.Margin * 2; tb.Measure(new Size(double.MaxValue, double.MaxValue)); height = Math.Ceiling(tb.ActualHeight) + 4; }); root.SyncRowHeight(this, height); }
/// <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="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); } } } }
protected override void DoOutput() { RptRootInst root = Inst; RptMatrix matrix = base._item as RptMatrix; RptRegion regClone = _region.Clone(); _region.RowSpan = 0; _region.ColSpan = 0; //矩阵角 if (!matrix.HideColHeader && !matrix.HideRowHeader) { CornerInst.Region = new RptRegion(_region.Row, _region.Col, matrix.ColHeader.RowSpan, matrix.RowHeader.ColSpan); CornerInst.Output(); _region.RowSpan += matrix.Corner.RowSpan; _region.ColSpan += matrix.Corner.ColSpan; } root.HorPageBegin += OnHorPageBegin; root.VerPageBegin += OnVerPageBegin; _rowIndex = _colIndex = 0; //列头 //可能出现水平分页、垂直分页相互调用,所以行、列Region都定义 _regColHeader = regClone.Clone(); _regRowHeader = regClone.Clone(); if (!matrix.HideRowHeader) { _regColHeader.Col += matrix.RowHeader.ColSpan; } if (!matrix.HideColHeader) { _outPutPart = MtxOutPutPart.ColHeader; _regRowHeader.Row += matrix.ColHeader.RowSpan; foreach (RptMtxHeaderInst inst in ColHeaderInsts) { _colPart = inst; inst.Region = new RptRegion(_regColHeader.Row, _regColHeader.Col, inst.Item.RowSpan, inst.Item.ColSpan); inst.Output(); _regColHeader.Col += 1; _colIndex++; _region.ColSpan++; } } //行头 //可能出现水平分页、垂直分页相互调用,所以行、列Region都定义 _colIndex = 0; _regColHeader = regClone.Clone(); _regRowHeader = regClone.Clone(); if (!matrix.HideColHeader) { _regRowHeader.Row += matrix.ColHeader.RowSpan; } if (!matrix.HideRowHeader) { _outPutPart = MtxOutPutPart.RowHeader; _regColHeader.Col += matrix.RowHeader.ColSpan; foreach (RptMtxHeaderInst inst in RowHeaderInsts) { _rowPart = inst; inst.Region = new RptRegion(_regRowHeader.Row, _regRowHeader.Col, inst.Item.RowSpan, inst.Item.ColSpan); inst.Output(); _regRowHeader.Row += 1; _rowIndex++; _region.RowSpan++; } } //数据 //还原行头、列头为开始状态(用于分页) _rowIndex = _colIndex = 0; _regColHeader = regClone.Clone(); _regRowHeader = regClone.Clone(); _regCells = regClone.Clone(); if (!matrix.HideRowHeader) { _regColHeader.Col += matrix.RowHeader.ColSpan; _regCells.Col += matrix.RowHeader.ColSpan; } if (!matrix.HideColHeader) { _regRowHeader.Row += matrix.ColHeader.RowSpan; _regCells.Row += matrix.ColHeader.RowSpan; } int colindex = 0; int col = _regCells.Col; _outPutPart = MtxOutPutPart.Cells; foreach (RptTextInst inst in _cellInsts) { _cellPart = inst; RptData.Current = GetCurrent(inst.Filter); //换行 if (colindex == ColHeaderInsts.Count) { _regCells.Row += 1; //当前行被占用,下移 while (_rowUsed.Contains(_regCells.Row)) { _regCells.Row++; } _regCells.Col = col; colindex = 0; } if (colindex != 0) { _regCells.Col++; //当前列被占用,下移 while (_colUsed.Contains(_regCells.Col)) { _regCells.Col++; } } inst.Region = new RptRegion(_regCells.Row, _regCells.Col, inst.Item.RowSpan, inst.Item.ColSpan); inst.Output(); colindex++; } root.HorPageBegin -= OnHorPageBegin; root.VerPageBegin -= OnVerPageBegin; }
/// <summary> /// 输出单列布局 /// </summary> void OutputList() { RptItemBase tempItem; RptRootInst root = Inst; List <RptRegion> regions = new List <RptRegion>(); RptRegion region = new RptRegion(_region.Row, _region.Col, 0, _item.ColSpan); regions.Add(region); if (_header != null) { _header.Output(); region.RowSpan += _header.Region.RowSpan; } RptTable tbl = _item as RptTable; int rowCount = tbl.RowBreakCount; int colCount = tbl.ColBreakCount; int rowNum = 0; foreach (RptTblPartInst tabInst in _rows) { RptItemBase item = tabInst.Item; tabInst.Region = new RptRegion( region.Row + region.RowSpan, region.Col, item.RowSpan, item.ColSpan); bool rowBreak = false; bool colBreak = false; if (rowCount == -1) { // 自动计算重复行数 if (root.TestPageBreak(tabInst)) { // 需要换页 if (colCount != 0 && (regions.Count % colCount) == 0) { rowBreak = true; colBreak = true; } else { rowBreak = false; colBreak = true; } } } else if (rowNum == rowCount) { // 应该换列 if (colCount != 0 && (regions.Count % colCount) == 0) { rowBreak = true; colBreak = true; } else { rowBreak = false; colBreak = true; } } if (colBreak) { // 换新列,重新累计行数 rowNum = 0; if (rowBreak) { // 列数达到后换行显示 RptRegion region2 = regions[regions.Count - colCount]; region = new RptRegion( region2.Row + region2.RowSpan, region2.Col, 0, region2.ColSpan); regions.Add(region); } else { RptRegion region3 = regions[regions.Count - 1]; region = new RptRegion( region3.Row, region3.Col + region3.ColSpan, 0, region3.ColSpan); regions.Add(region); } // 输出表头 if (_header != null) { RptTblHeaderInst header = _header.Clone() as RptTblHeaderInst; header.Region = region.Clone() as RptRegion; header.Region.RowSpan = header.Item.RowSpan; header.Output(); region.RowSpan = (header.Region.Row + header.Region.RowSpan) - region.Row; } tempItem = tabInst.Item; tabInst.Region = new RptRegion( region.Row + region.RowSpan, region.Col, tempItem.RowSpan, tempItem.ColSpan); tabInst.Output(); } else { tabInst.Output(); } region.RowSpan = (tabInst.Region.Row + tabInst.Region.RowSpan) - region.Row; if (((tabInst.Region.Row + tabInst.Region.RowSpan) - _region.Row) > _region.RowSpan) { _region.RowSpan = (tabInst.Region.Row + tabInst.Region.RowSpan) - _region.Row; } if (((tabInst.Region.Col + tabInst.Region.ColSpan) - _region.Col) > _region.ColSpan) { _region.ColSpan = (tabInst.Region.Col + tabInst.Region.ColSpan) - _region.Col; } rowNum++; } if (_footer != null) { region = _region; if (regions.Count > 0) { region = regions[regions.Count - 1]; } tempItem = _footer.Item; _footer.Region = new RptRegion( region.Row + region.RowSpan, region.Col, tempItem.RowSpan, tempItem.ColSpan); _footer.Output(); if (((_footer.Region.Row + _footer.Region.RowSpan) - _region.Row) > _region.RowSpan) { _region.RowSpan = (_footer.Region.Row + _footer.Region.RowSpan) - _region.Row; } if (((_footer.Region.Col + _footer.Region.ColSpan) - _region.Col) > _region.ColSpan) { _region.ColSpan = (_footer.Region.Col + _footer.Region.ColSpan) - _region.Col; } } }
/// <summary> /// 构造报表项实例 /// </summary> public override async Task Build() { RptRootInst inst = _part.Inst; string tblName = _data.Str("tbl"); if (string.IsNullOrEmpty(tblName)) { return; } // 使用时再加载数据 var rptData = await inst.Info.GetData(tblName); if (rptData == null) { return; } inst.CurrentParent = null; RptTableInst tbl = new RptTableInst(this); inst.Body.AddChild(tbl); inst.CurrentTable = tbl; tbl.Data = rptData; Table data = tbl.Data.Data; if (Header != null && Header.Rows.Count > 0) { await Header.Build(); } if (Body != null) { for (int num = 0; num < data.Count; num++) { RptTblGroup group; Row curRow = data[num]; Row preRow = null; Row nextRow = null; if (num > 0) { preRow = data[num - 1]; } if (num < data.Count - 1) { nextRow = data[num + 1]; } // 分组头 if (Groups != null) { for (int i = 0; i < Groups.Count; i++) { group = Groups[i]; string field = group.Field; if (!string.IsNullOrEmpty(field) && (preRow == null || curRow.Str(field) != preRow.Str(field))) { for (int j = i; j < Groups.Count; j++) { group = Groups[j]; if (group.Header != null && group.Header.Rows.Count > 0) { Dictionary <string, string> dict = GetFilters(j, curRow); await group.Header.Build(dict); } } break; } } } await Body.Build(); // 分组尾 if (Groups != null) { for (int i = 0; i < Groups.Count; i++) { group = Groups[i]; string field = group.Field; if (!string.IsNullOrEmpty(field) && (nextRow == null || curRow.Str(field) != nextRow.Str(field))) { for (int j = Groups.Count - 1; j >= i; j--) { group = Groups[j]; if (group.Footer != null && group.Footer.Rows.Count > 0) { Dictionary <string, string> dict = GetFilters(j, curRow); await group.Footer.Build(dict); } } break; } } } } // 未达到最少行数时增加空行 int minCount = MinRowCount; if (minCount > 0 && minCount > data.Count) { int tail = minCount - data.Count; for (int i = 0; i < tail; i++) { await Body.Build(); } } } if (Footer != null && Footer.Rows.Count > 0) { await Footer.Build(); } }