带有rowspan的生成表导致额外的单元格

时间:2012-11-24 11:34:41

标签: c# jquery asp.net .net html

HTML

<table id="tableAppointment" bgcolor="#fcfcfc" border="1" cellspacing="1" width="100%">
 <thead>
  <tr>
   <td class="csstextheader" width="70px"></td>
   <td class="csstextheader" width="70px"><b>Time Slot&nbsp;</b></td>
   <td><b>Room 7</b></td>
   <td><b>Room 8</b></td>
   <td><b>Room 9</b></td>
   <td><b>Room 10</b></td>
  </tr>
 </thead>
 <tbody>
  <tr class="csstablelisttd">
   <td width="70px">08:00AM</td>
   <td>00</td>
   <td class="csstdred">John</td>
   <td>&nbsp;</td>
   <td>&nbsp;</td>
   <td>&nbsp;</td>
  </tr>
 </table> 

C#

private void GenerateTable() {
    for(int i = 0; i < tableAppointment.Rows.Count; i++) {
        foreach(DataRow dr in dataTableAcqModality.Rows) {
            cell = new HtmlTableCell() {
                InnerHtml = "&nbsp;"
            };
            cell.Style.Add("word-wrap", "break-word");
            cell.Attributes.Remove("class");
            cell.Attributes.Remove("rowspan");
            cell.Style.Remove("display");

            tableAppointment.Rows[i].Cells.Add(cell);
            tableAppointment.Style.Add("table-layout", "fixed");

            if(i == 0) {
                cell.Attributes.Add("ID", RoomID.ToString());
                cell.InnerHtml = String.Format(
                    "<span id='{0}'>{1}</span>",
                    RoomID, Roomname
                );
                tableAppointment.Rows[0].Attributes.Add("class", "csstextheader");
            }
        }
    }
}

protected void Page_Load(object sender, EventArgs e) {
    for(int i = 0; i < tableAppointment.Rows.Count; i++) {
        for(int j = 0; j < tableAppointment.Rows[i].Cells.Count; j++) {
            // This is where I need to remove the extra cells added 
            // after providing rowspan :(
        }
    }
}

this JSBin中,您可以看到由于rowspan被添加到上面行中的单元格而卡在我行的右侧的额外单元格。我正在试图找出如何删除这些。任何建议都表示赞赏!

5 个答案:

答案 0 :(得分:4)

即使我不知道你想要什么,或者知道为什么,I wrote some jQuery删除额外的列,因为这就是我们在StackOverflow上所做的。

我不保证此代码的效率或实际有用性。

$(document).ready(function() {
  $('table tr').each(function(i, v) {
    var cols = $(this).find('td');
    $(this).find('td[rowspan]').each(function() {
      var idx = $(this).index();
      console.log(idx);
      for(var j = 1; j < $(this).prop('rowspan'); j++) {
        $('table tr').eq(i+j).find('td').eq(idx).hide();
      }
    });
  });
});

编辑:显然你只需要给行设置一个高度,以避免折叠到彼此的行为中:

tr { height: 30px; }

编辑2:我确实更新了我的jQuery以隐藏具有rowspan的单元格正下方的单元格。您的示例中看起来似乎有冲突的约会。开玩笑说,你可能想要处理以确保没有调度冲突,而不是首先编写那些额外的单元格。

提前处理此问题的一般策略是将与表格大小相同的多维布尔数组(例如cellsUsed)初始化为false,然后在打印具有行数的单元格时,标记rowspan - 1个数组位置为true。然后,当编写一个对应于数组索引设置为true的单元格时,您只需输出任何内容。如果恰好在您标记为不输出的单元格中定义了实际约会,则您会遇到完全不同的问题,并且必须处理该问题。

编辑:这是一个演示,为什么你必须隐藏额外的单元格或两次删除它们以删除它们以避免错误:

这是一个示例表,其中'a'是具有rowspan&gt;的单元格。 1.'x'指定需要删除的额外单元格,' - '表示空白的空白。

这是表格中的起始数据:

a-a-
x-xa
xaxx
-x-x

如果您从左下角到右上角开始删除,会发生这种情况。在倒数第二行中删除连接到约会的额外单元格后,最后一行中只有三个单元格。因此,当您从下一个约会向下遍历以删除该行中的第四个单元格时,您会收到错误。

a-a-
x-xa
xaxx
--x!

如果您尝试从右上角到左下角删除,当您要删除第二个约会时,最终会错误地删除另一个约会(两个“a”相邻堆叠)。

a-a-
-xa
axx
-x-x

