@Override
  public void visitContainedRecords(RecordVisitor rv) {

    PositionTrackingVisitor stv = new PositionTrackingVisitor(rv, 0);
    // DBCells are serialized before row records.
    final int blockCount = getRowBlockCount();
    for (int blockIndex = 0; blockIndex < blockCount; blockIndex++) {
      // Serialize a block of rows.
      // Hold onto the position of the first row in the block
      int pos = 0;
      // Hold onto the size of this block that was serialized
      final int rowBlockSize = visitRowRecordsForBlock(blockIndex, rv);
      pos += rowBlockSize;
      // Serialize a block of cells for those rows
      final int startRowNumber = getStartRowNumberForBlock(blockIndex);
      final int endRowNumber = getEndRowNumberForBlock(blockIndex);
      DBCellRecord.Builder dbcrBuilder = new DBCellRecord.Builder();
      // Note: Cell references start from the second row...
      int cellRefOffset = (rowBlockSize - RowRecord.ENCODED_SIZE);
      for (int row = startRowNumber; row <= endRowNumber; row++) {
        if (_valuesAgg.rowHasCells(row)) {
          stv.setPosition(0);
          _valuesAgg.visitCellsForRow(row, stv);
          int rowCellSize = stv.getPosition();
          pos += rowCellSize;
          // Add the offset to the first cell for the row into the
          // DBCellRecord.
          dbcrBuilder.addCellOffset(cellRefOffset);
          cellRefOffset = rowCellSize;
        }
      }
      // Calculate Offset from the start of a DBCellRecord to the first Row
      rv.visitRecord(dbcrBuilder.build(pos));
    }
    for (int i = 0; i < _unknownRecords.size(); i++) {
      // Potentially breaking the file here since we don't know exactly where to write these records
      rv.visitRecord(_unknownRecords.get(i));
    }
  }
 public void visitContainedRecords(RecordVisitor rv) {
   int nItems = records.size();
   if (nItems < 1) {
     return;
   }
   ColumnInfoRecord cirPrev = null;
   for (int i = 0; i < nItems; i++) {
     ColumnInfoRecord cir = records.get(i);
     rv.visitRecord(cir);
     if (cirPrev != null && CIRComparator.compareColInfos(cirPrev, cir) > 0) {
       // Excel probably wouldn't mind, but there is much logic in this class
       // that assumes the column info records are kept in order
       throw new RuntimeException("Column info records are out of order");
     }
     cirPrev = cir;
   }
 }
  private int visitRowRecordsForBlock(int blockIndex, RecordVisitor rv) {
    final int startIndex = blockIndex * DBCellRecord.BLOCK_SIZE;
    final int endIndex = startIndex + DBCellRecord.BLOCK_SIZE;

    Iterator<RowRecord> rowIterator = _rowRecords.values().iterator();

    // Given that we basically iterate through the rows in order,
    // For a performance improvement, it would be better to return an instance of
    // an iterator and use that instance throughout, rather than recreating one and
    // having to move it to the right position.
    int i = 0;
    for (; i < startIndex; i++) rowIterator.next();
    int result = 0;
    while (rowIterator.hasNext() && (i++ < endIndex)) {
      Record rec = rowIterator.next();
      result += rec.getRecordSize();
      rv.visitRecord(rec);
    }
    return result;
  }