Can a scheduled report be send as PDF?


the reports are working fantastic,
but the users here want to have them in PDF or excel
they dont like the email formatting …

I am sorry as per my knowledge we can’t specify the report format in the default REPORT module of SuiteCRM.
Please see this guide for all possiblities

You can purchase a paid plugin, Analytical Reporting. This plugin has this feature available. I can help you out to set this up.


@niraleeraval, how is this related to what this user was asking for? He doesn’t want to upload documents into the CRM, he wants to produce Documents from it - namely, Reports.

1 Like

Is there already a function in SuiteCRM that makes this possible, or do I have to build a Logic Hook if I want this function?

Which function do you mean, grabbing a report result and turning it into a PDF to send by email?

How would you do that in a logic hook? that’s quite a bit of code…

I wanted to create a Logic Hook that would be triggered when a value from a custom module changed. After the value changed, it will create a PDF document with a custom made PDF template, and after creation it will send an email with the PDF document as an attachment.

It was not that hard, you could use a lot of code from the classes “generatePdf.php” and “actionSendEmail.php”. If anyone is interested, I can share and explain my code.

1 Like

I’m actually looking to send a PDF by logic hook “relationship add” in Opportunities. That would be great if you’d share.

Okay, no problem!

  1. Create a Logic Hook for your module (path:/custom/Extension/modules/{module}/Ext/LogicHooks/logic_hooks.php).

  2. Create the action you want to trigger, in my case it was the ‘before_save’.

$hook_array['before_save'][] = array(
    //Processing index. For sorting the array.

    //Label. A string value to identify the hook.
    'Generate PDF and send as attachment',

    //The PHP file where your class is located.

    //The class the method is in.

    //The method to call.
  1. Create the file in the above written location (path:custom/Extension/modules/{module}/Ext/CustomFiles/test.php).

  2. Get the data from the record with a custom made PDF-template and send it to an emailaddress.


if (!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');

class testClass
    public function generatePdfDocument($bean, $event, $arguments)
        // Only send email if status is completed and mail not been sent yet.
        if ($bean->request_status == 'completed' && !$bean->mail_to_xxx_sent_c) {
            global $sugar_config;
            $errorLevelStored = error_reporting();

            $template = BeanFactory::newBean('AOS_PDF_Templates');
            $template->retrieve('25fc9bb3-ce3b-0f1d-ffa3-635fd12b69b6'); // Set Basecone PDF-template ID.

            $search = array('/<script[^>]*?>.*?<\/script>/si',      // Strip out javascript
                '/<[\/\!]*?[^<>]*?>/si',        // Strip out HTML tags
                '/([\r\n])[\s]+/',          // Strip out white space
                '/&(quot|#34);/i',          // Replace HTML entities

            $replace = array('', '', '\1', '"', '&', '<', '>', ' ', chr(161), '<br>', "'", 'chr(%1)');

            $header = preg_replace($search, $replace, $template->pdfheader);
            $footer = preg_replace($search, $replace, $template->pdffooter);
            $text = preg_replace($search, $replace, $template->description);
            $text = str_replace("<p><pagebreak /></p>", "<pagebreak />", $text);
            $text = preg_replace_callback(
                function ($matches) {
                    return date($matches[1]);

            $variableName = strtolower($bean->module_dir);
            $text = str_replace("\$aos_quotes", "\$" . $variableName, $text);
            $text = str_replace("\$aos_invoices", "\$" . $variableName, $text);
            $text = str_replace("\$total_amt", "\$" . $variableName . "_total_amt", $text);
            $text = str_replace("\$discount_amount", "\$" . $variableName . "_discount_amount", $text);
            $text = str_replace("\$subtotal_amount", "\$" . $variableName . "_subtotal_amount", $text);
            $text = str_replace("\$tax_amount", "\$" . $variableName . "_tax_amount", $text);
            $text = str_replace("\$shipping_amount", "\$" . $variableName . "_shipping_amount", $text);
            $text = str_replace("\$total_amount", "\$" . $variableName . "_total_amount", $text);

            $object_arr = array();
            $object_arr[$bean->module_dir] = $bean->id;
            $converted = templateParser::parse_template($text, $object_arr);
            $header = templateParser::parse_template($header, $object_arr);
            $footer = templateParser::parse_template($footer, $object_arr);

            $printable = str_replace("\n", "<br />", $converted);

            $file_name = date("Ymd") . "_" . str_replace(" ", "_", $bean->name) . ".pdf";

            try {
                $orientation = ($template->orientation == "Landscape") ? "-L" : "";
                $pdf = new mPDF('en', $template->page_size . $orientation, '', 'DejaVuSansCondensed', $template->margin_left, $template->margin_right, $template->margin_top, $template->margin_bottom, $template->margin_header, $template->margin_footer);
                $fp = fopen($sugar_config['upload_dir'] . 'attachfile.pdf', 'wb');
                $pdf->Output($sugar_config['upload_dir'] . 'attachfile.pdf', 'F');

                $this->sendEmail($bean, $file_name);
            } catch (mPDF_exception $e) {
                echo $e;

            $bean->mail_to_xxx_sent_c = true;

    private function sendEmail(SugarBean $relatedBean, $file_name)
        global $sugar_config;

        $emailTo = array('');
        $emailObj = BeanFactory::newBean('Emails');
        $defaults = $emailObj->getSystemDefaultEmail();
        $mail = new SugarPHPMailer();

        // set the id for relationship
        $emailObj->id = create_guid();
        $emailObj->new_with_id = true;

        $mail->From = $defaults['email'];
        $mail->FromName = $defaults['name'];
        $mail->Subject = from_html($relatedBean->name);
        $mail->Body = "This mail has data from project: '{$relatedBean->name}'.";
        $mail->AltBody = '';

        foreach ($emailTo as $to) {

        // Create the note (attachment)
        $note = BeanFactory::newBean('Notes');
        $note->id = create_guid();
        $note->new_with_id = true;
        $note->name = 'PDF document: ' . $relatedBean->name;
        $note->parent_type = 'Emails';
        $note->parent_id = $emailObj->id;
        $note->file_mime_type = 'application/pdf';
        $note->filename = $file_name;
        $noteId = $note->save();

        if (!empty($noteId)) {
            rename($sugar_config['upload_dir'] . 'attachfile.pdf', $sugar_config['upload_dir'] . $note->id);
        } else {
            $GLOBALS['log']->error('AOS_PDF_Templates: Unable to save note');

        // Add the attachment to the mail

        //now create email
        if ($mail->Send()) {
            $emailObj->to_addrs = implode(',', $emailTo);
            $emailObj->type = 'out';
            $emailObj->deleted = '0';
            $emailObj->name = $mail->Subject;
            $emailObj->description = $mail->AltBody;
            $emailObj->description_html = $mail->Body;
            $emailObj->from_addr = $mail->From;
            if ($relatedBean instanceof SugarBean && !empty($relatedBean->id)) {
                $emailObj->parent_type = $relatedBean->module_dir;
                $emailObj->parent_id = $relatedBean->id;
            $emailObj->date_sent_received = TimeDate::getInstance()->nowDb();
            $emailObj->modified_user_id = '1';
            $emailObj->created_by = '1';
            $emailObj->status = 'sent';

Good luck!


Nice! Thank you. I’m going to study and try and implement your solution. Thanks so much for that.