Object[] previousRow; RowMetaInterface outputMeta; public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException { // First, get a row from the default input hop Object[] r = getRow(); // If the row object is null, we are done processing. if (r == null) { setOutputDone(); return false; } if (outputMeta == null) { outputMeta = data.outputRowMeta.clone(); for(int i=0; i < outputMeta.size(); i++) { ValueMetaInterface meta = outputMeta.getValueMeta(i); if (meta.getType() == ValueMetaInterface.TYPE_NUMBER) { meta.setPrecision(4); meta.setConversionMask("#.####"); } } } // It is always safest to call createOutputRow() to ensure that your output row's Object[] is large // enough to handle any new fields you are creating in this step. Object[] outputRow = createOutputRow(r, data.outputRowMeta.size()); // copy all input fields to the output fields for (int i=0; i < getInputRowMeta().size(); i++) { if ((r[i] == null) && (previousRow != null)) { // if the current field is empty take it from the previous row outputRow[i] = previousRow[i]; } else { // otherwise use the current row outputRow[i] = r[i]; } } putRow(outputMeta, outputRow); // store the current row as future previous row previousRow = outputMeta.cloneRow(outputRow); return true; }