0

I have an issue where I'm trying to export html table to a csv file. The issue is that no download box appears but I know my JS function is run via an alert check.

I wonder if it can be my table that is generated from an exiting csv file like this:

  echo "<table>\n\n";
  $f = fopen("../translations/EXAMPLE.csv", "r");
  while (($line = fgetcsv($f)) !== false) {
        echo "<tr>";
        foreach ($line as $cell) {
                echo "<td contenteditable>" . htmlspecialchars($cell) . "</td>";
        }
        echo "</tr>\n";
  }
  fclose($f);
  echo "\n</table>";

I have a button to call the javascript:

<button class='saveCSV' style='float:right;'>Save</button>

And here is the javascript file:

$(document).ready(function () {

    function exportTableToCSV($table, filename) {

        var $rows = $table.find('tr:has(td)'),

            // Temporary delimiter characters unlikely to be typed by keyboard
            // This is to avoid accidentally splitting the actual contents
            tmpColDelim = String.fromCharCode(11), // vertical tab character
            tmpRowDelim = String.fromCharCode(0), // null character

            // actual delimiter characters for CSV format
            colDelim = '","',
            rowDelim = '"\r\n"',

            // Grab text from table into CSV formatted string
            csv = '"' + $rows.map(function (i, row) {
                var $row = $(row),
                    $cols = $row.find('td');

                return $cols.map(function (j, col) {
                    var $col = $(col),
                        text = $col.text();

                    return text.replace(/"/g, '""'); // escape double quotes

                }).get().join(tmpColDelim);

            }).get().join(tmpRowDelim)
                .split(tmpRowDelim).join(rowDelim)
                .split(tmpColDelim).join(colDelim) + '"',

            // Data URI
            csvData = 'data:application/csv;charset=utf-8,' + encodeURIComponent(csv);

        $(this)
            .attr({
            'download': filename,
                'href': csvData,
                'target': '_blank'
        });
                alert("KØRT");
    }

    // This must be a hyperlink
    $(".saveCSV").on('click', function (event) {
        // CSV
        exportTableToCSV.apply(this, [$('#dvData>table'), 'export.csv']);

        // IF CSV, don't do event.preventDefault() or return false
        // We actually need this to be a typical hyperlink
    });
});

Anyone having an idea to what os wrong here and the csv file is not exported?

Troels Johannesen
  • 725
  • 2
  • 7
  • 30
  • Are there any errors in the console? – shennan Sep 02 '15 at 10:18
  • Does `console.log(csv)` (before the csvData line) produce anything? My point is: at what point is the script failing. Does it give you your CSV data, but just doesn't offer it as a 'download'? – shennan Sep 02 '15 at 10:21
  • If I apply console.log(csv) right after csvData line I get the table as csv in the console. Before the csvData line i get nothing. – Troels Johannesen Sep 02 '15 at 10:25
  • @shennan - So I get the csv in console.log but how can it not download or sent the popup message ? – Troels Johannesen Sep 02 '15 at 10:33
  • Possible duplicate of [Export to CSV using jQuery and html](https://stackoverflow.com/questions/16078544/export-to-csv-using-jquery-and-html) – Dave Jarvis Apr 21 '18 at 00:55

2 Answers2

0

Have you tried removing the encodeURIComponent method? With some initial testing, I found this to break functionality. So your code may look something like this instead:

var csvData = 'data:application/csv;charset=utf-8,' + csv;

Here's an example of this in action.

Remember also, that what you're attempting to do won't work in every browser as the download attribute is not universally supported. See here for more about support.

shennan
  • 10,798
  • 5
  • 44
  • 79
0

Simply convert the csvData to a blob file or base64 file and then send to the server using ajax. Take note of the two functions added after the document.ready.

    $(document).ready(function () {
    function dataURItoBlob(dataURI) {
        // convert base64/URLEncoded data component to raw binary data held in a string
        var byteString;
        if (dataURI.split(',')[0].indexOf('base64') >= 0)
            byteString = atob(dataURI.split(',')[1]);
        else
            byteString = unescape(dataURI.split(',')[1]);

        // separate out the mime component
        var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

        // write the bytes of the string to a typed array
        var ia = new Uint8Array(byteString.length);
        for (var i = 0; i < byteString.length; i++) {
            ia[i] = byteString.charCodeAt(i);
        }

        return new Blob([ia], {type:mimeString});
    }

function uploadCSV( blob ) {
  var reader = new FileReader();
  reader.onload = function(event){
    var fd = {};
    fd["fname"] = "example.csv";
    fd["data"] = event.target.result;
    $.ajax({
      type: 'POST',
      url: 'upload.php',
      data: fd,
      dataType: 'text'
    }).done(function(data) {
        console.log(data);
    });
  };
  reader.readAsDataURL(blob);
}
        function exportTableToCSV($table, filename) {

            var $rows = $table.find('tr:has(td)'),

                // Temporary delimiter characters unlikely to be typed by keyboard
                // This is to avoid accidentally splitting the actual contents
                tmpColDelim = String.fromCharCode(11), // vertical tab character
                tmpRowDelim = String.fromCharCode(0), // null character

                // actual delimiter characters for CSV format
                colDelim = '","',
                rowDelim = '"\r\n"',

                // Grab text from table into CSV formatted string
                csv = '"' + $rows.map(function (i, row) {
                    var $row = $(row),
                        $cols = $row.find('td');

                    return $cols.map(function (j, col) {
                        var $col = $(col),
                            text = $col.text();

                        return text.replace(/"/g, '""'); // escape double quotes

                    }).get().join(tmpColDelim);

                }).get().join(tmpRowDelim)
                    .split(tmpRowDelim).join(rowDelim)
                    .split(tmpColDelim).join(colDelim) + '"',

                // Data URI
                csvData = 'data:application/csv;charset=utf-8,' + encodeURIComponent(csv);

            var asblob = dataURItoBlob(csvData);
            uploadCSV( asblob ); //prepare and send via ajax post. The ajax post is not tested though

        }

        // This must be a hyperlink
        $(".saveCSV").on('click', function (event) {
            // CSV
            exportTableToCSV.apply(this, [$('#dvData>table'), 'export.csv']);

            // IF CSV, don't do event.preventDefault() or return false
            // We actually need this to be a typical hyperlink
        });
    });

PHP CODE should be

<?
// pull the raw binary data from the POST array
$data = substr($_POST['data'], strpos($_POST['data'], ",") + 1);
// decode it
$decodedData = base64_decode($data);
// print out the raw data,
$filename = $_POST['fname'];
echo $filename;
// write the data out to the file
$fp = fopen($filename, 'wb');
fwrite($fp, $decodedData);
fclose($fp);
?>

OR

Blob blob = *// get Blob file *
byte [] bytes = blob.getBytes(1, (int) blob.length());
Bitmap bmp = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
String filePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Testing/";
File dir = new File(filePath);
File file = new File(dir, "filename.csv");
FileOutputStream fOut = new FileOutputStream(file);
//bmp.compress(Bitmap.CompressFormat.PNG, 85, fOut);
fOut.flush();
fOut.close(); 
Ifeanyi Chukwu
  • 3,187
  • 3
  • 28
  • 32