[PATCH] Bad CSV export on Reports module #9

Open
opened 2026-02-20 14:13:44 -05:00 by deekerman · 17 comments
Owner

Originally created by @lsmonki on GitHub (Mar 6, 2014).

Originally assigned to: @mattlorimer on GitHub.

The csv export do not escapes quotes ("), do not support new lines on field content, and can't be oppened without problems on excel. Also the http headers do not set the filename ok.

Here is a patch for the build_report_csv function on modules/AOR_Reports/AOR_Report.php

    function build_report_csv(){

        ini_set('zlib.output_compression', 'Off');

        ob_start();
        require_once('include/export_utils.php');

        $delimiter = getDelimiter();
        //text/comma-separated-values

        $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
        if ($GLOBALS['locale']->getExportCharset() == 'UTF-8' &&
            ! preg_match('/macintosh|mac os x|mac_powerpc/i', $user_agent)) // Bug 60377 - Mac Excel doesn't support UTF-8
        {
            //Bug 55520 - add BOM to the exporting CSV so any symbols are displayed correctly in Excel
            $BOM = "\xEF\xBB\xBF";
            $csv = $BOM;
        }
        else
        {
            $csv = '';
        }

        $sql = "SELECT id FROM aor_fields WHERE aor_report_id = '".$this->id."' AND deleted = 0 ORDER BY field_order ASC";
        $result = $this->db->query($sql);

        $fields = array();
        $i = 0;
        $first_item = true;
        while ($row = $this->db->fetchByAssoc($result)) {
            $field = new AOR_Field();
            $field->retrieve($row['id']);

            $path = unserialize(base64_decode($field->module_path));

            $field_module = $this->report_module;
            if($path[0] != $this->report_module){
                foreach($path as $rel){
                    $field_module = getRelatedModule($field_module,$rel);
                }
            }
            $label = str_replace(' ','_',$field->label).$i;
            $fields[$label]['field'] = $field->field;
            $fields[$label]['display'] = $field->display;
            $fields[$label]['function'] = $field->field_function;
            $fields[$label]['module'] = $field_module;


            if($field->display){
                if(!$first_item)
                    $csv .= $delimiter;
                else
                    $first_item = false;

                $csv.= '"'.preg_replace("/\"/","\"\"", $field->label).'"';
            }
            ++$i;
        }

        $sql = $this->build_report_query();
        $result = $this->db->query($sql);

        while ($row = $this->db->fetchByAssoc($result)) {
            $csv .= "\r\n";
            $first_item = true;
            foreach($fields as $name => $att){
                if($att['display']){
                    if(!$first_item)
                        $csv .= $delimiter;
                    else
                        $first_item = false;

                    if($att['function'] != '' )
                        $csv .= '"'.preg_replace("/\"/","\"\"", $row[$name]).'"';
                    else
                        $csv .= '"'.preg_replace("/\"/","\"\"", trim(strip_tags(getModuleField($att['module'], $att['field'], $att['field'], 'DetailView',$row[$name])))).'"';
                }
            }
        }

        $csv= $GLOBALS['locale']->translateCharset($csv, 'UTF-8', $GLOBALS['locale']->getExportCharset());

        ob_clean();
        header("Pragma: cache");
        header("Content-type: text/comma-separated-values; charset=".$GLOBALS['locale']->getExportCharset());
        header("Content-Disposition: attachment; filename=\"{$this->name}.csv\"");
        header("Content-transfer-encoding: binary");
        header("Expires: Mon, 26 Jul 1997 05:00:00 GMT" );
        header("Last-Modified: " . TimeDate::httpTime() );
        header("Cache-Control: post-check=0, pre-check=0", false );
        header("Content-Length: ".mb_strlen($csv, '8bit'));

        print $csv;

        sugar_cleanup(true);
    }
Originally created by @lsmonki on GitHub (Mar 6, 2014). Originally assigned to: @mattlorimer on GitHub. The csv export do not escapes quotes ("), do not support new lines on field content, and can't be oppened without problems on excel. Also the http headers do not set the filename ok. Here is a patch for the `build_report_csv` function on `modules/AOR_Reports/AOR_Report.php` ``` function build_report_csv(){ ini_set('zlib.output_compression', 'Off'); ob_start(); require_once('include/export_utils.php'); $delimiter = getDelimiter(); //text/comma-separated-values $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; if ($GLOBALS['locale']->getExportCharset() == 'UTF-8' && ! preg_match('/macintosh|mac os x|mac_powerpc/i', $user_agent)) // Bug 60377 - Mac Excel doesn't support UTF-8 { //Bug 55520 - add BOM to the exporting CSV so any symbols are displayed correctly in Excel $BOM = "\xEF\xBB\xBF"; $csv = $BOM; } else { $csv = ''; } $sql = "SELECT id FROM aor_fields WHERE aor_report_id = '".$this->id."' AND deleted = 0 ORDER BY field_order ASC"; $result = $this->db->query($sql); $fields = array(); $i = 0; $first_item = true; while ($row = $this->db->fetchByAssoc($result)) { $field = new AOR_Field(); $field->retrieve($row['id']); $path = unserialize(base64_decode($field->module_path)); $field_module = $this->report_module; if($path[0] != $this->report_module){ foreach($path as $rel){ $field_module = getRelatedModule($field_module,$rel); } } $label = str_replace(' ','_',$field->label).$i; $fields[$label]['field'] = $field->field; $fields[$label]['display'] = $field->display; $fields[$label]['function'] = $field->field_function; $fields[$label]['module'] = $field_module; if($field->display){ if(!$first_item) $csv .= $delimiter; else $first_item = false; $csv.= '"'.preg_replace("/\"/","\"\"", $field->label).'"'; } ++$i; } $sql = $this->build_report_query(); $result = $this->db->query($sql); while ($row = $this->db->fetchByAssoc($result)) { $csv .= "\r\n"; $first_item = true; foreach($fields as $name => $att){ if($att['display']){ if(!$first_item) $csv .= $delimiter; else $first_item = false; if($att['function'] != '' ) $csv .= '"'.preg_replace("/\"/","\"\"", $row[$name]).'"'; else $csv .= '"'.preg_replace("/\"/","\"\"", trim(strip_tags(getModuleField($att['module'], $att['field'], $att['field'], 'DetailView',$row[$name])))).'"'; } } } $csv= $GLOBALS['locale']->translateCharset($csv, 'UTF-8', $GLOBALS['locale']->getExportCharset()); ob_clean(); header("Pragma: cache"); header("Content-type: text/comma-separated-values; charset=".$GLOBALS['locale']->getExportCharset()); header("Content-Disposition: attachment; filename=\"{$this->name}.csv\""); header("Content-transfer-encoding: binary"); header("Expires: Mon, 26 Jul 1997 05:00:00 GMT" ); header("Last-Modified: " . TimeDate::httpTime() ); header("Cache-Control: post-check=0, pre-check=0", false ); header("Content-Length: ".mb_strlen($csv, '8bit')); print $csv; sugar_cleanup(true); } ```
Author
Owner

@ghost commented on GitHub (May 19, 2014):

Thank you for this patch! It worked flawlessly to fix my issue with fields "shifting" on my CSV exports.

@ghost commented on GitHub (May 19, 2014): Thank you for this patch! It worked flawlessly to fix my issue with fields "shifting" on my CSV exports.
Author
Owner

@iYianni commented on GitHub (Jul 2, 2015):

Is this included in the latest release of SuiteCRM?

@iYianni commented on GitHub (Jul 2, 2015): Is this included in the latest release of SuiteCRM?
Author
Owner

@darthtang commented on GitHub (Jul 30, 2015):

Sorry. This patch hasnt been added ye,

However, i have replaced the old function with this new patch function and it still doesn't seem to work.

I am using a new version of suite 7.2.2, and considering this patch was long ago, maybe something has broken in the process of a new version being used

@iYianni , have you also tried to replace the old function with the new function?

@darthtang commented on GitHub (Jul 30, 2015): Sorry. This patch hasnt been added ye, However, i have replaced the old function with this new patch function and it still doesn't seem to work. I am using a new version of suite 7.2.2, and considering this patch was long ago, maybe something has broken in the process of a new version being used @iYianni , have you also tried to replace the old function with the new function?
Author
Owner

@iYianni commented on GitHub (Jul 30, 2015):

@darthtang Yes, I replaced the code from version 7.1.2 and it works fine. Having looked at the code in the latest release, an attempt has been made to resolve the issues. Though, I haven't actually tested it.

What issues are you experiencing?

@iYianni commented on GitHub (Jul 30, 2015): @darthtang Yes, I replaced the code from version 7.1.2 and it works fine. Having looked at the code in the latest release, an attempt has been made to resolve the issues. Though, I haven't actually tested it. What issues are you experiencing?
Author
Owner

@darthtang commented on GitHub (Jul 30, 2015):

Hi @iYianni

So the latest release has the new change? i am looking at the master branch now of suite and cannot see the change.

The issues i am experiencing are that the quotes are still not escaped i get """ in the csv file when i export my report

@darthtang commented on GitHub (Jul 30, 2015): Hi @iYianni So the latest release has the new change? i am looking at the master branch now of suite and cannot see the change. The issues i am experiencing are that the quotes are still not escaped i get """ in the csv file when i export my report
Author
Owner

@iYianni commented on GitHub (Jul 30, 2015):

It's not the same code as above, but the latest release looks like it is attempting to deal with (at least some of) these issues. As we're not using it yet, and without testing it, I won't be able to tell for sure, sorry. Have you check with @willrennie or @lsmonki for help with the latest release?

@iYianni commented on GitHub (Jul 30, 2015): It's not the same code as above, but the latest release looks like it is attempting to deal with (at least some of) these issues. As we're not using it yet, and without testing it, I won't be able to tell for sure, sorry. Have you check with @willrennie or @lsmonki for help with the latest release?
Author
Owner

@darthtang commented on GitHub (Jul 30, 2015):

@lsmonki

What were the errors before you added the changes into Suite? I know it was a long time ago when you posted this so no worries if you cant remember!

Cheers

Darren

@darthtang commented on GitHub (Jul 30, 2015): @lsmonki What were the errors before you added the changes into Suite? I know it was a long time ago when you posted this so no worries if you cant remember! Cheers Darren
Author
Owner

@lsmonki commented on GitHub (Jul 30, 2015):

Some problems are described here: http://stackoverflow.com/questions/1241220/generating-csv-file-for-excel-how-to-have-a-newline-inside-a-value

First, you need to add the BOM to allow excell open it and get new lines on fields:

        $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
        if ($GLOBALS['locale']->getExportCharset() == 'UTF-8' &&
            ! preg_match('/macintosh|mac os x|mac_powerpc/i', $user_agent)) // Bug 60377 - Mac Excel doesn't support UTF-8
        {
            //Bug 55520 - add BOM to the exporting CSV so any symbols are displayed correctly in Excel
            $BOM = "\xEF\xBB\xBF";
            $csv = $BOM;
        }
        else
        {
            $csv = '';
        }

NOTE: The code was copied from SugarCRM, the bug numbers are from their issues list.

Now there is a problem, the last field names and values for each row has an end delimiter and it shouldn't (do it on field names and field values):

        $first_item = true;
        while ($row = $this->db->fetchByAssoc($result)) {
            ...
            ...
            if($field->display){
                if(!$first_item)
                    $csv .= $delimiter;
                else
                    $first_item = false;

                $csv.= $this->encloseForCSV($field->label);
            }
            ...
            ...
        while ($row = $this->db->fetchByAssoc($result)) {
            $csv .= "\r\n";
            $first_item = true;
            foreach($fields as $name => $att){
                if($att['display']){
                    if(!$first_item)
                        $csv .= $delimiter;
                    else
                        $first_item = false;

                    if($att['function'] != '' )
                        $csv .= $this->encloseForCSV($row[$name]);
                    else
                        $csv .= $this->encloseForCSV(trim(strip_tags(getModuleField($att['module'], $att['field'], $att['field'], 'DetailView',$row[$name]))));
                }
            }
        }
        ...
        ...        

Now you need to scape quotes and fix new lines, in the new code you can modify the encloseForCSV function

    private function encloseForCSV($field){
        //Replace \r\n with \n only, \r\n is the row delimiter
        $field = str_replace("\r\n", "\n", $field);
        return '"'.preg_replace("/\"/","\"\"", $field).'"';
    }

And in the new code I see an error, if you are going to modify the csv content, modify it before setting the headers, the length could change:

        // Modify before set headers
        if (!empty($sugar_config['export_excel_compatible'])) {
            $csv==chr(255) . chr(254) . mb_convert_encoding($csv, 'UTF-16LE', 'UTF-8');
        }

       ob_clean();
        header("Pragma: cache");
        header("Content-type: text/comma-separated-values; charset=".$GLOBALS['locale']->getExportCharset());
        header("Content-Disposition: attachment; filename={$this->name}.csv");
        header("Content-transfer-encoding: binary");
        header("Expires: Mon, 26 Jul 1997 05:00:00 GMT" );
        header("Last-Modified: " . TimeDate::httpTime() );
        header("Cache-Control: post-check=0, pre-check=0", false );
        header("Content-Length: ".mb_strlen($csv, '8bit'));


        print $csv;

NOTE: I have not tested it :)

@lsmonki commented on GitHub (Jul 30, 2015): Some problems are described here: http://stackoverflow.com/questions/1241220/generating-csv-file-for-excel-how-to-have-a-newline-inside-a-value First, you need to add the BOM to allow excell open it and get new lines on fields: ``` php $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; if ($GLOBALS['locale']->getExportCharset() == 'UTF-8' && ! preg_match('/macintosh|mac os x|mac_powerpc/i', $user_agent)) // Bug 60377 - Mac Excel doesn't support UTF-8 { //Bug 55520 - add BOM to the exporting CSV so any symbols are displayed correctly in Excel $BOM = "\xEF\xBB\xBF"; $csv = $BOM; } else { $csv = ''; } ``` NOTE: The code was copied from SugarCRM, the bug numbers are from their issues list. Now there is a problem, the last field names and values for each row has an end delimiter and it shouldn't (do it on field names and field values): ``` php $first_item = true; while ($row = $this->db->fetchByAssoc($result)) { ... ... if($field->display){ if(!$first_item) $csv .= $delimiter; else $first_item = false; $csv.= $this->encloseForCSV($field->label); } ... ... while ($row = $this->db->fetchByAssoc($result)) { $csv .= "\r\n"; $first_item = true; foreach($fields as $name => $att){ if($att['display']){ if(!$first_item) $csv .= $delimiter; else $first_item = false; if($att['function'] != '' ) $csv .= $this->encloseForCSV($row[$name]); else $csv .= $this->encloseForCSV(trim(strip_tags(getModuleField($att['module'], $att['field'], $att['field'], 'DetailView',$row[$name])))); } } } ... ... ``` Now you need to scape quotes and fix new lines, in the new code you can modify the encloseForCSV function ``` php private function encloseForCSV($field){ //Replace \r\n with \n only, \r\n is the row delimiter $field = str_replace("\r\n", "\n", $field); return '"'.preg_replace("/\"/","\"\"", $field).'"'; } ``` And in the new code I see an error, if you are going to modify the csv content, modify it before setting the headers, the length could change: ``` php // Modify before set headers if (!empty($sugar_config['export_excel_compatible'])) { $csv==chr(255) . chr(254) . mb_convert_encoding($csv, 'UTF-16LE', 'UTF-8'); } ob_clean(); header("Pragma: cache"); header("Content-type: text/comma-separated-values; charset=".$GLOBALS['locale']->getExportCharset()); header("Content-Disposition: attachment; filename={$this->name}.csv"); header("Content-transfer-encoding: binary"); header("Expires: Mon, 26 Jul 1997 05:00:00 GMT" ); header("Last-Modified: " . TimeDate::httpTime() ); header("Cache-Control: post-check=0, pre-check=0", false ); header("Content-Length: ".mb_strlen($csv, '8bit')); print $csv; ``` NOTE: I have not tested it :)
Author
Owner

