2012年10月10日星期三

GridView多行多列合并单元格(完整代码和例子)

GridView多行多列合并单元格(完整代码和例子)

使用GridView展示数据,经常会遇到合并单元格的情况。首先说明一下项目中合并单元格的要求,如下图所示,左边是合并之前的GridView,右边是合并之后的GridView。从图中可以看到GridView一共有“等级”、“颜色”,“箱子”,“净重”,“规格”,“汇总”6列,首先要要合并等级,如右图中合并后的“一级”,然后再合并每个等级下面的颜色,如右图中合并后的“一级”下面的“片红”和“条红”,依次类推。

1

从网上搜索了一下“GridView合并单元格”,大多是合并单列,诸如此类。搜索未果,只能自己动手写一个了。参考现有的合并单列的代码,我完成了满足上面合并要求的代码,自我感觉算法很烂,写这篇文章也是希望有经验的园友提供更好的解决方法。

首先,完成合并单列的行,代码如下:

   1:  /// <summary>
   2:  /// 合并单列的行
   3:  /// </summary>
   4:  /// <param name="gv">GridView</param>
   5:  /// <param name="currentCol">当前列</param>
   6:  /// <param name="startRow">开始合并的行索引</param>
   7:  /// <param name="endRow">结束合并的行索引</param>
   8:  private static void MergeRow(GridView gv, int currentCol, int startRow, int endRow)
   9:  {
  10:      for (int rowIndex = endRow; rowIndex >= startRow; rowIndex--)
  11:      {
  12:          GridViewRow currentRow = gv.Rows[rowIndex];
  13:          GridViewRow prevRow = gv.Rows[rowIndex + 1];
  14:          if (currentRow.Cells[currentCol].Text != "" && currentRow.Cells[currentCol].Text != " ")
  15:          {
  16:              if (currentRow.Cells[currentCol].Text == prevRow.Cells[currentCol].Text)
  17:              {
  18:                  currentRow.Cells[currentCol].RowSpan = prevRow.Cells[currentCol].RowSpan < 1 ? 2 : prevRow.Cells[currentCol].RowSpan + 1;
  19:                  prevRow.Cells[currentCol].Visible = false;
  20:              }
  21:          }
  22:      }
  23:  }

在合并后面的列之前,首先要遍历前一列。上面的例子中,合并第二列,首先要遍历第一列,以便得到一级是从第几行到第几行。开始写遍历前一列的代码之前,首先定义一个类,如下所示:

   1:          class RowArg
   2:          {
   3:              public int StartRowIndex { get; set; }
   4:              public int EndRowIndex { get; set; }
   5:          }

该类有两个属性,分别表示要合并的开始行的索引和结束行的索引。下面是遍历前一列的代码:

   1:  /// <summary>
   2:  /// 遍历前一列
   3:  /// </summary>
   4:  /// <param name="gv">GridView</param>
   5:  /// <param name="prevCol">当前列的前一列</param>
   6:  /// <param name="list"></param>
   7:  private static void TraversesPrevCol(GridView gv, int prevCol, List<RowArg> list)
   8:  {
   9:      if (list == null)
  10:      {
  11:          list = new List<RowArg>();
  12:      }
  13:      RowArg ra = null;
  14:      for (int i = 0; i < gv.Rows.Count; i++)
  15:      {
  16:          if (!gv.Rows[i].Cells[prevCol].Visible)
  17:          {
  18:              continue;
  19:          }
  20:          ra = new RowArg();
  21:          ra.StartRowIndex = gv.Rows[i].RowIndex;
  22:          ra.EndRowIndex = ra.StartRowIndex + gv.Rows[i].Cells[prevCol].RowSpan - 2;
  23:          list.Add(ra);
  24:      }
  25:  }

