public void expandRow(int rowNumber) {
    int idx = rowNumber;
    if (idx == -1) return;

    // If it is already expanded do nothing.
    if (!isRowGroupCollapsed(idx)) {
      return;
    }

    // Find the start of the group.
    int startIdx = findStartOfRowOutlineGroup(idx);
    RowRecord row = getRow(startIdx);

    // Find the end of the group.
    int endIdx = findEndOfRowOutlineGroup(idx);

    // expand:
    // collapsed bit must be unset
    // hidden bit gets unset _if_ surrounding groups are expanded you can determine
    //   this by looking at the hidden bit of the enclosing group.  You will have
    //   to look at the start and the end of the current group to determine which
    //   is the enclosing group
    // hidden bit only is altered for this outline level.  ie.  don't un-collapse contained groups
    if (!isRowGroupHiddenByParent(idx)) {
      for (int i = startIdx; i <= endIdx; i++) {
        RowRecord otherRow = getRow(i);
        if (row.getOutlineLevel() == otherRow.getOutlineLevel() || !isRowGroupCollapsed(i)) {
          otherRow.setZeroHeight(false);
        }
      }
    }

    // Write collapse field
    getRow(endIdx + 1).setColapsed(false);
  }
  public int findStartOfRowOutlineGroup(int row) {
    // Find the start of the group.
    RowRecord rowRecord = this.getRow(row);
    int level = rowRecord.getOutlineLevel();
    int currentRow = row;
    while (this.getRow(currentRow) != null) {
      rowRecord = this.getRow(currentRow);
      if (rowRecord.getOutlineLevel() < level) {
        return currentRow + 1;
      }
      currentRow--;
    }

    return currentRow + 1;
  }
 /**
  * Hide all rows at or below the current outline level
  *
  * @return index of the <em>next<em> row after the last row that gets hidden
  */
 private int writeHidden(RowRecord pRowRecord, int row) {
   int rowIx = row;
   RowRecord rowRecord = pRowRecord;
   int level = rowRecord.getOutlineLevel();
   while (rowRecord != null && getRow(rowIx).getOutlineLevel() >= level) {
     rowRecord.setZeroHeight(true);
     rowIx++;
     rowRecord = getRow(rowIx);
   }
   return rowIx;
 }