@lsmonki commented on GitHub (Jul 30, 2015):

Other error, the double equal sign must be a single equal:

        // Modify before set headers
        if (!empty($sugar_config['export_excel_compatible'])) {
            $csv=/*<--- SINGLE EQUAL HERE*/ chr(255) . chr(254) . mb_convert_encoding($csv, 'UTF-16LE', 'UTF-8');
        }
@lsmonki commented on GitHub (Jul 30, 2015): Other error, the double equal sign must be a single equal: ``` php // Modify before set headers if (!empty($sugar_config['export_excel_compatible'])) { $csv=/*<--- SINGLE EQUAL HERE*/ chr(255) . chr(254) . mb_convert_encoding($csv, 'UTF-16LE', 'UTF-8'); } ```
Author
Owner

@samus-aran commented on GitHub (Apr 1, 2017):

Ok @lsmonki Revisiting the past.

Looking at the now 7.8.x code I can see the following points.

Content adjusted before length header set:
This has been resolved in the later versions.
https://github.com/salesagility/SuiteCRM/blob/master/export.php#L92

Double equal sign must be a single equal: https://github.com/salesagility/SuiteCRM/issues/18#issuecomment-126304976
Not quite sure what this is referring to as it has always been a single equal sign.
https://github.com/salesagility/SuiteCRM/blob/master/export.php#L92