下面完成最后一个方法,代码如下:

   1:  /// <summary>
   2:  /// GridView合并行,
   3:  /// </summary>
   4:  /// <param name="gv">GridView</param>
   5:  /// <param name="startCol">开始列</param>
   6:  /// <param name="endCol">结束列</param>
   7:  public static void MergeRow(GridView gv, int startCol, int endCol)
   8:  {
   9:      RowArg init = new RowArg()
  10:      {
  11:          StartRowIndex = 0,
  12:          EndRowIndex = gv.Rows.Count - 2
  13:      };
  14:      for (int i = startCol; i < endCol + 1; i++)
  15:      {
  16:          if (i > 0)
  17:          {
  18:              List<RowArg> list = new List<RowArg>();
  19:              //从第二列开始就要遍历前一列
  20:              TraversesPrevCol(gv, i - 1, list);
  21:              foreach (var item in list)
  22:              {
  23:                  MergeRow(gv, i, item.StartRowIndex, item.EndRowIndex);
  24:              }
  25:          }
  26:          //合并开始列的行
  27:          else
  28:          {
  29:              MergeRow(gv, i, init.StartRowIndex, init.EndRowIndex);
  30:          }
  31:      }
  32:  }

这个方法是最后在程序中调用的方法。

最后写个简单的例子:

页面代码:

   1:  <asp:GridView ID="Gridview1" runat="server" AutoGenerateColumns="false" 
   2:      onrowdatabound="Gridview1_RowDataBound">
   3:      <Columns>
   4:          <asp:BoundField DataField="Name" HeaderText="姓名" />
   5:          <asp:BoundField DataField="Item" HeaderText="工资项" />
   6:          <asp:BoundField DataField="SubItem" HeaderText="工资子项" />
   7:          <asp:BoundField DataField="Month" HeaderText="月份" />
   8:          <asp:BoundField DataField="Money" HeaderText="钱数" />
   9:      </Columns>
  10:  </asp:GridView>

