public function addBody($rows, callable $fn = null) {
        // last column will have TRUE for the TCPDF [ln] property
        end($this->columnDefinition);
        $this->columnDefinition[key($this->columnDefinition)]['ln'] = true;

        $auto_pb = $this->pdf->getAutoPageBreak();
        $bmargin = $this->pdf->getMargins()['bottom'];
        $this->pdf->SetAutoPageBreak(false, $this->bottomMargin);
        if ($this->trigger(self::EV_BODY_ADD, [$rows, $fn]) === false) {
            $this->trigger(self::EV_BODY_SKIPPED, [$rows]);
            $this->endBody($auto_pb, $bmargin);
            return $this;
        }
        if ($this->showHeader) {
            $this->addHeader();
        }
        foreach ($rows as $index => $row) {
            $data = $fn ? $fn($this, $row, $index, false) : $row;
            // draw row only if it's an array. It gives the possibility to skip
            // some rows with the user func
            if (is_array($data) || is_object($data)) {
                $this->addRow($data, $index);
            } else {
                $this->trigger(self::EV_ROW_SKIPPED, [$row, $index]);
            }
        }
        $this->trigger(self::EV_BODY_ADDED, [$rows]);
        $this->endBody($auto_pb, $bmargin);
        return $this;
    }