The delimiter at the end of each column has been raised as a separate bug:
https://github.com/salesagility/SuiteCRM/issues/3275

Seems the only remaining bit is that the build_report_csv does not contain the $BOM reference though calling the export_utils.php
I would deem this as a bug as if it already contains this on the export of other CSV it really should in Reports.

@samus-aran commented on GitHub (Apr 1, 2017): Ok @lsmonki Revisiting the past. Looking at the now 7.8.x code I can see the following points. Content adjusted before length header set: This has been resolved in the later versions. https://github.com/salesagility/SuiteCRM/blob/master/export.php#L92 Double equal sign must be a single equal: https://github.com/salesagility/SuiteCRM/issues/18#issuecomment-126304976 Not quite sure what this is referring to as it has always been a single equal sign. https://github.com/salesagility/SuiteCRM/blob/master/export.php#L92 The delimiter at the end of each column has been raised as a separate bug: https://github.com/salesagility/SuiteCRM/issues/3275 Seems the only remaining bit is that the build_report_csv does not contain the $BOM reference though calling the export_utils.php I would deem this as a bug as if it already contains this on the export of other CSV it really should in Reports.
Author
Owner

@ghost commented on GitHub (Apr 27, 2017):

Guys, I know you are working hard, but a three (* yes, 3! *) years old BUG/issue should have been taken care of by now... I am expriencing the same problem for years and my users complained again about this today...

