Search code examples
jqueryjsonasp.net-mvccsvjquery-csv

Acessing JQuery-CSV Object and formatting it into a txt file


I have an incoming txt/csv file containing a lot of information (58 columns), basically I will need to work on a few information (just name and telephone number). So I must be able get the whole information, retrieve what I need from it and then format it.

  • To get the whole information I used the terales answer which enables the file to be uploaded.
  • To work on the information I'm using this library JQuery-CSV, this will read the file content and turn it into a JSON Object, I'm stuck at this point. I have the object but I can't acess it as I need and hence I can't format it to write a new txt file.I may be missing something in the documentation, this should be really straight foward. Here's a sample of my code:

HTML

<link href="https://fonts.googleapis.com/css?family=Lato|Roboto|Source+Code+Pro" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/monokai.min.css">
<link rel="stylesheet" href="demo.css">

<div class="row" style="margin-bottom:8px;position:relative;">
    <h2>Contacts</h2>
    <div class="col-md-12">
        <label for="input-file">Select your file:</label><br>
        <input type="file" id="input-file">
        <input id="run" type="button" value="Format" />
    </div>
</div>


<textarea id="content-target"></textarea>
<textarea id="result"></textarea>

<script src="http://code.jquery.com/jquery-3.3.1.slim.js" integrity="sha256-fNXJFIlca05BIO2Y5zh1xrShK3ME+/lYZ0j+ChxX2DA=" crossorigin="anonymous"></script>
<script src="http://typeiii.github.io/jquery-csv/src/jquery.csv.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/highlight.min.js"></script>
<script src="jquery-csv.js"></script>

JS

<script>

    $("#content-target").hide();
    $("#result").hide();
    $("#run").hide();
    document.getElementById('input-file').addEventListener('change', getFile)

    function getFile(event) {
        const input = event.target
        if ('files' in input && input.files.length > 0) {
            placeFileContent(
                document.getElementById('content-target'),
                input.files[0])
            $("#run").show();
        }
    }

    function placeFileContent(target, file) {
        readFileContent(file).then(content => {
            target.value = content
        }).catch(error => console.log(error))
    }

    function readFileContent(file) {
        const reader = new FileReader()
        return new Promise((resolve, reject) => {
            reader.onload = event => resolve(event.target.result)
            reader.onerror = error => reject(error)
            reader.readAsText(file)
        })
    }

    // enable syntax highlighting
      hljs.initHighlightingOnLoad();

      $(document).ready(() => {
        parse();
      });

      $('#run').bind('click', function () {
          parse();
          //format();
      });

      function parse() {
        const input = $('#content-target').val();
        const data = $.csv.toObjects(input);
        $('#result').empty();
        //$('#result').html(JSON.stringify(data, null, 2));
        $("#result").show();
    };    

</script>

The format() function will acess specific indexes within the object (the ones I mentioned above Name and Telephone number) and perform a regex operation to format it. But as I said, I'm failing to acess these indexes, in my specific case, I thought that the syntax data[0].Name or anything like data[index].ColumnName generically speaking should have been fine.

Here is a small sample of my incoming data :

Name;Given Name;Additional Name;Family Name;Yomi Name;Given Name Yomi;Additional Name Yomi;Family Name Yomi;Name Prefix;Name Suffix;Initials;Nickname;Short Name;Maiden Name;Birthday;Gender;Location;Billing Information;Directory Server;Mileage;Occupation;Hobby;Sensitivity;Priority;Subject;Notes;Language;Photo;Group Membership;E-mail 1 - Type;E-mail 1 - Value;E-mail 2 - Type;E-mail 2 - Value;Phone 1 - Type;Phone 1 - Value;Phone 2 - Type;Phone 2 - Value;Phone 3 - Type;Phone 3 - Value;Address 1 - Type;Address 1 - Formatted;Address 1 - Street;Address 1 - City;Address 1 - PO Box;Address 1 - Region;Address 1 - Postal Code;Address 1 - Country;Address 1 - Extended Address;Organization 1 - Type;Organization 1 - Name;Organization 1 - Yomi Name;Organization 1 - Title;Organization 1 - Department;Organization 1 - Symbol;Organization 1 - Location;Organization 1 - Job Description;Website 1 - Type;Website 1 - Value
A1 Soluções;A1;;Soluções;;;;;;;;;;;;;;;;;;;;;;;;;* myContacts;;;;;Disp. móvel;8006009510;;;;;;;;;;;;;;;;;;;;;;;
Adelson;Adelson;;;;Adelson;;;;;;;;;;;;;;;;;;;;;;;* myContacts;;;;;Disp. móvel;027 99978-1045;;;;;;;;;;;;;;;Aluguel da Casa;;;;;;;;
Admilson;Admilson;;;;;;;;;;;;;;;;;;;;;;;;;;;* myContacts;;;;;Mobile;033 98888-1078;;;;;;;;;;;;;;;Paroquia Sagrado Coração de Jesus;;Bingo;;;;;;

Solution

  • You have some issues with asynchronous call. I fixed your code, because only when an asynchronous function ends (i.e.: fileReader.onload) you can go on:

    $("#content-target").hide();
    $("#result").hide();
    $("#run").hide();
    document.getElementById('input-file').addEventListener('change', getFile)
    
    function getFile(event) {
      const input = event.target
      if ('files' in input && input.files.length > 0) {
          var fileReader = new FileReader();
          fileReader.onload = function(fileLoadedEvent) {
              //
              //  only after you read the file you can go on with the data...
              //
              var textFromFileLoaded = fileLoadedEvent.target.result;
              $("#content-target").text(textFromFileLoaded).show();
              $("#run").show();
              parse();
          }
          fileReader.readAsText(input.files[0], "UTF-8");
      }
    }
    
    
    
    
     function parse() {
        const input = $('#content-target').text();
        const data = $.csv.toObjects(input, {"separator": ";"});
        $('#result tbody').empty();
        data.forEach(function (e) {
            // get arguments
            var name = e.Name;
            var phoneType = e['Phone 1 - Type'];
            var phoneValue = e['Phone 1 - Value'];
    
            // create a row and append to the table
            $('#result tbody').append($('<tr><td>' + name + '</td><td>' + phoneType + ' </td><td>' + phoneValue + '</td></tr>'));
    
        });
        $("#result").show();
    };
    table, th, td {
        border: 1px solid black;
        border-collapse: collapse;
        width: 33%;
    }
    table {
      width: 100%;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://typeiii.github.io/jquery-csv/src/jquery.csv.js"></script>
    <link href="https://fonts.googleapis.com/css?family=Lato|Roboto|Source+Code+Pro" rel="stylesheet">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/monokai.min.css">
    
    
    <div class="row" style="margin-bottom:8px;position:relative;">
        <h2>Contacts</h2>
    
        <div class="col-md-12">
            <label for="input-file">Select your file:</label><br>
            <input type="file" id="input-file">
            <input id="run" type="button" value="Format"/>
        </div>
    </div>
    <textarea id="content-target"></textarea>
    <table id="result">
        <thead>
        <tr>
            <th>name</th>
            <th>Phone Type</th>
            <th>Phone Value</th>
        </tr>
        </thead>
        <tbody>
    
        </tbody>
    </table>