Perhaps the approach below works, but for this it is necessary to have the list sorted by " CdOE " (as it looks like in your example), since indexes with the same code will always be one after the other.
$lista = $class->Lista($empresa, $fatura);
// executa enquanto a lista tiver valor
while (!empty($lista)) {
// pega o valor atual do ponteiro
$dados = current($lista);
// remove este valor da lista
unset($lista[key($lista)]);
$CdFatura = $dados->getFatura();
$NrNFSe = $dados->getNrNFSe();
$CdOE = $dados->getCdOe();
$NrNotaFiscal = $dados->getNrNotafiscal();
// pega o atual index da lista (o anterior já foi removido)
$nextDados = current($lista);
// executa este laço enquanto o próximo código existir e
// for igual ao código atual
while ($nextDados && $nextDados->getCdOe() == $CdOE) {
$NrNotaFiscal .= "<br>{$nextDados->getNrNotafiscal()}";
// remove o index usado e pega o pŕoximo
unset($lista[key($lista)]);
$nextDados = current($lista);
};
echo '
<div class="large-12 columns">
<table>
<thead>
<tr>
<th>NrNFSe</th>
<th>OE</th>
<th>NotaFiscal</th>
</tr>
</thead>
<tbody>
<tr>
<td>'.$NrNFSe.'</td>
<td>'.$CdOE.'</td>
<td>'.$NrNotaFiscal.'</td>
</tr>
</tbody>
</table>
</div>
';
}
Obviously, I could not exactly test with your code, but by the logic should work. Before executing it is good to analyze the structure of your array and take care that it does not fall into an infinite loop during the tests (which can slow down the machine).
For this, you can use an internal counter inside the loop as security.
$i = 0;
while (!empty($lista) && $i < 100) {
$i++;
Do this on the other internal loop as well.