we know that themes are important but not as important as normal functionalities to my opinion...

@ghost commented on GitHub (Apr 27, 2017): Guys, I know you are working hard, but a three (* yes, 3! *) years old BUG/issue should have been taken care of by now... I am expriencing the same problem for years and my users complained again about this today... we know that themes are important but not as important as normal functionalities to my opinion...
Author
Owner

@Mac-Rae commented on GitHub (Jul 26, 2019):

Confirmed in latest 7.10.x

@Mac-Rae commented on GitHub (Jul 26, 2019): Confirmed in latest 7.10.x
Author
Owner

@gunnicom commented on GitHub (Sep 27, 2019):

Still issues with double quotes " in csv exports on 7.11.7

@gunnicom commented on GitHub (Sep 27, 2019): Still issues with double quotes " in csv exports on 7.11.7
Author
Owner

@pgorod commented on GitHub (Sep 27, 2019):

Maybe this PR will help for this Issue here?

#7580

I'm not sure it does, though, I didn't examine the code, it just looks related...

@pgorod commented on GitHub (Sep 27, 2019): Maybe this PR will help for this Issue here? #7580 I'm not sure it does, though, I didn't examine the code, it just looks related...
Author
Owner

@gunnicom commented on GitHub (Sep 30, 2019):

@pgorod That seems to be encoding related.
Double quotes is definitly a different thing, as they need to be escaped somehow.