后台代码:

   1: public partial class WebForm1 : System.Web.UI.Page
   2: {
   3:     protected void Page_Load(object sender, EventArgs e)
   4:     {
   5:         if (!Page.IsPostBack)
   6:         {
   7:             #region 模拟数据
   8:             List<Salary> salaryList = new List<Salary>();
   9:             salaryList.Add(new Salary()
  10:             {
  11:                 Name = "张三",
  12:                 Item = "应发工资",
  13:                 SubItem = "基本工资",
  14:                 Month = "1月",
  15:                 Money = "3000"
  16:             });
  17:             salaryList.Add(new Salary()
  18:             {
  19:                 Name = "张三",
  20:                 Item = "应发工资",
  21:                 SubItem = "奖金",
  22:                 Month = "1月",
  23:                 Money = "500"
  24:             });
  25:             salaryList.Add(new Salary()
  26:             {
  27:                 Name = "张三",
  28:                 Item = "应发工资",
  29:                 SubItem = "奖金",
  30:                 Month = "1月",
  31:                 Money = "130"
  32:             });
  33:             salaryList.Add(new Salary()
  34:             {
  35:                 Name = "张三",
  36:                 Item = "应发工资",
  37:                 SubItem = "奖金",
  38:                 Month = "1月",
  39:                 Money = "150"
  40:             });
  41:             salaryList.Add(new Salary()
  42:             {
  43:                 Name = "张三",
  44:                 Item = "应发工资",
  45:                 SubItem = "加班",
  46:                 Month = "1月",
  47:                 Money = "100"
  48:             });
  49:             salaryList.Add(new Salary()
  50:             {
  51:                 Name = "张三",
  52:                 Item = "应发工资",
  53:                 SubItem = "加班",
  54:                 Month = "1月",
  55:                 Money = "100"
  56:             });
  57:             salaryList.Add(new Salary()
  58:             {
  59:                 Name = "张三",
  60:                 Item = "五险一金",
  61:                 SubItem = "医疗保险",
  62:                 Month = "1月",
  63:                 Money = "500"
  64:             });
  65:             salaryList.Add(new Salary()
  66:             {
  67:                 Name = "张三",
  68:                 Item = "五险一金",
  69:                 SubItem = "住房公积金",
  70:                 Month = "1月",
  71:                 Money = "370"
  72:             });
  73:             salaryList.Add(new Salary()
  74:             {
  75:                 Name = "",
  76:                 Item = "",
  77:                 SubItem = "",
  78:                 Month = "合计",
  79:                 Money = "3500"
  80:             });
  81:             salaryList.Add(new Salary()
  82:             {
  83:                 Name = "张三",
  84:                 Item = "应发工资",
  85:                 SubItem = "基本工资",
  86:                 Month = "2月",
  87:                 Money = "3000"
  88:             });
  89:             salaryList.Add(new Salary()
  90:             {
  91:                 Name = "张三",
  92:                 Item = "应发工资",
  93:                 SubItem = "奖金",
  94:                 Month = "2月",
  95:                 Money = "400"
  96:             });
  97:             salaryList.Add(new Salary()
  98:             {
  99:                 Name = "张三",
 100:                 Item = "应发工资",
 101:                 SubItem = "奖金",
 102:                 Month = "2月",
 103:                 Money = "100"
 104:             });
 105:             salaryList.Add(new Salary()
 106:             {
 107:                 Name = "张三",
 108:                 Item = "应发工资",
 109:                 SubItem = "加班",
 110:                 Month = "2月",
 111:                 Money = "100"
 112:             });
 113:             salaryList.Add(new Salary()
 114:             {
 115:                 Name = "张三",
 116:                 Item = "应发工资",
 117:                 SubItem = "加班",
 118:                 Month = "2月",
 119:                 Money = "100"
 120:             });
 121:             salaryList.Add(new Salary()
 122:             {
 123:                 Name = "张三",
 124:                 Item = "应发工资",
 125:                 SubItem = "加班",
 126:                 Month = "2月",
 127:                 Money = "100"
 128:             });
 129:             salaryList.Add(new Salary()
 130:             {
 131:                 Name = "张三",
 132:                 Item = "五险一金",
 133:                 SubItem = "医疗保险",
 134:                 Month = "2月",
 135:                 Money = "500"
 136:             });
 137:             salaryList.Add(new Salary()
 138:             {
 139:                 Name = "张三",
 140:                 Item = "五险一金",
 141:                 SubItem = "住房公积金",
 142:                 Month = "2月",
 143:                 Money = "370"
 144:             });
 145:             salaryList.Add(new Salary()
 146:             {
 147:                 Name = "",
 148:                 Item = "",
 149:                 SubItem = "",
 150:                 Month = "合计",
 151:                 Money = "3900"
 152:             });
 153:             //----------------------------------------
 154:             salaryList.Add(new Salary()
 155:             {
 156:                 Name = "李四",
 157:                 Item = "应发工资",
 158:                 SubItem = "基本工资",
 159:                 Month = "1月",
 160:                 Money = "3000"
 161:             });
 162:             salaryList.Add(new Salary()
 163:             {
 164:                 Name = "李四",
 165:                 Item = "应发工资",
 166:                 SubItem = "奖金",
 167:                 Month = "1月",
 168:                 Money = "500"
 169:             });
 170:             salaryList.Add(new Salary()
 171:             {
 172:                 Name = "李四",
 173:                 Item = "应发工资",
 174:                 SubItem = "奖金",
 175:                 Month = "1月",
 176:                 Money = "130"
 177:             });
 178:             salaryList.Add(new Salary()
 179:             {
 180:                 Name = "李四",
 181:                 Item = "应发工资",
 182:                 SubItem = "奖金",
 183:                 Month = "1月",
 184:                 Money = "150"
 185:             });
 186:             salaryList.Add(new Salary()
 187:             {
 188:                 Name = "李四",
 189:                 Item = "应发工资",
 190:                 SubItem = "加班",
 191:                 Month = "1月",
 192:                 Money = "100"
 193:             });
 194:             salaryList.Add(new Salary()
 195:             {
 196:                 Name = "李四",
 197:                 Item = "应发工资",
 198:                 SubItem = "加班",
 199:                 Month = "1月",
 200:                 Money = "100"
 201:             });
 202:             salaryList.Add(new Salary()
 203:             {
 204:                 Name = "李四",
 205:                 Item = "五险一金",
 206:                 SubItem = "医疗保险",
 207:                 Month = "1月",
 208:                 Money = "500"
 209:             });
 210:             salaryList.Add(new Salary()
 211:             {
 212:                 Name = "李四",
 213:                 Item = "五险一金",
 214:                 SubItem = "住房公积金",
 215:                 Month = "1月",
 216:                 Money = "370"
 217:             });
 218:             salaryList.Add(new Salary()
 219:             {
 220:                 Name = "",
 221:                 Item = "",
 222:                 SubItem = "",
 223:                 Month = "合计",
 224:                 Money = "3500"
 225:             });
 226:             salaryList.Add(new Salary()
 227:             {
 228:                 Name = "李四",
 229:                 Item = "应发工资",
 230:                 SubItem = "基本工资",
 231:                 Month = "2月",
 232:                 Money = "3000"
 233:             });
 234:             salaryList.Add(new Salary()
 235:             {
 236:                 Name = "李四",
 237:                 Item = "应发工资",
 238:                 SubItem = "奖金",
 239:                 Month = "2月",
 240:                 Money = "400"
 241:             });
 242:             salaryList.Add(new Salary()
 243:             {
 244:                 Name = "李四",
 245:                 Item = "应发工资",
 246:                 SubItem = "奖金",
 247:                 Month = "2月",
 248:                 Money = "100"
 249:             });
 250:             salaryList.Add(new Salary()
 251:             {
 252:                 Name = "李四",
 253:                 Item = "应发工资",
 254:                 SubItem = "加班",
 255:                 Month = "2月",
 256:                 Money = "100"
 257:             });
 258:             salaryList.Add(new Salary()
 259:             {
 260:                 Name = "李四",
 261:                 Item = "应发工资",
 262:                 SubItem = "加班",
 263:                 Month = "2月",
 264:                 Money = "100"
 265:             });
 266:             salaryList.Add(new Salary()
 267:             {
 268:                 Name = "李四",
 269:                 Item = "应发工资",
 270:                 SubItem = "加班",
 271:                 Month = "2月",
 272:                 Money = "100"
 273:             });
 274:             salaryList.Add(new Salary()
 275:             {
 276:                 Name = "李四",
 277:                 Item = "五险一金",
 278:                 SubItem = "医疗保险",
 279:                 Month = "2月",
 280:                 Money = "500"
 281:             });
 282:             salaryList.Add(new Salary()
 283:             {
 284:                 Name = "李四",
 285:                 Item = "五险一金",
 286:                 SubItem = "住房公积金",
 287:                 Month = "2月",
 288:                 Money = "370"
 289:             });
 290:             salaryList.Add(new Salary()
 291:             {
 292:                 Name = "",
 293:                 Item = "",
 294:                 SubItem = "",
 295:                 Month = "合计",
 296:                 Money = "3900"
 297:             });
 298:             //-------------------------------------------
 299:             #endregion
 300:             Gridview1.DataSource = salaryList;
 301:             Gridview1.DataBind();
 302:             MergeGridViewCell.MergeRow(Gridview1, 0, 3);
 303:         }
 304:     }
 305:  
 306:     protected void Gridview1_RowDataBound(object sender, GridViewRowEventArgs e)
 307:     {
 308:         if (e.Row.RowType == DataControlRowType.Header)
 309:         {
 310:             e.Row.BackColor = Color.FromArgb(135, 206, 250);
 311:         }
 312:         if (e.Row.RowType == DataControlRowType.DataRow)
 313:         {
 314:             if (e.Row.Cells[3].Text == "合计")
 315:             {
 316:                 e.Row.BackColor = Color.FromArgb(176, 226, 255);
 317:                 e.Row.Cells[0].ColumnSpan = 4;
 318:                 e.Row.Cells[0].Text = "合计";
 319:                 e.Row.Cells[1].Visible = e.Row.Cells[2].Visible = e.Row.Cells[3].Visible = false;
 320:             }
 321:         }
 322:     }
 323: }
 324:  
 325: public class Salary
 326: {
 327:     /// <summary>
 328:     /// 姓名
 329:     /// </summary>
 330:     public string Name { get; set; }
 331:     /// <summary>
 332:     /// 工资项
 333:     /// </summary>
 334:     public string Item { get; set; }
 335:     /// <summary>
 336:     /// 工资子项
 337:     /// </summary>
 338:     public string SubItem { get; set; }
 339:     /// <summary>
 340:     /// 月份
 341:     /// </summary>
 342:     public string Month { get; set; }
 343:     /// <summary>
 344:     /// 钱数
 345:     /// </summary>
 346:     public string Money { get; set; }
 347: }

GridView运行前后比较:

2

源码下载地址:http://pan.baidu.com/share/link?shareid=80747&uk=2466437167


TAG: