Search code examples
javascriptarraysregexloopsexport-to-csv

export datas to csv using javascript to get a product sheet


i'm working in a programm using Javascript which can extract data into a csv file. What i've done so far is to create a blank text area where we can paste a text, then the programm looks for common values targeted and print out the result into a csv file. To be more specific, these values corresponds to features of a product and i've also targeted the next value from each of these features founded in the text pasted, to extract the feature with its result. My goal is to get in a csv file all the details from a feature product with a simple copy/paste instead of writing it each time.

Here is my code :

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <textarea id="toConvert" name="" id="" cols="30" rows="10"></textarea>
    <br>
    <button id="submit">Dowload CSV</button>
    
    <script>
        let textArea = document.getElementById('toConvert');
        let btn = document.getElementById('submit');

        btn.addEventListener('click', function(e){
            e.preventDefault();

            let stack = [];

            // features product
            var features = [
                "Matière", 
                "Hauteur",
                "Longueur",
                "Diamètre",
                "Profondeur",
                "Poids",
                "Couleur"
            ]

            textArea.select();
            document.execCommand("copy");
            let result = textArea.value;
            let isFounded = features.filter( item => result.includes(item) );
            let values = result.split(' ');
            for(let i = 0; i < values.length; i++){
                for(let j=0; j < isFounded.length; j++){
                    if(values[i] === isFounded[j]){
                        let rows = [
                            [isFounded[j], values[i+1]]
                        ];
                        
                        rows.forEach(function(rowArray){
                            let row = rowArray.join(',');
                            stack.push(row);
                        });
                        
                        var csvString = stack.join("\r\n");
                        var universalBOM    = "\uFEFF";
                        var a               = document.createElement('a');
                        a.setAttribute('href', 'data:text/csv; charset=utf-8,' + encodeURIComponent(universalBOM+csvString));
                        a.target            = '_blank';
                        a.download          = 'ficheProduit.csv';
                        document.body.appendChild(a);
                        a.click(); 
                        
                    }
                }
            }
        }, { once: true });
 
    </script>
</body>
</html>


The problems i've encountered are the following :

  • the programm only works if the text pasted looks like "Matière Métal Poids 300 Dimensions 500" and doesn't have line break between the words. I've been looking for a regexp expression to replace special characters but I can't find how to do this in my programm.
  • I only have succeeded to separate the feature from its result with a "," it gives me this :
Matière, Métal
Poids,300

but how could I make in a csv file a row with two columns instead of only one. I expect this output:

Matière | Métal
Poids   | 300 ..

I would like a lot to get some help, thank you in advance !!!


Solution

  • When I run your code, I can get only first item in the csv file. So, I updated the code for extracting the values.

    For creating csv file with equal space and "|" character, I don't see any library in javascript so far. So, the way that I used is finding maximum length of "features" word from "result" and add the spaces to each word to have the length is equal to max_length + 1.

    For example, if "Matière" is max_length which is 7, we will make each first word in csv as length 8 where remaining lengths are added with csv.

    Hope this is what you want :)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
    
        <textarea id="toConvert" name="" id="" cols="30" rows="10"></textarea>
        <br>
        <button id="submit">Dowload CSV</button>
        
        <script>
            let textArea = document.getElementById('toConvert');
            let btn = document.getElementById('submit');
    
            btn.addEventListener('click', function(e){
                e.preventDefault();
    
                let stack = [];
    
                // features product
                var features = [
                    "Matière", 
                    "Hauteur",
                    "Longueur",
                    "Diamètre",
                    "Profondeur",
                    "Poids",
                    "Couleur"
                ]
    
                textArea.select();
                document.execCommand("copy");
                let result = textArea.value;
                // ----------
                result = result.split(' ')
    
                // make the result list into boolean list as the item will be true if the word is included in the features
                condition_list = result.map(item => features.includes(item))
    
                // find the maximum length of feature word from result and add + 1 for extra space before "|" in max_length word
                max_length = features.filter( item => result.includes(item) ) // first filter the features words from result
                                    .reduce((acc, cur) => { // reduce the list into one maximum length element
                                        if (cur.length > acc.length) { 
                                            return cur
                                        } else {
                                            return acc
                                        }
                                    }, " ").length + 1
    
                // get pair of feature word from result
                var new_result = []
                let current_list = []
                result.forEach((item, index) => {
                    if(condition_list[index]){ // if it's feature word, we will capture in new list called current_list
                        current_list = []
                        current_list.push(item)
                    }else if(condition_list[index - 1]){ // if it's next value of feature word, we will append to current_list and push it to new_result
                        current_list.push(item)
                        new_result.push(current_list)
                    }
                })
                
                // convert to csv
                let csvContent = "data:text/csv;charset=utf-8,";
                new_result.forEach(row => {
                    let row_with_spaces = ""
                    row.forEach((item, index) => {
                        
                        if (index) { //index === 1 is second item
                            row_with_spaces += " " + item // if it's second item, just append one space before the item
                        } else{
                            row_with_spaces += item + " ".repeat(max_length - item.length) + "|" // if it's first item, fill remaining length with spaces and "|"
                        }
                    })
                    csvContent += row_with_spaces + "\r\n"; 
                });
    
                // download as csv
                const encodedUri = encodeURI(csvContent);
                const link = document.createElement("a");
                link.setAttribute("href", encodedUri);
                link.setAttribute("download", "ficheProduit11.csv");
                document.body.appendChild(link);
    
                link.click()
            }, { once: true });
     
        </script>
    </body>
    </html>
    

    Input: "Matière Métal Poids 300 Dimensions 500"

    Output:

    Matière | Métal
    Poids   | 300
    

    Input: "Matière Métal Poids 300 Diamètre 500"

    Output:

    Matière  | Métal
    Poids    | 300
    Diamètre | 500