@gunnicom commented on GitHub (Sep 30, 2019): @pgorod That seems to be encoding related. Double quotes is definitly a different thing, as they need to be escaped somehow.
Author
Owner

@carlos-cumplisoft commented on GitHub (May 14, 2025):

I also have encountered problems using export on windows systems and trying to open csv in excel, but in my solution (SuiteCRM 7.11.18), I have to do only small changes. I think maybe, in combination with @lsmonki solution, we could get a better solution.

The problem as far as I know is not only on printCSV on include/export_utils.php, we also have to make changes to file include/Localization/Localization.php.

I added a new charset to $availableCharsets array, 'Windows-1251', this give me the chance of could set on any user profile this charset on exporting, and also could be the default by configuration (for those who use windows).

So the new code on Localization array should be:

    public $availableCharsets = array(
        'BIG-5',        //Taiwan and Hong Kong
        /*'CP866'			  // ms-dos Cyrillic */
        /*'CP949'			  //Microsoft Korean */
        'CP1251',       //MS Cyrillic
        'CP1252',       //MS Western European & US
        'EUC-CN',       //Simplified Chinese GB2312
        'EUC-JP',       //Unix Japanese
        'EUC-KR',       //Korean
        'EUC-TW',       //Taiwanese
        'ISO-2022-JP',  //Japanese
        'ISO-2022-KR',  //Korean
        'ISO-8859-1',   //Western European and US
        'ISO-8859-2',   //Central and Eastern European
        'ISO-8859-3',   //Latin 3
        'ISO-8859-4',   //Latin 4
        'ISO-8859-5',   //Cyrillic
        'ISO-8859-6',   //Arabic
        'ISO-8859-7',   //Greek
        'ISO-8859-8',   //Hebrew
        'ISO-8859-9',   //Latin 5
        'ISO-8859-10',  //Latin 6
        'ISO-8859-13',  //Latin 7
        'ISO-8859-14',  //Latin 8
        'ISO-8859-15',  //Latin 9
        'KOI8-R',       //Cyrillic Russian
        'KOI8-U',       //Cyrillic Ukranian
        'SJIS',         //MS Japanese
        'UTF-8',        //UTF-8
        'UTF-16LE',     //UTF-16LE
        'WINDOWS-1252', // Windows Latin 1
    );

