code: @Override
      public void updateModel(final FacesContext context) {
          final Iterator<Entry<SheetRowColIndex, Object>> entries = localValues.entrySet().iterator();
          // Keep track of the dirtied rows for ajax callbacks so we can send
          // updates on what was touched
          final HashSet<String> dirtyRows = new HashSet<>();
          while (entries.hasNext()) {
              final Entry<SheetRowColIndex, Object> entry = entries.next();
  
              final Object newValue = entry.getValue();
              final String rowKey = entry.getKey().getRowKey();
              final int col = entry.getKey().getColIndex();
              final SheetColumn column = getColumns().get(col);
              setRowVar(context, rowKey);
              final Object rowVal = rowMap.get(rowKey);
  
              final ValueExpression ve = column.getValueExpression(PropertyKeys.value.name());
              final ELContext elContext = context.getELContext();
              final Object oldValue = ve.getValue(elContext);
              ve.setValue(elContext, newValue);
              entries.remove();
              appendUpdateEvent(getRowKeyValue(context), col, rowVal, oldValue, newValue);
              dirtyRows.add(rowKey);
          }
          setLocalValueSet(false);
          setRowVar(context, null);
  
          if (context.getPartialViewContext().isPartialRequest()) {
              renderRowUpdateScript(context, dirtyRows);
          }
      }
docs: Override to update model with local values. Note that this is where things can be fragile in that we can successfully update some values and fail on
  others. There is no clean way to roll back the updates, but we also need to fail processing. Consider keeping old values as we update (need for event
  anyhow) and if there is a failure attempt to roll back by updating successful model updates with the old value. This may not all be necessary.