起因是我在使用FastReport.Net工具的时候,搜不到对于我的问题的具体解决办法,所以开始写csdn来记录自己当前遇到的问题。
有关FastReport.Net的问题欢迎一起讨论。
目标:这是一个考勤报表,展示每个员工当前年月的出勤状态、天数。
要求:1.第一行展示第二行日期对应的星期几
2、根据月份动态展示列。
下面这张图是我已经画好的整个图
接下来就只需要在脚本即code里面写完整的代码。
//这个方法可以在右边属性栏找到闪电图标,会有这个事件ManualBuild,双击进去//Table2就是你给这个Table控件命的名称privatevoidTable2_ManualBuild(objectsender,EventArgse){TableObjecttable=senderasTableObject;if(table==null)return;// 1. 获取主表数据源(用于判断年月)DataSourceBasemainSource=Report.GetDataSource("V_HR_SimpleTimeSheetInfoList");// 2.获取子表数据源填充数据行DataSourceBaserowData=Report.GetDataSource("V_HR_SimpleTimeSheet");if(mainSource==null)return;// 移动到第一行获取年月(假设主表只有一条记录或取第一条)mainSource.First();intyear=Convert.ToInt32(mainSource["TSYear"]);intmonth=Convert.ToInt32(mainSource["TSMonth"]);// 2. 计算该月最大天数intmaxDays=DateTime.DaysInMonth(year,month);// 3. 定义日期列的起始索引// 假设:第2~31列对应 Day1~Day31// 请根据你的实际设计器列顺序修改这个 startColIndexintstartColIndex=2;//这个是因为我第一行需要填充的星期的开始名称为Cell169intstartWeekCellIndex=169;// 4. 循环处理 1 到 31 号for(inti=1;i<=31;i++){// 计算当前列对应的 Cell 变量名索引// 偏移量是 i-1,因为数组/索引是从 0 开始的intcurrentWeekIndex=startWeekCellIndex+(i-1);// 尝试通过反射或 FindObject 获取单元格对象// 注意:这里使用 FindObject 是最稳妥的,因为它能处理动态生成的名称stringweekCellName="Cell"+currentWeekIndex.ToString();BaseweekCell=Report.FindObject(weekCellName)asBase;// 如果找到了单元格对象if(weekCell!=null){if(i<=maxDays){// --- 情况 A: 该日期存在 (例如 6月1日 - 6月30日) ---// 1. 构造日期对象DateTimecurrentDay=newDateTime(year,month,i);// 2. 填充内容// 设置星期 (例如 "Mon", "Tue"),这里因为我要显示英文,如果不显示可以删除System.Globalization.CultureInfo.InvariantCulture((TextObject)weekCell).Text=currentDay.ToString("ddd",System.Globalization.CultureInfo.InvariantCulture);}else{((TextObject)weekCell).Text="";}}}// 5. 循环隐藏多余列// 表格通常预置了31列数据列,我们从 maxDays+1 开始隐藏for(inti=maxDays+1;i<=31;i++){// 计算当前要隐藏的列索引intcolIndex=startColIndex+(i-1);// 安全检查:防止索引越界if(colIndex<table.Columns.Count){// 核心操作:直接隐藏列// 只要 Visible = false,FastReport 就不会渲染这一列,也不会报错table.Columns[colIndex].Visible=false;}}//6. 分表头,数据行打印表格// init the data sourcerowData.Init();// print the first table row - it is a headerTable2.PrintRow(0);// each PrintRow call must be followed by either PrintColumn or PrintColumns call// to print cells on the rowTable2.PrintColumns();// print the first table row - it is a headerTable2.PrintRow(1);// each PrintRow call must be followed by either PrintColumn or PrintColumns call// to print cells on the rowTable2.PrintColumns();// now enumerate the data source and print the table bodywhile(rowData.HasMoreRows){// print the table bodyTable2.PrintRow(2);Table2.PrintColumns();// go next data source rowrowData.Next();}}最终效果