and also iconvCharsetMap array shoud be:

    public $iconvCharsetMap = array(
        'KS_C_5601-1987' => 'CP949',
        'ISO-8859-8-I' => 'ISO-8859-8',
        'WINDOWS-1252' => 'WINDOWS-1252//IGNORE' // IGNORE means that any unknown character will be omitted.
    );

In my case I only have to make an slightly modification to call Localization->translateCharset on file include/export_utils.php change function printCSV:

Change the line

        $data = $locale->translateCharset($csv, 'UTF-8', $charset);

for this one:

        $data = $locale->translateCharset($csv, 'UTF-8', $charset, isset($locale->iconvCharsetMap[$charset]));

Note that, I didn't need to force excel compatibility (This is an option on config.php file).

In my case I need a language charset on windows that use Windows1252, but other people could be need other one.

Also note, if you look inside translateCharset function, the function mb_list_encodings, give the list of system available character codes, so with this, I think you need only to know if you have Windows1252 on this list on your system and add it to availableCharsets, with this you will don't need to change printCSV, and maybe the best solution should be to load available charsets on configuration / user profile, instead of using a hardcoded one, because in my system the harcoded array one is only a small subset of available ones. Also, I think that if you chose a harcoded one that really isn't in your system, it will fail.

@carlos-cumplisoft commented on GitHub (May 14, 2025): I also have encountered problems using export on windows systems and trying to open csv in excel, but in my solution (SuiteCRM 7.11.18), I have to do only small changes. I think maybe, in combination with @lsmonki solution, we could get a better solution. The problem as far as I know is not only on printCSV on include/export_utils.php, we also have to make changes to file include/Localization/Localization.php. I added a new charset to $availableCharsets array, 'Windows-1251', this give me the chance of could set on any user profile this charset on exporting, and also could be the default by configuration (for those who use windows). So the new code on Localization array should be: ```php public $availableCharsets = array( 'BIG-5', //Taiwan and Hong Kong /*'CP866' // ms-dos Cyrillic */ /*'CP949' //Microsoft Korean */ 'CP1251', //MS Cyrillic 'CP1252', //MS Western European & US 'EUC-CN', //Simplified Chinese GB2312 'EUC-JP', //Unix Japanese 'EUC-KR', //Korean 'EUC-TW', //Taiwanese 'ISO-2022-JP', //Japanese 'ISO-2022-KR', //Korean 'ISO-8859-1', //Western European and US 'ISO-8859-2', //Central and Eastern European 'ISO-8859-3', //Latin 3 'ISO-8859-4', //Latin 4 'ISO-8859-5', //Cyrillic 'ISO-8859-6', //Arabic 'ISO-8859-7', //Greek 'ISO-8859-8', //Hebrew 'ISO-8859-9', //Latin 5 'ISO-8859-10', //Latin 6 'ISO-8859-13', //Latin 7 'ISO-8859-14', //Latin 8 'ISO-8859-15', //Latin 9 'KOI8-R', //Cyrillic Russian 'KOI8-U', //Cyrillic Ukranian 'SJIS', //MS Japanese 'UTF-8', //UTF-8 'UTF-16LE', //UTF-16LE 'WINDOWS-1252', // Windows Latin 1 ); ``` and also iconvCharsetMap array shoud be: ```php public $iconvCharsetMap = array( 'KS_C_5601-1987' => 'CP949', 'ISO-8859-8-I' => 'ISO-8859-8', 'WINDOWS-1252' => 'WINDOWS-1252//IGNORE' // IGNORE means that any unknown character will be omitted. ); ``` In my case I only have to make an slightly modification to call Localization->translateCharset on file include/export_utils.php change function printCSV: Change the line ```php $data = $locale->translateCharset($csv, 'UTF-8', $charset); ``` for this one: ```php $data = $locale->translateCharset($csv, 'UTF-8', $charset, isset($locale->iconvCharsetMap[$charset])); ``` Note that, I didn't need to force excel compatibility (This is an option on config.php file). In my case I need a language charset on windows that use Windows1252, but other people could be need other one. Also note, if you look inside translateCharset function, the function mb_list_encodings, give the list of system available character codes, so with this, I think you need only to know if you have Windows1252 on this list on your system and add it to availableCharsets, with this you will don't need to change printCSV, and maybe the best solution should be to load available charsets on configuration / user profile, instead of using a hardcoded one, because in my system the harcoded array one is only a small subset of available ones. Also, I think that if you chose a harcoded one that really isn't in your system, it will fail.
Author
Owner