避免在生成表格后删除单元格的问题的唯一方法是标记要删除的所有单元格,然后从右到左删除每行中的单元格。

答案 1 :(得分:3)

为你简化..

如果您在单元格中使用[rowspan="2"] - &gt;那么你必须从下一行中删除一个单元格

示例:

<table id="Table1" >
    <tr>
        <td rowspan="2" style="border-style:solid"></td>
        <td style="border-style:solid"></td>
    </tr>
    <tr>
        <td style="border-style:solid"></td>          
    </tr>
</table>

如果在单元格中使用[rowspan =“3”] - &gt;然后你必须从下一个两个

中删除一个单元格

示例:

<table id="Table1" >
    <tr>
        <td rowspan="3" style="border-style:solid"></td>
        <td style="border-style:solid"></td>
    </tr>
    <tr>
        <td style="border-style:solid"></td>          
    </tr>
    <tr>
        <td style="border-style:solid"></td>          
    </tr>
</table>

答案 2 :(得分:2)

尝试这样的事情

protected void Page_Load(object sender, EventArgs e)
{
    for(int i = 0; i < tableAppointment.Rows.Count; i++)
    {
        for(int j = 0; j < tableAppointment.Rows[i].Cells.Count; j++)
        {
             // Assuming you have set the rowSpan by now.
             // TODO: Handle the possibility of missing rowspan attribute.
             int rowSpan = int.Parse(tableAppointment.Rows[i].Cells[j].Attributes["rowspan"]);
             if (rowSpan > 0) {
                // Now try to look ahead for rows and remove their j'th cell.
                for (int k = j+1; k < j + rowSpan; k++)
                {
                   tableAppointment.Rows[k].Cells.RemoveAt(j);
                   // TODO: Validate if k is not beyond available rows. It shoudn't be if rowspans are correct.
                }
             }
        }        //Here i have to remove those extra cell added after giving rowspan       
    }
}

注意:此代码尚未经过测试,甚至未经过编译。提供更多指导。

说完这个后,我相信你可以在生成表时更好地处理这个问题。如果我理解正确(可能是我没有)你有静态创建的表,然后你注入约会。 这就是你得到这种细胞外综合症的原因。如果动态生成整个表,则不应该发生这种情况。

答案 3 :(得分:1)

如果您的单元格为空,则可以隐藏css。等;

table{empty-cells:hide;}    

答案 4 :(得分:1)

由于缺少代码,我不得不做出假设:获取数据,数据是什么样的,如何将约会添加到表中。

我做了两件事来解决这个问题。 1 - 我切换了循环的顺序,而不是在每个房间循环一段时间,我在一个房间的所有时间跨度循环,然后移动到下一个房间。 2 - 由于更改#1,我能够将时间跨度计数器增加需要删除的单元格数量(不推荐)

Default.aspx.cs

public partial class _Default : Page
{
  //Used to store generated data.
  List<Room> Rooms = new List<Room>();

  protected void Page_Load(object sender, EventArgs e)
  {
    if (!IsPostBack)
    {
      //To simulate the datasource
      GenerateData();

      //Generate the output
      GenerateTable();
    }
  }

  private void GenerateData()
  {
    //Generate Rooms
    foreach (var roomNumber in Enumerable.Range(7, 4))
    {
      var newRoom = new Room();

      newRoom.RoomID = roomNumber;
      newRoom.Roomname = "Room " + roomNumber.ToString();
      //Generate 40 15-minute time slot appointments for each room
      for (var count = 0; count < 40; ++count)
      {
        var newAppointment = new Appointment();

        newAppointment.Id = (roomNumber * 40) + count;
        newAppointment.Name = " ";
        newAppointment.NumberOfTimeSlots = 1;

        newRoom.Appointments.Add(newAppointment);
      }

      Rooms.Add(newRoom);
    }

    Rooms[0].Appointments[0].Name = "John";
    Rooms[0].Appointments[0].NumberOfTimeSlots = 1;

    Rooms[0].Appointments[2].Name = "John";
    Rooms[0].Appointments[2].NumberOfTimeSlots = 3;

    Rooms[1].Appointments[14].Name = "calc";
    Rooms[1].Appointments[14].NumberOfTimeSlots = 3;

    //More can be added
  }

