C# 从TXT读数据 用Dictionary按年、月维度填充DataGridView的实现求助
核心实现方案
你考虑的Dictionary<int, Dictionary<int, int>>结构完全适配动态年份的需求,Dictionary本身就是动态键值存储结构,不需要提前枚举所有可能的年份,运行时读到哪年的记录就自动新增对应条目,根本不会因为年份不确定卡壳。
逻辑拆解
- 替换单层汇总字典为嵌套结构
外层Dictionary的键存储动态出现的年份,值为内层Dictionary;内层Dictionary的键存储1-12月的月份值,值为对应年月下num1的累计汇总值。 - 逐行处理记录时按年-月双层累加
每读到一条Record对象,同时取出对应日期的年份和月份,按两层键的层级判断是否存在对应条目,不存在则初始化,存在则累加num1值,逻辑和你之前实现的单月汇总完全一致,只是多了一层按年份的拆分。 - 按固定列结构填充DataGridView
dgv的列结构是固定的(第一列Y,后接12个月份列),行是动态的:遍历所有收集到的年份,按升序排序后逐行添加,每个月份列如果没有对应汇总值就填充0,避免出现空单元格。
修正后的可运行代码
替换原有逻辑即可,顺带修正原代码里未定义变量m的问题,去掉了容易出边界bug的字符串拼接拆分逻辑:
private void Form_Load(object sender, EventArgs e) { // 嵌套字典:外层key=年份,内层key=月份,value=对应num1汇总值 Dictionary<int, Dictionary<int, int>> dataByYearMonth = new Dictionary<int, Dictionary<int, int>>(); Record b; try { if (File.Exists("data.txt")) { using (StreamReader sr = new StreamReader("data.txt")) { while (!sr.EndOfStream) { b = new Record(sr.ReadLine()); int year = b.date1.Year; int month = b.date1.Month; // 第一层:判断是否存在当前年份的条目 if (!dataByYearMonth.ContainsKey(year)) { // 新年份直接初始化内层空字典 dataByYearMonth[year] = new Dictionary<int, int>(); } // 拿到当前年份对应的月份字典 var monthDict = dataByYearMonth[year]; // 第二层:判断是否存在当前月份的条目,逻辑和原有单月汇总完全一致 if (!monthDict.ContainsKey(month)) { monthDict[month] = b.num1; } else { monthDict[month] += b.num1; } } } // 清空dgv原有行,避免重复加载 dgv.Rows.Clear(); // 对收集到的年份按升序排序,避免Dictionary随机存储顺序导致行序混乱 var sortedYears = dataByYearMonth.Keys.OrderBy(y => y).ToList(); foreach (int year in sortedYears) { // 构建13个元素的行数组,匹配dgv的1列年份+12列月份结构 var rowValues = new object[13]; rowValues[0] = year; // 按固定顺序填充1-12月的汇总值,无数据则填0 for (int m = 1; m <= 12; m++) { rowValues[m] = dataByYearMonth[year].TryGetValue(m, out int val) ? val : 0; } dgv.Rows.Add(rowValues); } } } catch (Exception ex) { MessageBox.Show($"数据加载失败:{ex.Message}"); } }
开发注意点
- 不需要提前给每个年份预生成12个月份的条目,在填充行时通过
TryGetValue判断是否有对应月份数据即可,无数据自动填0,能减少不必要的内存占用。 - 填充行前一定要对年份键做排序,否则Dictionary的键存储顺序是哈希随机的,会导致dgv里的年份行顺序混乱,不符合常规阅读习惯。
- 原代码里拼接字符串拆分数组的方法容易出现边界问题(比如末尾多拼接的下划线会拆分出空字符串、字典遍历顺序和12个月的列顺序不匹配),直接按1-12月的固定顺序取值填充,能保证列和值严格对应。
- 如果后续需要扩展其他字段的汇总,只需要在内层结构里新增对应键值即可,不需要改动外层的动态年份逻辑。
内容的提问来源于stack exchange,提问作者Alan Romagnoli
相关产品推荐
相关产品推荐