@carlos-cumplisoft commented on GitHub (May 14, 2025):

I tested my last words on my comment, and this is an alternative solution that also works.

With this solution you only have to add a line in include/Localization/Localization.php file. change the constructor from:

    /**
     * sole constructor
     */
    public function __construct()
    {
        global $sugar_config;
        $this->localeNameFormatDefault = empty($sugar_config['locale_name_format_default']) ? 's f l' : $sugar_config['default_name_format'];
        $this->loadCurrencies();
    }

to

    /**
     * sole constructor
     */
    public function __construct()
    {
        global $sugar_config;
        $this->localeNameFormatDefault = empty($sugar_config['locale_name_format_default']) ? 's f l' : $sugar_config['default_name_format'];
        $this->loadCurrencies();

        $this->availableCharsets = mb_list_encodings(); // Overriding harcoded character set with system character set
    }

And after this change, you only have to select, in my case, windows-1252 character set. The csv generated will be opened without problems on windows with double click.

May be also we can merge harcoded array with system one but I think is better take it from system.

I hope this will help!

@carlos-cumplisoft commented on GitHub (May 14, 2025): I tested my last words on my comment, and this is an alternative solution that also works. With this solution you only have to add a line in include/Localization/Localization.php file. change the constructor from: ```php /** * sole constructor */ public function __construct() { global $sugar_config; $this->localeNameFormatDefault = empty($sugar_config['locale_name_format_default']) ? 's f l' : $sugar_config['default_name_format']; $this->loadCurrencies(); } ``` to ```php /** * sole constructor */ public function __construct() { global $sugar_config; $this->localeNameFormatDefault = empty($sugar_config['locale_name_format_default']) ? 's f l' : $sugar_config['default_name_format']; $this->loadCurrencies(); $this->availableCharsets = mb_list_encodings(); // Overriding harcoded character set with system character set } ``` And after this change, you only have to select, in my case, windows-1252 character set. The csv generated will be opened without problems on windows with double click. May be also we can merge harcoded array with system one but I think is better take it from system. I hope this will help!
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/SuiteCRM-SuiteCRM#9
No description provided.