  private void GenerateTable()
  {
    //Moved outside of the loop since it is globally setting the table and does not need to run for each row.
    tableAppointment.Style.Add("table-layout", "fixed");

    /**********************************************************************************************
     * Major change 1:
     * I flipped the order of the loops, I changed it from row->column to column->row.
     * What this allows you to do is skip the step of adding additional rows for the current room
     * by increment the row counter (not a good practice, need to refactor code).
     **********************************************************************************************/

    //You had: foreach(DataRow dr in dataTableAcqModality.Rows) {
    //I am assuming that this is a list of rooms to display
    foreach (var dr in Rooms)      
    {

      for (int i = 0; i < tableAppointment.Rows.Count; ++i)
      {
        var cell = new HtmlTableCell();

        cell.Style.Add("word-wrap", "break-word");
        cell.Attributes.Remove("class");
        cell.Attributes.Remove("rowspan");
        cell.Style.Remove("display");

        tableAppointment.Rows[i].Cells.Add(cell);

        if (i == 0) //Indicating the header row
        {
          cell.Attributes.Add("ID", dr.RoomID.ToString());
          cell.InnerHtml = String.Format(
              "<span id='{0}'>{1}</span>",
              dr.RoomID, dr.Roomname
          );
          tableAppointment.Rows[0].Attributes.Add("class", "csstextheader");
        }
        else
        {

          /***********************************************************************
           * Assumption that this is how you are adding the appointments to the 
           * table, did not see it in your quesiton
           ***********************************************************************/ 
          //i-1 to offset the header row
          cell.InnerHtml = dr.Appointments[i-1].Name;

          //NumberOfTimeSlots does not have to be part of the object, you are already doing it one way (not shown)
          cell.RowSpan = dr.Appointments[i - 1].NumberOfTimeSlots;

          //This is the inportant part, incrementing the row counter for this table by the number of cells you need to be removed becasue of the rowspan.
          //NOTE: I do not like the idea of messing with a loop counter, I would try to refactor your code, but since it was not provided this is a temporary fix.
          i += dr.Appointments[i - 1].NumberOfTimeSlots - 1;
        }
      }
    }
  }
}

public class Room
{
  public int RoomID { get; set; }
  public string Roomname { get; set; }
  public List<Appointment> Appointments { get; set; }

  public Room()
  {
    Appointments = new List<Appointment>();
  }
}

public class Appointment
{
  public int Id { get; set; }
  public string Name { get; set; }
  public int NumberOfTimeSlots { get; set; }
}

Default.aspx的:

                                     时隙                                08:00 AM00         15         三十         40

    <tr><td>09:00AM</td><td>00</td></tr>
    <tr><td>&nbsp;</td><td>15</td></tr>
    <tr><td>&nbsp;</td><td>30</td></tr>
    <tr><td>&nbsp;</td><td>40</td></tr>

    <tr><td>10:00AM</td><td>00</td></tr>
    <tr><td>&nbsp;</td><td>15</td></tr>
    <tr><td>&nbsp;</td><td>30</td></tr>
    <tr><td>&nbsp;</td><td>40</td></tr>

    <tr><td>11:00AM</td><td>00</td></tr>
    <tr><td>&nbsp;</td><td>15</td></tr>
    <tr><td>&nbsp;</td><td>30</td></tr>
    <tr><td>&nbsp;</td><td>40</td></tr>

    <tr><td>12:00PM</td><td>00</td></tr>
    <tr><td>&nbsp;</td><td>15</td></tr>
    <tr><td>&nbsp;</td><td>30</td></tr>
    <tr><td>&nbsp;</td><td>40</td></tr>

    <tr><td>01:00PM</td><td>00</td></tr>
    <tr><td>&nbsp;</td><td>15</td></tr>
    <tr><td>&nbsp;</td><td>30</td></tr>
    <tr><td>&nbsp;</td><td>40</td></tr>

    <tr><td>02:00PM</td><td>00</td></tr>
    <tr><td>&nbsp;</td><td>15</td></tr>
    <tr><td>&nbsp;</td><td>30</td></tr>
    <tr><td>&nbsp;</td><td>40</td></tr>

    <tr><td>03:00PM</td><td>00</td></tr>
    <tr><td>&nbsp;</td><td>15</td></tr>
    <tr><td>&nbsp;</td><td>30</td></tr>
    <tr><td>&nbsp;</td><td>40</td></tr>

    <tr><td>04:00PM</td><td>00</td></tr>
    <tr><td>&nbsp;</td><td>15</td></tr>
    <tr><td>&nbsp;</td><td>30</td></tr>
    <tr><td>&nbsp;</td><td>40</td></tr>

    <tr><td>05:00PM</td><td>00</td></tr>
    <tr><td>&nbsp;</td><td>15</td></tr>
    <tr><td>&nbsp;</td><td>30</td></tr>
    <tr><td>&nbsp;</td><td>40</td></tr>
  </tbody>
</table>