public void add(FormulaRecordAggregate agg) {
   if (_numberOfFormulas == 0) {
     if (_firstCell.getRow() != agg.getRow() || _firstCell.getCol() != agg.getColumn()) {
       throw new IllegalStateException(
           "shared formula coding error: "
               + _firstCell.getCol()
               + '/'
               + _firstCell.getRow()
               + " != "
               + agg.getColumn()
               + '/'
               + agg.getRow());
     }
   }
   if (_numberOfFormulas >= _frAggs.length) {
     throw new RuntimeException("Too many formula records for shared formula group");
   }
   _frAggs[_numberOfFormulas++] = agg;
 }
  /**
   * Gets the {@link SharedValueRecordBase} record if it should be encoded immediately after the
   * formula record contained in the specified {@link FormulaRecordAggregate} agg. Note - the shared
   * value record always appears after the first formula record in the group. For arrays and tables
   * the first formula is always the in the top left cell. However, since shared formula groups can
   * be sparse and/or overlap, the first formula may not actually be in the top left cell.
   *
   * @return the SHRFMLA, TABLE or ARRAY record for the formula cell, if it is the first cell of a
   *     table or array region. <code>null</code> if the formula cell is not shared/array/table, or
   *     if the specified formula is not the the first in the group.
   */
  public SharedValueRecordBase getRecordForFirstCell(FormulaRecordAggregate agg) {
    CellReference firstCell = agg.getFormulaRecord().getFormula().getExpReference();
    // perhaps this could be optimised by consulting the (somewhat unreliable) isShared flag
    // and/or distinguishing between tExp and tTbl.
    if (firstCell == null) {
      // not a shared/array/table formula
      return null;
    }

    int row = firstCell.getRow();
    int column = firstCell.getCol();
    if (agg.getRow() != row || agg.getColumn() != column) {
      // not the first formula cell in the group
      return null;
    }

    if (!_groupsBySharedFormulaRecord.isEmpty()) {
      SharedFormulaGroup sfg = findFormulaGroupForCell(firstCell);
      if (null != sfg) {
        return sfg.getSFR();
      }
    }

    // Since arrays and tables cannot be sparse (all cells in range participate)
    // The first cell will be the top left in the range.  So we can match the
    // ARRAY/TABLE record directly.

    for (TableRecord tr : _tableRecords) {
      if (tr.isFirstCell(row, column)) {
        return tr;
      }
    }
    for (ArrayRecord ar : _arrayRecords) {
      if (ar.isFirstCell(row, column)) {
        return ar;
      }
    }
    return null;
  }
 public void removeCell(CellValueRecordInterface cvRec) {
   if (cvRec instanceof FormulaRecordAggregate) {
     ((FormulaRecordAggregate) cvRec).notifyFormulaChanging();
   }
   _valuesAgg.removeCell(cvRec);
 }